VirtualBox

Changeset 28206 in vbox


Ignore:
Timestamp:
Apr 12, 2010 1:48:49 PM (15 years ago)
Author:
vboxsync
Message:

Guest Control: Update (first code for low level HGCM callback).

Location:
trunk
Files:
4 edited

Legend:

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

    r28186 r28206  
    4949* Typedefs, constants and inlines                                             *
    5050******************************************************************************/
     51
     52/**
     53 * Data structure to pass to the service extension callback.  We use this to
     54 * notify the host of changes to properties.
     55 */
     56typedef struct _HOSTCALLBACKDATA
     57{
     58    /** Magic number to identify the structure */
     59    uint32_t u32Magic;
     60   
     61} HOSTCALLBACKDATA, *PHOSTCALLBACKDATA;
     62
     63enum
     64{
     65    /** Magic number for sanity checking the HOSTCALLBACKDATA structure */
     66    HOSTCALLBACKMAGIC = 0x26011982
     67};
    5168
    5269/**
  • trunk/src/VBox/HostServices/GuestControl/service.cpp

    r28180 r28206  
    242242    int clientConnect(uint32_t u32ClientID, void *pvClient);
    243243    int clientDisconnect(uint32_t u32ClientID, void *pvClient);
    244     int guestGetHostMsg(VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    245     int hostNotifyGuest(GuestCall *pCall, uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    246     int hostProcessCmd(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
     244    int processHostMsg(VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
     245    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[]);
     247    int processCmd(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    247248    void call(VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID,
    248249              void *pvClient, uint32_t eFunction, uint32_t cParms,
     
    405406 * defer the guest call until we have something from the host.
    406407 */
    407 int Service::guestGetHostMsg(VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
     408int Service::processHostMsg(VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
    408409{
    409410    int rc = VINF_SUCCESS;
     
    411412    if (cParms < 2)
    412413    {
    413         LogFlowFunc(("Parameter buffer is too small!\n"));
     414        LogFlowFunc(("Guest parameter buffer is too small!\n"));
    414415        rc = VERR_INVALID_PARAMETER;
    415416    }
    416417    else
    417     {
     418    {   
    418419        /*
    419420         * If host command list is empty (nothing to do right now) just
     
    473474 * order to wake up and do some work.
    474475 */
    475 int Service::hostNotifyGuest(GuestCall *pCall, uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
     476int Service::notifyGuest(GuestCall *pCall, uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
    476477{
    477478    AssertPtr(pCall);
    478479    int rc = VINF_SUCCESS;
    479480
    480     int rc2 = guestGetHostMsg(pCall->mHandle, pCall->mNumParms, pCall->mParms);
     481    int rc2 = processHostMsg(pCall->mHandle, pCall->mNumParms, pCall->mParms);
    481482    if (RT_SUCCESS(rc2))
    482483        rc2 = pCall->mRc;
     
    486487}
    487488
    488 int Service::hostProcessCmd(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
    489 {
    490     int rc = VINF_SUCCESS;
    491 
    492     /* Some lazy guests to wake up? */
     489int Service::notifyHost(VBOXHGCMCALLHANDLE callHandle, uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
     490{
     491    LogFlowFunc (("eFunction=%ld, cParms=%ld, paParms=%p\n",
     492                  eFunction, cParms, paParms));
     493    HOSTCALLBACKDATA HostCallbackData;
     494    HostCallbackData.u32Magic = HOSTCALLBACKMAGIC;
     495
     496    int rc = mpfnHostCallback (mpvHostData, 0 /*u32Function*/,
     497                           (void *)(&HostCallbackData),
     498                           sizeof(HostCallbackData));
     499    LogFlowFunc (("returning %Rrc\n", rc));
     500    return rc;
     501}
     502
     503int Service::processCmd(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
     504{
     505    int rc = VINF_SUCCESS;
     506
     507    /* Some lazy guests to wake up which can process this command right now? */
    493508    if (!mGuestWaiters.empty())
    494509    {
    495510        GuestCall curCall = mGuestWaiters.front();
    496         rc = hostNotifyGuest(&curCall, eFunction, cParms, paParms);
     511        rc = notifyGuest(&curCall, eFunction, cParms, paParms);
    497512        mGuestWaiters.pop_front();
    498513    }
     
    539554            case GUEST_GET_HOST_MSG:
    540555                LogFlowFunc(("GUEST_GET_HOST_MSG\n"));
    541                 rc = guestGetHostMsg(callHandle, cParms, paParms);
     556                rc = processHostMsg(callHandle, cParms, paParms);
    542557                break;
    543558
     
    555570            case GUEST_EXEC_SEND_STATUS:
    556571                LogFlowFunc(("SEND_STATUS\n"));
     572                rc = notifyHost(callHandle, eFunction, cParms, paParms);
    557573                break;
    558574
     
    596612            case HOST_EXEC_CMD:
    597613                LogFlowFunc(("HOST_EXEC_CMD\n"));
    598                 rc = hostProcessCmd(eFunction, cParms, paParms);
     614                rc = processCmd(eFunction, cParms, paParms);
    599615                break;
    600616
  • trunk/src/VBox/Main/GuestImpl.cpp

    r28132 r28206  
    3636# include <VBox/HostServices/GuestControlSvc.h>
    3737# include <VBox/com/array.h>
     38# include <hgcm/HGCM.h>
    3839#endif
    3940#include <iprt/cpp/utils.h>
     
    435436    return rc;
    436437}
     438
     439// static
     440DECLCALLBACK(int) Guest::doGuestCtrlNotification(void *pvExtension,
     441                                                 uint32_t u32Function,
     442                                                 void *pvParms,
     443                                                 uint32_t cbParms)
     444{
     445    using namespace guestControl;
     446
     447    /*
     448     * No locking, as this is purely a notification which does not make any
     449     * changes to the object state.
     450     */
     451    PHOSTCALLBACKDATA pCBData = reinterpret_cast<PHOSTCALLBACKDATA>(pvParms);
     452    AssertReturn(sizeof(HOSTCALLBACKDATA) == cbParms, VERR_INVALID_PARAMETER);
     453    AssertReturn(HOSTCALLBACKMAGIC == pCBData->u32Magic, VERR_INVALID_PARAMETER);
     454    LogFlowFunc(("pvExtension = %p, u32Function = %d, pvParms = %p, cbParms = %d\n",
     455                 pvExtension, u32Function, pvParms, cbParms));
     456
     457    int rc = VINF_SUCCESS;
     458    Guest *pGuest = static_cast <Guest *>(pvExtension);
     459
     460    switch (u32Function)
     461    {       
     462        default:
     463            rc = VERR_NOT_SUPPORTED;
     464            break;
     465    }
     466
     467    ASMAtomicWriteBool(&pGuest->mSignalled, true);
     468    return rc;
     469}
    437470#endif /* VBOX_WITH_GUEST_CONTROL */
    438471
     
    477510
    478511        /*
    479          * Prepare process execution.
     512         * Register the host notification callback
    480513         */
    481         int vrc = VINF_SUCCESS;
    482         Utf8Str Utf8Command(aCommand);
    483 
    484         /* Prepare arguments. */       
    485         com::SafeArray<IN_BSTR> args(ComSafeArrayInArg(aArguments));
    486         uint32_t uNumArgs = args.size();
    487         char **papszArgv = NULL;
    488         if(uNumArgs > 0)
    489         {
    490             papszArgv = (char**)RTMemAlloc(sizeof(char*) * (uNumArgs + 1));
    491             AssertPtr(papszArgv);
    492             for (unsigned i = 0; RT_SUCCESS(vrc) && i < uNumArgs; i++)
    493                 vrc = RTStrAPrintf(&papszArgv[i], "%s", Utf8Str(args[i]).raw());
    494             papszArgv[uNumArgs] = NULL;
    495         }
    496 
     514        HGCMSVCEXTHANDLE hExt;
     515        int vrc = HGCMHostRegisterServiceExtension(&hExt, "VBoxGuestCtrlSvc",
     516                                                   &Guest::doGuestCtrlNotification,
     517                                                   this);
    497518        if (RT_SUCCESS(vrc))
    498519        {
    499             char *pszArgs = NULL;
    500             if (uNumArgs > 0)
    501                 vrc = RTGetOptArgvToString(&pszArgs, papszArgv, 0);         
     520            /*
     521             * Prepare process execution.
     522             */
     523            Utf8Str Utf8Command(aCommand);
     524   
     525            /* Prepare arguments. */       
     526            com::SafeArray<IN_BSTR> args(ComSafeArrayInArg(aArguments));
     527            uint32_t uNumArgs = args.size();
     528            char **papszArgv = NULL;
     529            if(uNumArgs > 0)
     530            {
     531                papszArgv = (char**)RTMemAlloc(sizeof(char*) * (uNumArgs + 1));
     532                AssertPtr(papszArgv);
     533                for (unsigned i = 0; RT_SUCCESS(vrc) && i < uNumArgs; i++)
     534                    vrc = RTStrAPrintf(&papszArgv[i], "%s", Utf8Str(args[i]).raw());
     535                papszArgv[uNumArgs] = NULL;
     536            }
     537   
    502538            if (RT_SUCCESS(vrc))
    503539            {
    504                 uint32_t cbArgs = pszArgs ? strlen(pszArgs) + 1 : 0; /* Include terminating zero. */
    505 
    506                 /* Prepare environment. */
    507                 com::SafeArray<IN_BSTR> env(ComSafeArrayInArg(aEnvironment));
    508    
    509                 void *pvEnv = NULL;
    510                 uint32_t uNumEnv = 0;
    511                 uint32_t cbEnv = 0;
    512    
    513                 for (unsigned i = 0; i < env.size(); i++)
    514                 {
    515                     vrc = prepareExecuteEnv(Utf8Str(env[i]).raw(), &pvEnv, &cbEnv, &uNumEnv);
    516                     if (RT_FAILURE(vrc))
    517                         break;
    518                 }
    519    
     540                char *pszArgs = NULL;
     541                if (uNumArgs > 0)
     542                    vrc = RTGetOptArgvToString(&pszArgs, papszArgv, 0);         
    520543                if (RT_SUCCESS(vrc))
    521544                {
    522                     Utf8Str Utf8StdIn(aStdIn);
    523                     Utf8Str Utf8StdOut(aStdOut);
    524                     Utf8Str Utf8StdErr(aStdErr);
    525                     Utf8Str Utf8UserName(aUserName);
    526                     Utf8Str Utf8Password(aPassword);
    527                
    528                     VBOXHGCMSVCPARM paParms[14];
    529                     int i = 0;
    530                     paParms[i++].setPointer((void*)Utf8Command.raw(), (uint32_t)strlen(Utf8Command.raw()) + 1);
    531                     paParms[i++].setUInt32(aFlags);
    532                     paParms[i++].setUInt32(uNumArgs);
    533                     paParms[i++].setPointer((void*)pszArgs, cbArgs);
    534                     paParms[i++].setUInt32(uNumEnv);
    535                     paParms[i++].setUInt32(cbEnv);
    536                     paParms[i++].setPointer((void*)pvEnv, cbEnv);
    537                     paParms[i++].setPointer((void*)Utf8StdIn.raw(), (uint32_t)strlen(Utf8StdIn.raw()) + 1);
    538                     paParms[i++].setPointer((void*)Utf8StdOut.raw(), (uint32_t)strlen(Utf8StdOut.raw()) + 1);
    539                     paParms[i++].setPointer((void*)Utf8StdErr.raw(), (uint32_t)strlen(Utf8StdErr.raw()) + 1);
    540                     paParms[i++].setPointer((void*)Utf8UserName.raw(), (uint32_t)strlen(Utf8UserName.raw()) + 1);
    541                     paParms[i++].setPointer((void*)Utf8Password.raw(), (uint32_t)strlen(Utf8Password.raw()) + 1);
    542                     paParms[i++].setUInt32(aTimeoutMS);
     545                    uint32_t cbArgs = pszArgs ? strlen(pszArgs) + 1 : 0; /* Include terminating zero. */
    543546   
    544                     /* Forward the information to the VMM device. */
    545                     AssertPtr(mParent);
    546                     VMMDev *vmmDev = mParent->getVMMDev();
    547                     if (vmmDev)
     547                    /* Prepare environment. */
     548                    com::SafeArray<IN_BSTR> env(ComSafeArrayInArg(aEnvironment));
     549       
     550                    void *pvEnv = NULL;
     551                    uint32_t uNumEnv = 0;
     552                    uint32_t cbEnv = 0;
     553       
     554                    for (unsigned i = 0; i < env.size(); i++)
    548555                    {
    549                         LogFlow(("Guest::ExecuteProgram: numParms=%d\n", i));
    550                         vrc = vmmDev->hgcmHostCall("VBoxGuestControlSvc", HOST_EXEC_CMD,
    551                                                    i, paParms);
    552                         /** @todo Get the PID. */
     556                        vrc = prepareExecuteEnv(Utf8Str(env[i]).raw(), &pvEnv, &cbEnv, &uNumEnv);
     557                        if (RT_FAILURE(vrc))
     558                            break;
    553559                    }
    554                     RTMemFree(pvEnv);
     560       
     561                    if (RT_SUCCESS(vrc))
     562                    {
     563                        Utf8Str Utf8StdIn(aStdIn);
     564                        Utf8Str Utf8StdOut(aStdOut);
     565                        Utf8Str Utf8StdErr(aStdErr);
     566                        Utf8Str Utf8UserName(aUserName);
     567                        Utf8Str Utf8Password(aPassword);
     568                   
     569                        VBOXHGCMSVCPARM paParms[14];
     570                        int i = 0;
     571                        paParms[i++].setPointer((void*)Utf8Command.raw(), (uint32_t)strlen(Utf8Command.raw()) + 1);
     572                        paParms[i++].setUInt32(aFlags);
     573                        paParms[i++].setUInt32(uNumArgs);
     574                        paParms[i++].setPointer((void*)pszArgs, cbArgs);
     575                        paParms[i++].setUInt32(uNumEnv);
     576                        paParms[i++].setUInt32(cbEnv);
     577                        paParms[i++].setPointer((void*)pvEnv, cbEnv);
     578                        paParms[i++].setPointer((void*)Utf8StdIn.raw(), (uint32_t)strlen(Utf8StdIn.raw()) + 1);
     579                        paParms[i++].setPointer((void*)Utf8StdOut.raw(), (uint32_t)strlen(Utf8StdOut.raw()) + 1);
     580                        paParms[i++].setPointer((void*)Utf8StdErr.raw(), (uint32_t)strlen(Utf8StdErr.raw()) + 1);
     581                        paParms[i++].setPointer((void*)Utf8UserName.raw(), (uint32_t)strlen(Utf8UserName.raw()) + 1);
     582                        paParms[i++].setPointer((void*)Utf8Password.raw(), (uint32_t)strlen(Utf8Password.raw()) + 1);
     583                        paParms[i++].setUInt32(aTimeoutMS);
     584       
     585                        /* Forward the information to the VMM device. */
     586                        AssertPtr(mParent);
     587                        VMMDev *vmmDev = mParent->getVMMDev();
     588                        if (vmmDev)
     589                        {
     590                            LogFlow(("Guest::ExecuteProgram: numParms=%d\n", i));
     591                            vrc = vmmDev->hgcmHostCall("VBoxGuestControlSvc", HOST_EXEC_CMD,
     592                                                       i, paParms);
     593                            /** @todo Get the PID. */
     594                        }
     595                        RTMemFree(pvEnv);
     596                    }
     597                    RTStrFree(pszArgs);
    555598                }
    556                 RTStrFree(pszArgs);
     599                if (RT_SUCCESS(vrc))
     600                {
     601                    /* Wait for the HGCM low level callback */
     602                    mSignalled = false;
     603                    uint64_t u64Started = RTTimeMilliTS();
     604                    do
     605                    {
     606                        unsigned cMsWait;
     607                        if (aTimeoutMS == RT_INDEFINITE_WAIT)
     608                            cMsWait = 1000;
     609                        else
     610                        {
     611                            uint64_t cMsElapsed = RTTimeMilliTS() - u64Started;
     612                            if (cMsElapsed >= aTimeoutMS)
     613                                break; /* timed out */
     614                            cMsWait = RT_MIN(1000, aTimeoutMS - (uint32_t)cMsElapsed);
     615                        }
     616                    } while (!mSignalled);
     617#if 0
     618                    progress.queryInterfaceTo(aProgress);
     619#endif
     620                }
     621                else
     622                    rc = setError(E_UNEXPECTED,
     623                                  tr("The service call failed with the error %Rrc"),
     624                                  vrc);
     625   
     626                for (unsigned i = 0; i < uNumArgs; i++)
     627                    RTMemFree(papszArgv[i]);
     628                RTMemFree(papszArgv);
    557629            }
    558             if (RT_SUCCESS(vrc))
    559             {
    560 #if 0
    561                 progress.queryInterfaceTo(aProgress);
    562 #endif
    563                 rc = S_OK;
    564             }
    565             else
    566                 rc = setError(E_UNEXPECTED,
    567                               tr("The service call failed with the error %Rrc"),
    568                               vrc);
    569 
    570             for (unsigned i = 0; i < uNumArgs; i++)
    571                 RTMemFree(papszArgv[i]);
    572             RTMemFree(papszArgv);
     630            /* Unregister HGCM extension */
     631            HGCMHostUnregisterServiceExtension(hExt);
    573632        }
    574633    }
     
    576635    {
    577636        rc = E_OUTOFMEMORY;
    578     };
    579 
     637    }
    580638    return rc;
    581639#endif /* VBOX_WITH_GUEST_CONTROL */
  • trunk/src/VBox/Main/include/GuestImpl.h

    r28036 r28206  
    107107
    108108# ifdef VBOX_WITH_GUEST_CONTROL
    109     int prepareExecuteArgs(const char *pszArgs, void **ppvList,
    110                            uint32_t *pcbList, uint32_t *pcArgs);
    111 
    112     int prepareExecuteEnv(const char *pszEnv, void **ppvList,
    113                           uint32_t *pcbList, uint32_t *pcEnv);
     109    int prepareExecuteArgs(const char *pszArgs, void **ppvList, uint32_t *pcbList, uint32_t *pcArgs);
     110    int prepareExecuteEnv(const char *pszEnv, void **ppvList, uint32_t *pcbList, uint32_t *pcEnv);
     111    /** Static callback for handling guest notifications. */
     112    static DECLCALLBACK(int) doGuestCtrlNotification(void *pvExtension, uint32_t u32Function, void *pvParms, uint32_t cbParms);
    114113# endif
    115114
     
    132131    Console *mParent;
    133132    Data mData;
     133    bool mSignalled;
    134134};
    135135
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