Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp	(revision 14257)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp	(revision 14258)
@@ -76,4 +76,9 @@
 typedef DECLCALLBACK(int) FNHANDLER(int argc, char *argv[], ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession);
 typedef FNHANDLER *PFNHANDLER;
+
+#ifdef USE_XPCOM_QUEUE
+/** A pointer to the event queue, set by main() before calling any handlers. */
+nsCOMPtr<nsIEventQueue> g_pEventQ;
+#endif
 
 /**
@@ -8498,5 +8503,7 @@
      * after the session is closed) */
 
-    EventQueue eventQ;
+#ifdef USE_XPCOM_QUEUE
+    NS_GetMainEventQ(getter_AddRefs(g_pEventQ));
+#endif
 
     if (!checkForAutoConvertedSettings (virtualBox, session, fConvertSettings))
@@ -8575,4 +8582,8 @@
     session->Close();
 
+#ifdef USE_XPCOM_QUEUE
+    g_pEventQ->ProcessPendingEvents();
+#endif
+
     // end "all-stuff" scope
     ////////////////////////////////////////////////////////////////////////////
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManage.h
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManage.h	(revision 14257)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManage.h	(revision 14258)
@@ -26,7 +26,12 @@
 #include <VBox/com/ptr.h>
 #include <VBox/com/VirtualBox.h>
+#include <VBox/com/EventQueue.h>
 #endif /* !VBOX_ONLY_DOCS */
 
 #include <iprt/types.h>
+
+#if defined(VBOX_WITH_XPCOM) && !defined(RT_OS_DARWIN) && !defined(RT_OS_OS2)
+# define USE_XPCOM_QUEUE
+#endif
 
 /** @name Syntax diagram category.
@@ -87,4 +92,9 @@
 extern bool g_fInternalMode;
 
+#ifndef VBOX_ONLY_DOCS
+/** A pointer to the event queue, set by main() before calling any handlers. */
+extern nsCOMPtr<nsIEventQueue> g_pEventQ;
+#endif /* !VBOX_ONLY_DOCS */
+
 /** showVMInfo details */
 typedef enum
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestProp.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestProp.cpp	(revision 14257)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestProp.cpp	(revision 14258)
@@ -25,17 +25,176 @@
 *******************************************************************************/
 
+#if defined(VBOX_WITH_XPCOM) && !defined(RT_OS_DARWIN) && !defined(RT_OS_OS2)
+# define USE_XPCOM_QUEUE
+#endif
+
+#include "VBoxManage.h"
+
 #include <VBox/com/com.h>
 #include <VBox/com/string.h>
 #include <VBox/com/array.h>
 #include <VBox/com/ErrorInfo.h>
-
 #include <VBox/com/VirtualBox.h>
 
+#include <VBox/log.h>
 #include <iprt/stream.h>
-#include <VBox/log.h>
-
-#include "VBoxManage.h"
+#include <iprt/thread.h>
+#include <iprt/time.h>
+
+#ifdef USE_XPCOM_QUEUE
+# include <sys/select.h>
+#endif
 
 using namespace com;
+
+class GuestPropertyCallback : public IVirtualBoxCallback
+{
+public:
+    GuestPropertyCallback(const char *pszPatterns, Guid aUuid)
+        : mSignalled(false), mPatterns(pszPatterns), mUuid(aUuid)
+    {
+#if defined (RT_OS_WINDOWS)
+        refcnt = 0;
+#endif
+    }
+
+    virtual ~GuestPropertyCallback() {}
+
+#ifdef RT_OS_WINDOWS
+    STDMETHOD_(ULONG, AddRef)()
+    {
+        return ::InterlockedIncrement(&refcnt);
+    }
+    STDMETHOD_(ULONG, Release)()
+    {
+        long cnt = ::InterlockedDecrement(&refcnt);
+        if (cnt == 0)
+            delete this;
+        return cnt;
+    }
+    STDMETHOD(QueryInterface)(REFIID riid , void **ppObj)
+    {
+        if (riid == IID_IUnknown)
+        {
+            *ppObj = this;
+            AddRef();
+            return S_OK;
+        }
+        if (riid == IID_IVirtualBoxCallback)
+        {
+            *ppObj = this;
+            AddRef();
+            return S_OK;
+        }
+        *ppObj = NULL;
+        return E_NOINTERFACE;
+    }
+#endif
+
+    NS_DECL_ISUPPORTS
+
+    STDMETHOD(OnMachineStateChange)(INPTR GUIDPARAM machineId,
+                                    MachineState_T state)
+    {
+        return S_OK;
+    }
+
+    STDMETHOD(OnMachineDataChange)(INPTR GUIDPARAM machineId)
+    {
+        return S_OK;
+    }
+
+    STDMETHOD(OnExtraDataCanChange)(INPTR GUIDPARAM machineId, INPTR BSTR key,
+                                    INPTR BSTR value, BSTR *error,
+                                    BOOL *changeAllowed)
+    {
+        /* we never disagree */
+        if (!changeAllowed)
+            return E_INVALIDARG;
+        *changeAllowed = TRUE;
+        return S_OK;
+    }
+
+    STDMETHOD(OnExtraDataChange)(INPTR GUIDPARAM machineId, INPTR BSTR key,
+                                 INPTR BSTR value)
+    {
+        return S_OK;
+    }
+
+    STDMETHOD(OnMediaRegistered) (INPTR GUIDPARAM mediaId,
+                                  DeviceType_T mediaType, BOOL registered)
+    {
+        NOREF (mediaId);
+        NOREF (mediaType);
+        NOREF (registered);
+        return S_OK;
+    }
+
+    STDMETHOD(OnMachineRegistered)(INPTR GUIDPARAM machineId, BOOL registered)
+    {
+        return S_OK;
+    }
+
+     STDMETHOD(OnSessionStateChange)(INPTR GUIDPARAM machineId,
+                                    SessionState_T state)
+    {
+        return S_OK;
+    }
+
+    STDMETHOD(OnSnapshotTaken) (INPTR GUIDPARAM aMachineId,
+                                INPTR GUIDPARAM aSnapshotId)
+    {
+        return S_OK;
+    }
+
+    STDMETHOD(OnSnapshotDiscarded) (INPTR GUIDPARAM aMachineId,
+                                    INPTR GUIDPARAM aSnapshotId)
+    {
+        return S_OK;
+    }
+
+    STDMETHOD(OnSnapshotChange) (INPTR GUIDPARAM aMachineId,
+                                 INPTR GUIDPARAM aSnapshotId)
+    {
+        return S_OK;
+    }
+
+    STDMETHOD(OnGuestPropertyChange)(INPTR GUIDPARAM machineId,
+                                     INPTR BSTR name, INPTR BSTR value,
+                                     INPTR BSTR flags)
+    {
+        int rc = S_OK;
+        Utf8Str utf8Name (name);
+        Guid uuid(machineId);
+        if (utf8Name.isNull())
+            rc = E_OUTOFMEMORY;
+        if (   SUCCEEDED (rc)
+            && uuid == mUuid
+            && RTStrSimplePatternMultiMatch (mPatterns, RTSTR_MAX,
+                                             utf8Name.raw(), RTSTR_MAX, NULL))
+        {
+            RTPrintf ("Name: %lS, value: %lS, flags: %lS\n", name, value,
+                      flags);
+            mSignalled = true;
+        }
+        return rc;
+    }
+
+    bool Signalled(void) { return mSignalled; }
+
+private:
+    bool mSignalled;
+    const char *mPatterns;
+    Guid mUuid;
+#ifdef RT_OS_WINDOWS
+    long refcnt;
+#endif
+
+};
+
+#ifdef VBOX_WITH_XPCOM
+NS_DECL_CLASSINFO(GuestPropertyCallback)
+NS_IMPL_ISUPPORTS1_CI(GuestPropertyCallback, IVirtualBoxCallback)
+#endif /* VBOX_WITH_XPCOM */
 
 void usageGuestProperty(void)
@@ -49,4 +208,7 @@
     RTPrintf("VBoxManage guestproperty    enumerate <vmname>|<uuid>\n"
              "                            [-patterns <patterns>]\n"
+             "\n");
+    RTPrintf("VBoxManage guestproperty    wait <vmname>|<uuid> <patterns>\n"
+             "                            [--timeout <timeout>]\n"
              "\n");
 }
@@ -240,4 +402,113 @@
 
 /**
+ * Enumerates the properties in the guest property store.
+ *
+ * @returns 0 on success, 1 on failure
+ * @note see the command line API description for parameters
+ */
+static int handleWaitGuestProperty(int argc, char *argv[],
+                                   ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession)
+{
+
+/*
+ * Handle arguments
+ */
+    const char *pszPatterns = NULL;
+    uint32_t u32Timeout = RT_INDEFINITE_WAIT;
+    bool usageOK = true;
+    if (argc < 2)
+        usageOK = false;
+    else
+        pszPatterns = argv[1];
+    ComPtr<IMachine> machine;
+    /* assume it's a UUID */
+    HRESULT rc = aVirtualBox->GetMachine(Guid(argv[0]), machine.asOutParam());
+    if (FAILED(rc) || !machine)
+    {
+        /* must be a name */
+        CHECK_ERROR(aVirtualBox, FindMachine(Bstr(argv[0]), machine.asOutParam()));
+    }
+    if (!machine)
+        usageOK = false;
+    for (int i = 2; usageOK && i < argc; ++i)
+    {
+        if (strcmp(argv[i], "-timeout") == 0)
+        {
+            if (   i + 1 >= argc
+                || RTStrToUInt32Full(argv[i + 1], 10, &u32Timeout)
+                       != VINF_SUCCESS
+               )
+                usageOK = false;
+            else
+                ++i;
+        }
+        else
+            usageOK = false;
+    }
+    if (!usageOK)
+        return errorSyntax(USAGE_GUESTPROPERTY, "Incorrect parameters");
+
+/*
+ * Set up the callback and wait.
+ */
+    Guid uuid;
+    machine->COMGETTER(Id)(uuid.asOutParam());
+    GuestPropertyCallback *callback = new GuestPropertyCallback(pszPatterns, uuid);
+    callback->AddRef();
+    aVirtualBox->RegisterCallback (callback);
+    bool stop = false;
+#ifdef USE_XPCOM_QUEUE
+    int max_fd = g_pEventQ->GetEventQueueSelectFD();
+#endif
+    for (; !stop && u32Timeout > 0; u32Timeout -= RT_MIN(u32Timeout, 1000))
+    {
+#ifdef USE_XPCOM_QUEUE
+        int prc;
+        fd_set fdset;
+        struct timeval tv;
+        FD_ZERO (&fdset);
+        FD_SET(max_fd, &fdset);
+        tv.tv_sec = RT_MIN(u32Timeout, 1000);
+        tv.tv_usec = u32Timeout > 1000 ? 0 : u32Timeout * 1000;
+        RTTIMESPEC TimeNow;
+        uint64_t u64Time = RTTimeSpecGetMilli(RTTimeNow(&TimeNow));
+        prc = select(max_fd + 1, &fdset, NULL, NULL, &tv);
+        if (prc == -1)
+        {
+            RTPrintf("Error waiting for event.\n");
+            stop = true;
+        }
+        else if (prc != 0)
+        {
+            uint64_t u64NextTime = RTTimeSpecGetMilli(RTTimeNow(&TimeNow));
+            u32Timeout += (uint32_t)(u64Time + 1000 - u64NextTime);
+            g_pEventQ->ProcessPendingEvents();
+            if (callback->Signalled())
+                stop = true;
+        }
+#else
+        /** @todo Use a semaphore.  But I currently don't have a Windows system
+         * running to test on. */
+        RTThreadSleep(RT_MIN(1000, u32Timeout));
+        if (callback->Signalled())
+            stop = true;
+#endif /* USE_XPCOM_QUEUE */
+    }
+
+/*
+ * Clean up the callback.
+ */
+    aVirtualBox->UnregisterCallback (callback);
+    if (!callback->Signalled())
+        RTPrintf("Time out or interruption while waiting for a notification.\n");
+    callback->Release ();
+
+/*
+ * Done.
+ */
+    return 0;
+}
+
+/**
  * Access the guest property store.
  *
@@ -256,4 +527,6 @@
     else if (0 == strcmp(argv[0], "enumerate"))
         return handleEnumGuestProperty(argc - 1, argv + 1, aVirtualBox, aSession);
+    else if (0 == strcmp(argv[0], "wait"))
+        return handleWaitGuestProperty(argc - 1, argv + 1, aVirtualBox, aSession);
     /* else */
     return errorSyntax(USAGE_GUESTPROPERTY, "Incorrect parameters");
