VirtualBox

Changeset 14258 in vbox for trunk


Ignore:
Timestamp:
Nov 17, 2008 5:05:09 PM (16 years ago)
Author:
vboxsync
Message:

FE/VBoxManage: added support for guest property notifications

Location:
trunk/src/VBox/Frontends/VBoxManage
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp

    r14178 r14258  
    7676typedef DECLCALLBACK(int) FNHANDLER(int argc, char *argv[], ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession);
    7777typedef FNHANDLER *PFNHANDLER;
     78
     79#ifdef USE_XPCOM_QUEUE
     80/** A pointer to the event queue, set by main() before calling any handlers. */
     81nsCOMPtr<nsIEventQueue> g_pEventQ;
     82#endif
    7883
    7984/**
     
    84988503     * after the session is closed) */
    84998504
    8500     EventQueue eventQ;
     8505#ifdef USE_XPCOM_QUEUE
     8506    NS_GetMainEventQ(getter_AddRefs(g_pEventQ));
     8507#endif
    85018508
    85028509    if (!checkForAutoConvertedSettings (virtualBox, session, fConvertSettings))
     
    85758582    session->Close();
    85768583
     8584#ifdef USE_XPCOM_QUEUE
     8585    g_pEventQ->ProcessPendingEvents();
     8586#endif
     8587
    85778588    // end "all-stuff" scope
    85788589    ////////////////////////////////////////////////////////////////////////////
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManage.h

    r13908 r14258  
    2626#include <VBox/com/ptr.h>
    2727#include <VBox/com/VirtualBox.h>
     28#include <VBox/com/EventQueue.h>
    2829#endif /* !VBOX_ONLY_DOCS */
    2930
    3031#include <iprt/types.h>
     32
     33#if defined(VBOX_WITH_XPCOM) && !defined(RT_OS_DARWIN) && !defined(RT_OS_OS2)
     34# define USE_XPCOM_QUEUE
     35#endif
    3136
    3237/** @name Syntax diagram category.
     
    8792extern bool g_fInternalMode;
    8893
     94#ifndef VBOX_ONLY_DOCS
     95/** A pointer to the event queue, set by main() before calling any handlers. */
     96extern nsCOMPtr<nsIEventQueue> g_pEventQ;
     97#endif /* !VBOX_ONLY_DOCS */
     98
    8999/** showVMInfo details */
    90100typedef enum
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestProp.cpp

    r13294 r14258  
    2525*******************************************************************************/
    2626
     27#if defined(VBOX_WITH_XPCOM) && !defined(RT_OS_DARWIN) && !defined(RT_OS_OS2)
     28# define USE_XPCOM_QUEUE
     29#endif
     30
     31#include "VBoxManage.h"
     32
    2733#include <VBox/com/com.h>
    2834#include <VBox/com/string.h>
    2935#include <VBox/com/array.h>
    3036#include <VBox/com/ErrorInfo.h>
    31 
    3237#include <VBox/com/VirtualBox.h>
    3338
     39#include <VBox/log.h>
    3440#include <iprt/stream.h>
    35 #include <VBox/log.h>
    36 
    37 #include "VBoxManage.h"
     41#include <iprt/thread.h>
     42#include <iprt/time.h>
     43
     44#ifdef USE_XPCOM_QUEUE
     45# include <sys/select.h>
     46#endif
    3847
    3948using namespace com;
     49
     50class GuestPropertyCallback : public IVirtualBoxCallback
     51{
     52public:
     53    GuestPropertyCallback(const char *pszPatterns, Guid aUuid)
     54        : mSignalled(false), mPatterns(pszPatterns), mUuid(aUuid)
     55    {
     56#if defined (RT_OS_WINDOWS)
     57        refcnt = 0;
     58#endif
     59    }
     60
     61    virtual ~GuestPropertyCallback() {}
     62
     63#ifdef RT_OS_WINDOWS
     64    STDMETHOD_(ULONG, AddRef)()
     65    {
     66        return ::InterlockedIncrement(&refcnt);
     67    }
     68    STDMETHOD_(ULONG, Release)()
     69    {
     70        long cnt = ::InterlockedDecrement(&refcnt);
     71        if (cnt == 0)
     72            delete this;
     73        return cnt;
     74    }
     75    STDMETHOD(QueryInterface)(REFIID riid , void **ppObj)
     76    {
     77        if (riid == IID_IUnknown)
     78        {
     79            *ppObj = this;
     80            AddRef();
     81            return S_OK;
     82        }
     83        if (riid == IID_IVirtualBoxCallback)
     84        {
     85            *ppObj = this;
     86            AddRef();
     87            return S_OK;
     88        }
     89        *ppObj = NULL;
     90        return E_NOINTERFACE;
     91    }
     92#endif
     93
     94    NS_DECL_ISUPPORTS
     95
     96    STDMETHOD(OnMachineStateChange)(INPTR GUIDPARAM machineId,
     97                                    MachineState_T state)
     98    {
     99        return S_OK;
     100    }
     101
     102    STDMETHOD(OnMachineDataChange)(INPTR GUIDPARAM machineId)
     103    {
     104        return S_OK;
     105    }
     106
     107    STDMETHOD(OnExtraDataCanChange)(INPTR GUIDPARAM machineId, INPTR BSTR key,
     108                                    INPTR BSTR value, BSTR *error,
     109                                    BOOL *changeAllowed)
     110    {
     111        /* we never disagree */
     112        if (!changeAllowed)
     113            return E_INVALIDARG;
     114        *changeAllowed = TRUE;
     115        return S_OK;
     116    }
     117
     118    STDMETHOD(OnExtraDataChange)(INPTR GUIDPARAM machineId, INPTR BSTR key,
     119                                 INPTR BSTR value)
     120    {
     121        return S_OK;
     122    }
     123
     124    STDMETHOD(OnMediaRegistered) (INPTR GUIDPARAM mediaId,
     125                                  DeviceType_T mediaType, BOOL registered)
     126    {
     127        NOREF (mediaId);
     128        NOREF (mediaType);
     129        NOREF (registered);
     130        return S_OK;
     131    }
     132
     133    STDMETHOD(OnMachineRegistered)(INPTR GUIDPARAM machineId, BOOL registered)
     134    {
     135        return S_OK;
     136    }
     137
     138     STDMETHOD(OnSessionStateChange)(INPTR GUIDPARAM machineId,
     139                                    SessionState_T state)
     140    {
     141        return S_OK;
     142    }
     143
     144    STDMETHOD(OnSnapshotTaken) (INPTR GUIDPARAM aMachineId,
     145                                INPTR GUIDPARAM aSnapshotId)
     146    {
     147        return S_OK;
     148    }
     149
     150    STDMETHOD(OnSnapshotDiscarded) (INPTR GUIDPARAM aMachineId,
     151                                    INPTR GUIDPARAM aSnapshotId)
     152    {
     153        return S_OK;
     154    }
     155
     156    STDMETHOD(OnSnapshotChange) (INPTR GUIDPARAM aMachineId,
     157                                 INPTR GUIDPARAM aSnapshotId)
     158    {
     159        return S_OK;
     160    }
     161
     162    STDMETHOD(OnGuestPropertyChange)(INPTR GUIDPARAM machineId,
     163                                     INPTR BSTR name, INPTR BSTR value,
     164                                     INPTR BSTR flags)
     165    {
     166        int rc = S_OK;
     167        Utf8Str utf8Name (name);
     168        Guid uuid(machineId);
     169        if (utf8Name.isNull())
     170            rc = E_OUTOFMEMORY;
     171        if (   SUCCEEDED (rc)
     172            && uuid == mUuid
     173            && RTStrSimplePatternMultiMatch (mPatterns, RTSTR_MAX,
     174                                             utf8Name.raw(), RTSTR_MAX, NULL))
     175        {
     176            RTPrintf ("Name: %lS, value: %lS, flags: %lS\n", name, value,
     177                      flags);
     178            mSignalled = true;
     179        }
     180        return rc;
     181    }
     182
     183    bool Signalled(void) { return mSignalled; }
     184
     185private:
     186    bool mSignalled;
     187    const char *mPatterns;
     188    Guid mUuid;
     189#ifdef RT_OS_WINDOWS
     190    long refcnt;
     191#endif
     192
     193};
     194
     195#ifdef VBOX_WITH_XPCOM
     196NS_DECL_CLASSINFO(GuestPropertyCallback)
     197NS_IMPL_ISUPPORTS1_CI(GuestPropertyCallback, IVirtualBoxCallback)
     198#endif /* VBOX_WITH_XPCOM */
    40199
    41200void usageGuestProperty(void)
     
    49208    RTPrintf("VBoxManage guestproperty    enumerate <vmname>|<uuid>\n"
    50209             "                            [-patterns <patterns>]\n"
     210             "\n");
     211    RTPrintf("VBoxManage guestproperty    wait <vmname>|<uuid> <patterns>\n"
     212             "                            [--timeout <timeout>]\n"
    51213             "\n");
    52214}
     
    240402
    241403/**
     404 * Enumerates the properties in the guest property store.
     405 *
     406 * @returns 0 on success, 1 on failure
     407 * @note see the command line API description for parameters
     408 */
     409static int handleWaitGuestProperty(int argc, char *argv[],
     410                                   ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession)
     411{
     412
     413/*
     414 * Handle arguments
     415 */
     416    const char *pszPatterns = NULL;
     417    uint32_t u32Timeout = RT_INDEFINITE_WAIT;
     418    bool usageOK = true;
     419    if (argc < 2)
     420        usageOK = false;
     421    else
     422        pszPatterns = argv[1];
     423    ComPtr<IMachine> machine;
     424    /* assume it's a UUID */
     425    HRESULT rc = aVirtualBox->GetMachine(Guid(argv[0]), machine.asOutParam());
     426    if (FAILED(rc) || !machine)
     427    {
     428        /* must be a name */
     429        CHECK_ERROR(aVirtualBox, FindMachine(Bstr(argv[0]), machine.asOutParam()));
     430    }
     431    if (!machine)
     432        usageOK = false;
     433    for (int i = 2; usageOK && i < argc; ++i)
     434    {
     435        if (strcmp(argv[i], "-timeout") == 0)
     436        {
     437            if (   i + 1 >= argc
     438                || RTStrToUInt32Full(argv[i + 1], 10, &u32Timeout)
     439                       != VINF_SUCCESS
     440               )
     441                usageOK = false;
     442            else
     443                ++i;
     444        }
     445        else
     446            usageOK = false;
     447    }
     448    if (!usageOK)
     449        return errorSyntax(USAGE_GUESTPROPERTY, "Incorrect parameters");
     450
     451/*
     452 * Set up the callback and wait.
     453 */
     454    Guid uuid;
     455    machine->COMGETTER(Id)(uuid.asOutParam());
     456    GuestPropertyCallback *callback = new GuestPropertyCallback(pszPatterns, uuid);
     457    callback->AddRef();
     458    aVirtualBox->RegisterCallback (callback);
     459    bool stop = false;
     460#ifdef USE_XPCOM_QUEUE
     461    int max_fd = g_pEventQ->GetEventQueueSelectFD();
     462#endif
     463    for (; !stop && u32Timeout > 0; u32Timeout -= RT_MIN(u32Timeout, 1000))
     464    {
     465#ifdef USE_XPCOM_QUEUE
     466        int prc;
     467        fd_set fdset;
     468        struct timeval tv;
     469        FD_ZERO (&fdset);
     470        FD_SET(max_fd, &fdset);
     471        tv.tv_sec = RT_MIN(u32Timeout, 1000);
     472        tv.tv_usec = u32Timeout > 1000 ? 0 : u32Timeout * 1000;
     473        RTTIMESPEC TimeNow;
     474        uint64_t u64Time = RTTimeSpecGetMilli(RTTimeNow(&TimeNow));
     475        prc = select(max_fd + 1, &fdset, NULL, NULL, &tv);
     476        if (prc == -1)
     477        {
     478            RTPrintf("Error waiting for event.\n");
     479            stop = true;
     480        }
     481        else if (prc != 0)
     482        {
     483            uint64_t u64NextTime = RTTimeSpecGetMilli(RTTimeNow(&TimeNow));
     484            u32Timeout += (uint32_t)(u64Time + 1000 - u64NextTime);
     485            g_pEventQ->ProcessPendingEvents();
     486            if (callback->Signalled())
     487                stop = true;
     488        }
     489#else
     490        /** @todo Use a semaphore.  But I currently don't have a Windows system
     491         * running to test on. */
     492        RTThreadSleep(RT_MIN(1000, u32Timeout));
     493        if (callback->Signalled())
     494            stop = true;
     495#endif /* USE_XPCOM_QUEUE */
     496    }
     497
     498/*
     499 * Clean up the callback.
     500 */
     501    aVirtualBox->UnregisterCallback (callback);
     502    if (!callback->Signalled())
     503        RTPrintf("Time out or interruption while waiting for a notification.\n");
     504    callback->Release ();
     505
     506/*
     507 * Done.
     508 */
     509    return 0;
     510}
     511
     512/**
    242513 * Access the guest property store.
    243514 *
     
    256527    else if (0 == strcmp(argv[0], "enumerate"))
    257528        return handleEnumGuestProperty(argc - 1, argv + 1, aVirtualBox, aSession);
     529    else if (0 == strcmp(argv[0], "wait"))
     530        return handleWaitGuestProperty(argc - 1, argv + 1, aVirtualBox, aSession);
    258531    /* else */
    259532    return errorSyntax(USAGE_GUESTPROPERTY, "Incorrect parameters");
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