Index: /trunk/include/VBox/HostServices/GuestPropertySvc.h
===================================================================
--- /trunk/include/VBox/HostServices/GuestPropertySvc.h	(revision 14213)
+++ /trunk/include/VBox/HostServices/GuestPropertySvc.h	(revision 14214)
@@ -448,5 +448,5 @@
 typedef struct _GetNotification
 {
-    VBoxGuestHGCMCallInfo hdr;
+    VBoxGuestHGCMCallInfoTimeout hdr;
 
     /**
Index: /trunk/include/VBox/VBoxGuest.h
===================================================================
--- /trunk/include/VBox/VBoxGuest.h	(revision 14213)
+++ /trunk/include/VBox/VBoxGuest.h	(revision 14214)
@@ -759,5 +759,5 @@
         type                    = VMMDevHGCMParmType_LinAddr;
         u.Pointer.size          = cb;
-        u.Pointer.u.linearAddr  = (uintptr_t)pv;
+        u.Pointer.u.linearAddr  = (VMMDEVHYPPTR32)(uintptr_t)pv;
     }
 #endif
@@ -1689,10 +1689,10 @@
 VBGLR3DECL(void)    VbglR3GuestPropReadValueFree(char *pszValue);
 VBGLR3DECL(int)     VbglR3GuestPropEnumRaw(uint32_t u32ClientId, const char *paszPatterns, char *pcBuf, uint32_t cbBuf, uint32_t *pcbBufActual);
-VBGLR3DECL(int)     VbglR3GuestPropEnum(uint32_t u32ClientId, char const * const *ppaszPatterns, size_t cPatterns, PVBGLR3GUESTPROPENUM *ppHandle,
+VBGLR3DECL(int)     VbglR3GuestPropEnum(uint32_t u32ClientId, char const * const *ppaszPatterns, uint32_t cPatterns, PVBGLR3GUESTPROPENUM *ppHandle,
                                         char const **ppszName, char const **ppszValue, uint64_t *pu64Timestamp, char const **ppszFlags);
 VBGLR3DECL(int)     VbglR3GuestPropEnumNext(PVBGLR3GUESTPROPENUM pHandle, char const **ppszName, char const **ppszValue, uint64_t *pu64Timestamp,
                                             char const **ppszFlags);
 VBGLR3DECL(void)    VbglR3GuestPropEnumFree(PVBGLR3GUESTPROPENUM pHandle);
-VBGLR3DECL(int)     VbglR3GuestPropDelSet(uint32_t u32ClientId, char const * const *papszPatterns, size_t cPatterns);
+VBGLR3DECL(int)     VbglR3GuestPropDelSet(uint32_t u32ClientId, char const * const *papszPatterns, uint32_t cPatterns);
 VBGLR3DECL(int)     VbglR3GuestPropWait(uint32_t u32ClientId, const char *pszPatterns, void *pvBuf, uint32_t cbBuf, uint64_t u64Timestamp, uint32_t u32Timeout, char ** ppszName, char **ppszValue, uint64_t *pu64Timestamp, char **ppszFlags, uint32_t *pcbBufActual);
 /** @}  */
Index: /trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibGuestProp.cpp
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibGuestProp.cpp	(revision 14213)
+++ /trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibGuestProp.cpp	(revision 14214)
@@ -253,5 +253,5 @@
  * @retval  VERR_NOT_FOUND if the key wasn't found.
  *
- * @param   u32ClientId     The client id returned by VbglR3ClipboardConnect().
+ * @param   u32ClientId     The client id returned by VbglR3GuestPropConnect().
  * @param   pszName         The value to read.  Utf8
  * @param   pvBuf           A scratch buffer to store the data retrieved into.
@@ -349,5 +349,5 @@
  *          property value.
  *
- * @param   u32ClientId     The client id returned by VbglR3ClipboardConnect().
+ * @param   u32ClientId     The client id returned by VbglR3GuestPropConnect().
  * @param   pszName         The value to read. Must be valid UTF-8.
  * @param   ppszValue       Where to store the pointer to the value returned.
@@ -431,5 +431,5 @@
  *          needed to hold the value and the value being updated.
  *
- * @param   u32ClientId     The client id returned by VbglR3ClipboardConnect().
+ * @param   u32ClientId     The client id returned by VbglR3GuestPropConnect().
  * @param   pszName         The value to read.  Utf8
  * @param   pszValue        Where to store the value retrieved.
@@ -556,5 +556,5 @@
 VBGLR3DECL(int) VbglR3GuestPropEnum(uint32_t u32ClientId,
                                     char const * const *papszPatterns,
-                                    size_t cPatterns,
+                                    uint32_t cPatterns,
                                     PVBGLR3GUESTPROPENUM *ppHandle,
                                     char const **ppszName,
@@ -577,8 +577,8 @@
     RTMemAutoPtr<char> Patterns;
     Patterns = (char *)RTMemAlloc(cchPatterns);
-    size_t iOffs = 0;
-    for (size_t i = 0; i < cPatterns; ++i)
-    {
-        size_t cb = strlen(papszPatterns[i]) + 1;
+    uint32_t iOffs = 0;
+    for (uint32_t i = 0; i < cPatterns; ++i)
+    {
+        uint32_t cb = strlen(papszPatterns[i]) + 1;
         memcpy(&Patterns[iOffs], papszPatterns[i], cb);
         iOffs += cb;
@@ -754,5 +754,5 @@
 VBGLR3DECL(int) VbglR3GuestPropDelSet(uint32_t u32ClientId,
                                       const char * const *papszPatterns,
-                                      size_t cPatterns)
+                                      uint32_t cPatterns)
 {
     PVBGLR3GUESTPROPENUM pHandle;
@@ -785,2 +785,121 @@
 }
 
+
+/**
+ * Wait for notification of changes to a guest property.  If this is called in
+ * a loop, the timestamp of the last notification seen can be passed as a
+ * parameter to be sure that no notifications are missed.
+ *
+ * @returns VBox status code.
+ * @retval  VINF_SUCCESS on success, @a ppszName, @a ppszValue,
+ *          @a pu64Timestamp and @a ppszFlags containing valid data.
+ * @retval  VINF_NOT_FOUND if no previous notification could be found with the
+ *          timestamp supplied.  This will normally mean that a large number
+ *          of notifications occurred in between.
+ * @retval  VERR_BUFFER_OVERFLOW if the scratch buffer @a pvBuf is not large
+ *          enough.  In this case the size needed will be placed in
+ *          @a pcbBufActual if it is not NULL.
+ * @retval  VERR_TIMEOUT if a timeout occurred before a notification was seen.
+ *
+ * @param   u32ClientId     The client id returned by VbglR3GuestPropConnect().
+ * @param   pszPatterns     The patterns that the property names must matchfor
+ *                          the change to be reported.
+ * @param   pvBuf           A scratch buffer to store the data retrieved into.
+ *                          The returned data is only valid for it's lifetime.
+ *                          @a ppszValue will point to the start of this buffer.
+ * @param   cbBuf           The size of @a pvBuf
+ * @param   u64Timestamp    The timestamp of the last event seen.  Pass zero
+ *                          to wait for the next event.
+ * @param   u32Timeout      Timeout in milliseconds.  Use RT_INDEFINITE_WAIT
+ *                          to wait indefinitely.
+ * @param   ppszName        Where to store the pointer to the name retrieved.
+ *                          Optional.
+ * @param   ppszValue       Where to store the pointer to the value retrieved.
+ *                          Optional.
+ * @param   pu64Timestamp   Where to store the timestamp.  Optional.
+ * @param   ppszFlags       Where to store the pointer to the flags.  Optional.
+ * @param   pcbBufActual    If @a pcBuf is not large enough, the size needed.
+ *                          Optional.
+ */
+VBGLR3DECL(int) VbglR3GuestPropWait(uint32_t u32ClientId,
+                                    const char *pszPatterns,
+                                    void *pvBuf, uint32_t cbBuf,
+                                    uint64_t u64Timestamp, uint32_t u32Timeout,
+                                    char ** ppszName, char **ppszValue,
+                                    uint64_t *pu64Timestamp, char **ppszFlags,
+                                    uint32_t *pcbBufActual)
+{
+    /*
+     * Create the GET_NOTIFICATION message and call the host.
+     */
+    GetNotification Msg;
+
+    Msg.hdr.u32Timeout = u32Timeout;
+    Msg.hdr.info.result = (uint32_t)VERR_WRONG_ORDER;  /** @todo drop the cast when the result type has been fixed! */
+    Msg.hdr.info.u32ClientID = u32ClientId;
+    Msg.hdr.info.u32Function = GET_NOTIFICATION;
+    Msg.hdr.info.cParms = 4;
+    Msg.patterns.SetPtr(const_cast<char *>(pszPatterns),
+                        strlen(pszPatterns) + 1);
+    Msg.buffer.SetPtr(pvBuf, cbBuf);
+    Msg.timestamp.SetUInt64(u64Timestamp);
+    Msg.size.SetUInt32(0);
+
+    int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL_TIMEOUT(sizeof(Msg)), &Msg, sizeof(Msg));
+    if (RT_SUCCESS(rc))
+        rc = Msg.hdr.info.result;
+
+    /*
+     * The cbBufActual parameter is also returned on overflow so the caller can
+     * adjust their buffer.
+     */
+    if (    rc == VERR_BUFFER_OVERFLOW
+        ||  pcbBufActual != NULL)
+    {
+        int rc2 = Msg.size.GetUInt32(pcbBufActual);
+        AssertRCReturn(rc2, RT_FAILURE(rc) ? rc : rc2);
+    }
+    if (RT_FAILURE(rc))
+        return rc;
+
+    /*
+     * Buffer layout: Name\0Value\0Flags\0.
+     *
+     * If the caller cares about any of these strings, make sure things are
+     * propertly terminated (paranoia).
+     */
+    if (    RT_SUCCESS(rc)
+        &&  (ppszName != NULL || ppszValue != NULL || ppszFlags != NULL))
+    {
+        /* Validate / skip 'Name'. */
+        char *pszValue = (char *)memchr(pvBuf, '\0', cbBuf) + 1;
+        AssertPtrReturn(pszValue, VERR_TOO_MUCH_DATA);
+        if (ppszName)
+            *ppszName = (char *)pvBuf;
+
+        /* Validate / skip 'Value'. */
+        char *pszFlags = (char *)memchr(pszValue, '\0',
+                                        cbBuf - (pszValue - (char *)pvBuf)) + 1;
+        AssertPtrReturn(pszFlags, VERR_TOO_MUCH_DATA);
+        if (ppszValue)
+            *ppszValue = pszValue;
+
+        if (ppszFlags)
+        {
+            /* Validate 'Flags'. */
+            void *pvEos = memchr(pszFlags, '\0', cbBuf - (pszFlags - (char *)pvBuf));
+            AssertPtrReturn(pvEos, VERR_TOO_MUCH_DATA);
+            *ppszFlags = pszFlags;
+        }
+    }
+
+    /* And the timestamp, if requested. */
+    if (pu64Timestamp != NULL)
+    {
+        rc = Msg.timestamp.GetUInt64(pu64Timestamp);
+        AssertRCReturn(rc, rc);
+    }
+
+    return VINF_SUCCESS;
+}
+
