Index: /trunk/include/VBox/HostServices/GuestPropertySvc.h
===================================================================
--- /trunk/include/VBox/HostServices/GuestPropertySvc.h	(revision 11082)
+++ /trunk/include/VBox/HostServices/GuestPropertySvc.h	(revision 11083)
@@ -39,22 +39,27 @@
     /** 
      * Get the value attached to a configuration property key
-     * The parameter format matches that of GET_CONFIG_KEY. 
-     */
-    GET_CONFIG_KEY_HOST = 2,
+     * The parameter format matches that of GET_PROP. 
+     */
+    GET_PROP_HOST = 2,
     /** 
      * Set the value attached to a configuration property key
-     * The parameter format matches that of SET_CONFIG_KEY.
-     */
-    SET_CONFIG_KEY_HOST = 3,
+     * The parameter format matches that of SET_PROP.
+     */
+    SET_PROP_HOST = 3,
+    /** 
+     * Set the value attached to a configuration property key
+     * The parameter format matches that of SET_PROP_VALUE.
+     */
+    SET_PROP_VALUE_HOST = 4,
     /** 
      * Remove the value attached to a configuration property key
-     * The parameter format matches that of DEL_CONFIG_KEY.
-     */
-    DEL_CONFIG_KEY_HOST = 4,
+     * The parameter format matches that of DEL_PROP.
+     */
+    DEL_PROP_HOST = 5,
     /** 
      * Enumerate guest properties.
      * The parameter format matches that of ENUM_PROPS.
      */
-    ENUM_PROPS_HOST = 5
+    ENUM_PROPS_HOST = 6
 };
 
Index: /trunk/src/VBox/HostServices/GuestProperties/service.cpp
===================================================================
--- /trunk/src/VBox/HostServices/GuestProperties/service.cpp	(revision 11082)
+++ /trunk/src/VBox/HostServices/GuestProperties/service.cpp	(revision 11083)
@@ -354,7 +354,6 @@
     uint64_t u64Timestamp = 0;
     if (RT_SUCCESS(rc) && (mpTimestampNode != NULL))
-        rc = CFGMR3QueryU64(mpFlagsNode, pszName, &u64Timestamp);
-    if (RT_SUCCESS(rc))
-        VBoxHGCMParmUInt64Set(&paParms[2], 0);
+        CFGMR3QueryU64(mpTimestampNode, pszName, &u64Timestamp);
+    VBoxHGCMParmUInt64Set(&paParms[2], u64Timestamp);
 
 /*
@@ -770,17 +769,23 @@
 
         /* The host wishes to read a configuration value */
-        case GET_CONFIG_KEY_HOST:
-            LogFlowFunc(("GET_CONFIG_KEY_HOST\n"));
-            rc = getKey(cParms, paParms);
+        case GET_PROP_HOST:
+            LogFlowFunc(("GET_PROP_HOST\n"));
+            rc = getProperty(cParms, paParms);
             break;
 
         /* The host wishes to set a configuration value */
-        case SET_CONFIG_KEY_HOST:
-            LogFlowFunc(("SET_CONFIG_KEY_HOST\n"));
+        case SET_PROP_HOST:
+            LogFlowFunc(("SET_PROP_HOST\n"));
             rc = setKey(cParms, paParms);
             break;
 
+        /* The host wishes to set a configuration value */
+        case SET_PROP_VALUE_HOST:
+            LogFlowFunc(("SET_PROP_VALUE_HOST\n"));
+            rc = setKey(cParms, paParms);
+            break;
+
         /* The host wishes to remove a configuration value */
-        case DEL_CONFIG_KEY_HOST:
+        case DEL_PROP_HOST:
             LogFlowFunc(("DEL_CONFIG_KEY_HOST\n"));
             rc = delKey(cParms, paParms);
Index: /trunk/src/VBox/Main/ConsoleImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/ConsoleImpl.cpp	(revision 11082)
+++ /trunk/src/VBox/Main/ConsoleImpl.cpp	(revision 11083)
@@ -3537,13 +3537,18 @@
  * @note Temporarily locks this object for writing.
  */
-HRESULT Console::getGuestProperty (INPTR BSTR aKey, BSTR *aValue)
+HRESULT Console::getGuestProperty (INPTR BSTR aName, BSTR *aValue,
+                                   ULONG64 *aTimestamp, BSTR *aFlags)
 {
 #if !defined (VBOX_WITH_GUEST_PROPS)
     return E_NOTIMPL;
 #else
-    if (!VALID_PTR (aKey))
+    if (!VALID_PTR (aName))
         return E_INVALIDARG;
     if (!VALID_PTR (aValue))
         return E_POINTER;
+    if ((aTimestamp != NULL) && !VALID_PTR (aTimestamp))
+        return E_POINTER;
+    if ((aFlags != NULL) && !VALID_PTR (aFlags))
+        return E_POINTER;
 
     AutoCaller autoCaller (this);
@@ -3560,25 +3565,32 @@
     using namespace guestProp;
 
-    VBOXHGCMSVCPARM parm[3];
-    Utf8Str Utf8Key = aKey;
-    Utf8Str Utf8Value (MAX_VALUE_LEN + 1);
+    VBOXHGCMSVCPARM parm[4];
+    Utf8Str Utf8Name = aName;
+    AssertReturn(!Utf8Name.isNull(), E_OUTOFMEMORY);
+    char pszBuffer[MAX_VALUE_LEN + MAX_FLAGS_LEN + 2];
 
     parm[0].type = VBOX_HGCM_SVC_PARM_PTR;
     /* To save doing a const cast, we use the mutableRaw() member. */
-    parm[0].u.pointer.addr = Utf8Key.mutableRaw();
+    parm[0].u.pointer.addr = Utf8Name.mutableRaw();
     /* The + 1 is the null terminator */
-    parm[0].u.pointer.size = Utf8Key.length() + 1;
+    parm[0].u.pointer.size = Utf8Name.length() + 1;
     parm[1].type = VBOX_HGCM_SVC_PARM_PTR;
-    parm[1].u.pointer.addr = Utf8Value.mutableRaw();
-    parm[1].u.pointer.size = MAX_VALUE_LEN + 1;
-    int vrc = mVMMDev->hgcmHostCall ("VBoxGuestPropSvc", GET_CONFIG_KEY_HOST,
-                                     3, &parm[0]);
+    parm[1].u.pointer.addr = pszBuffer;
+    parm[1].u.pointer.size = sizeof(pszBuffer);
+    int vrc = mVMMDev->hgcmHostCall ("VBoxGuestPropSvc", GET_PROP_HOST,
+                                     4, &parm[0]);
     /* The returned string should never be able to be greater than our buffer */
     AssertLogRel (vrc != VERR_BUFFER_OVERFLOW);
+    AssertLogRel (!RT_SUCCESS(vrc) || VBOX_HGCM_SVC_PARM_64BIT == parm[2].type);
     if (RT_SUCCESS (vrc) || (VERR_NOT_FOUND == vrc))
     {
         rc = S_OK;
         if (vrc != VERR_NOT_FOUND)
-            Utf8Value.cloneTo (aValue);
+        {
+            size_t iFlags = strlen(pszBuffer) + 1;
+            Utf8Str(pszBuffer).cloneTo (aValue);
+            *aTimestamp = parm[2].u.uint32;
+            Utf8Str(pszBuffer + iFlags).cloneTo (aFlags);
+        }
         else
             aValue = NULL;
@@ -3594,13 +3606,15 @@
  * @note Temporarily locks this object for writing.
  */
-HRESULT Console::setGuestProperty (INPTR BSTR aKey, INPTR BSTR aValue)
+HRESULT Console::setGuestProperty (INPTR BSTR aName, INPTR BSTR aValue, INPTR BSTR aFlags)
 {
 #if !defined (VBOX_WITH_GUEST_PROPS)
     return E_NOTIMPL;
 #else
-    if (!VALID_PTR (aKey))
+    if (!VALID_PTR (aName))
         return E_INVALIDARG;
     if ((aValue != NULL) && !VALID_PTR (aValue))
         return E_INVALIDARG;
+    if ((aFlags != NULL) && !VALID_PTR (aFlags))
+        return E_INVALIDARG;
 
     AutoCaller autoCaller (this);
@@ -3617,16 +3631,16 @@
     using namespace guestProp;
 
-    VBOXHGCMSVCPARM parm[2];
-    Utf8Str Utf8Key = aKey;
+    VBOXHGCMSVCPARM parm[3];
+    Utf8Str Utf8Name = aName;
     int vrc = VINF_SUCCESS;
 
     parm[0].type = VBOX_HGCM_SVC_PARM_PTR;
     /* To save doing a const cast, we use the mutableRaw() member. */
-    parm[0].u.pointer.addr = Utf8Key.mutableRaw();
+    parm[0].u.pointer.addr = Utf8Name.mutableRaw();
     /* The + 1 is the null terminator */
-    parm[0].u.pointer.size = Utf8Key.length() + 1;
+    parm[0].u.pointer.size = Utf8Name.length() + 1;
+    Utf8Str Utf8Value = aValue;
     if (aValue != NULL)
     {
-        Utf8Str Utf8Value = aValue;
         parm[1].type = VBOX_HGCM_SVC_PARM_PTR;
         /* To save doing a const cast, we use the mutableRaw() member. */
@@ -3634,9 +3648,22 @@
         /* The + 1 is the null terminator */
         parm[1].u.pointer.size = Utf8Value.length() + 1;
-        vrc = mVMMDev->hgcmHostCall ("VBoxGuestPropSvc", SET_CONFIG_KEY_HOST,
+    }
+    Utf8Str Utf8Flags = aFlags;
+    if (aFlags != NULL)
+    {
+        parm[2].type = VBOX_HGCM_SVC_PARM_PTR;
+        /* To save doing a const cast, we use the mutableRaw() member. */
+        parm[2].u.pointer.addr = Utf8Flags.mutableRaw();
+        /* The + 1 is the null terminator */
+        parm[2].u.pointer.size = Utf8Flags.length() + 1;
+    }
+    if ((aValue != NULL) && (aFlags != NULL))
+        vrc = mVMMDev->hgcmHostCall ("VBoxGuestPropSvc", SET_PROP_HOST,
+                                     3, &parm[0]);
+    else if (aValue != NULL)
+        vrc = mVMMDev->hgcmHostCall ("VBoxGuestPropSvc", SET_PROP_VALUE_HOST,
                                      2, &parm[0]);
-    }
     else
-        vrc = mVMMDev->hgcmHostCall ("VBoxGuestPropSvc", DEL_CONFIG_KEY_HOST,
+        vrc = mVMMDev->hgcmHostCall ("VBoxGuestPropSvc", DEL_PROP_HOST,
                                      1, &parm[0]);
     if (RT_SUCCESS (vrc))
@@ -3746,28 +3773,28 @@
  * arrays supplied by the caller.  We start by counting the number of entries.
  */
-     const char *pszBuf
-         = reinterpret_cast<const char *>(parm[1].u.pointer.addr);
-     unsigned cEntries = 0;
-     /* The list is terminated by a zero-length string at the end of a set
-      * of four strings. */
-     for (size_t i = 0; strlen(pszBuf + i) != 0; )
-     {
-        /* We are counting sets of four strings. */
-        for (unsigned j = 0; j < 4; ++j)
-            i += strlen(pszBuf + i) + 1;
-        ++cEntries;
-     }
+    const char *pszBuf
+        = reinterpret_cast<const char *>(parm[1].u.pointer.addr);
+    unsigned cEntries = 0;
+    /* The list is terminated by a zero-length string at the end of a set
+     * of four strings. */
+    for (size_t i = 0; strlen(pszBuf + i) != 0; )
+    {
+       /* We are counting sets of four strings. */
+       for (unsigned j = 0; j < 4; ++j)
+           i += strlen(pszBuf + i) + 1;
+       ++cEntries;
+    }
 
 /*
  * And now we create the COM safe arrays and fill them in.
  */
-     com::SafeArray <BSTR> names(cEntries);
-     com::SafeArray <BSTR> values(cEntries);
-     com::SafeArray <ULONG64> timestamps(cEntries);
-     com::SafeArray <BSTR> flags(cEntries);
-     size_t iBuf = 0;
-     /* Rely on the service to have formated the data correctly. */
-     for (unsigned i = 0; i < cEntries; ++i)
-     {
+    com::SafeArray <BSTR> names(cEntries);
+    com::SafeArray <BSTR> values(cEntries);
+    com::SafeArray <ULONG64> timestamps(cEntries);
+    com::SafeArray <BSTR> flags(cEntries);
+    size_t iBuf = 0;
+    /* Rely on the service to have formated the data correctly. */
+    for (unsigned i = 0; i < cEntries; ++i)
+    {
         size_t cchName = strlen(pszBuf + iBuf);
         Bstr(pszBuf + iBuf).detachTo(&names[i]);
@@ -3782,10 +3809,10 @@
         Bstr(pszBuf + iBuf).detachTo(&flags[i]);
         iBuf += cchFlags + 1;
-     }
-     names.detachTo(ComSafeArrayOutArg (aNames));
-     values.detachTo(ComSafeArrayOutArg (aValues));
-     timestamps.detachTo(ComSafeArrayOutArg (aTimestamps));
-     flags.detachTo(ComSafeArrayOutArg (aFlags));
-     return S_OK;
+    }
+    names.detachTo(ComSafeArrayOutArg (aNames));
+    values.detachTo(ComSafeArrayOutArg (aValues));
+    timestamps.detachTo(ComSafeArrayOutArg (aTimestamps));
+    flags.detachTo(ComSafeArrayOutArg (aFlags));
+    return S_OK;
 #endif /* else !defined (VBOX_WITH_GUEST_PROPS) */
 }
@@ -4315,62 +4342,52 @@
     }
 # ifdef VBOX_WITH_GUEST_PROPS
-    /* Save all guest/host property store entries to the machine XML
-     * file as extra data. */
-    PCFGMNODE pRegistry = CFGMR3GetChild (CFGMR3GetRoot (mpVM), "GuestProps/Values/");
-    PCFGMLEAF pValue = CFGMR3GetFirstValue (pRegistry);
+    /* Save all guest property store entries to the machine XML file */
+    PCFGMNODE pValues = CFGMR3GetChild (CFGMR3GetRoot (mpVM), "GuestProps/Values/");
+    PCFGMNODE pTimestamps = CFGMR3GetChild (CFGMR3GetRoot (mpVM), "GuestProps/Timestamps/");
+    PCFGMNODE pFlags = CFGMR3GetChild (CFGMR3GetRoot (mpVM), "GuestProps/Flags/");
+    /* Count the number of entries we have */
+    unsigned cValues = 0;
+    for (PCFGMLEAF pValue = CFGMR3GetFirstValue (pValues); pValue != NULL;
+         pValue = CFGMR3GetNextValue (pValue))
+        ++cValues;
+    /* And pack them into safe arrays */
+    com::SafeArray <BSTR> names(cValues);
+    com::SafeArray <BSTR> values(cValues);
+    com::SafeArray <ULONG64> timestamps(cValues);
+    com::SafeArray <BSTR> flags(cValues);
+    PCFGMLEAF pValue = CFGMR3GetFirstValue (pValues);
     vrc = VINF_SUCCESS;
+    unsigned iProp = 0;
     while (pValue != NULL && RT_SUCCESS(vrc))
     {
         using namespace guestProp;
-        char szKeyName[MAX_NAME_LEN + 1];
-        char szKeyValue[MAX_VALUE_LEN + 1];
-        char szExtraDataName[VBOX_SHARED_INFO_PREFIX_LEN + MAX_NAME_LEN + 1];
-        vrc = CFGMR3GetValueName (pValue, szKeyName, sizeof(szKeyName));
+
+        char szPropName[MAX_NAME_LEN + 1];
+        char szPropValue[MAX_VALUE_LEN + 1];
+        char szPropFlags[MAX_FLAGS_LEN + 1];
+        ULONG64 u64Timestamp = 0;  /* default */
+        szPropFlags[0] = '\0';  /* default */
+        vrc = CFGMR3GetValueName (pValue, szPropName, sizeof(szPropName));
         if (RT_SUCCESS(vrc))
-            vrc = CFGMR3QueryString (pRegistry, szKeyName, szKeyValue, sizeof(szKeyValue));
+            vrc = CFGMR3QueryString (pValues, szPropName, szPropValue, sizeof(szPropValue));
         if (RT_SUCCESS(vrc))
         {
-            strcpy(szExtraDataName, VBOX_SHARED_INFO_KEY_PREFIX);
-            strncpy(szExtraDataName + VBOX_SHARED_INFO_PREFIX_LEN, szKeyName, sizeof(szKeyName));
-            szExtraDataName[sizeof(szExtraDataName) - 1] = 0;
-        }
-        if (RT_SUCCESS(vrc))
-            if (FAILED(mMachine->SetExtraData(Bstr(szExtraDataName).raw(), Bstr(szKeyValue).raw())))
-                vrc = VERR_UNRESOLVED_ERROR;  /* We only need to know that we have to stop. */
-        if (RT_SUCCESS(vrc))
+            CFGMR3QueryString (pFlags, szPropName, szPropFlags, sizeof(szPropFlags));
+            CFGMR3QueryU64 (pTimestamps, szPropName, &u64Timestamp);
+            Bstr(szPropName).cloneTo(&names[iProp]);
+            Bstr(szPropValue).cloneTo(&values[iProp]);
+            timestamps[iProp] = u64Timestamp;
+            Bstr(szPropFlags).cloneTo(&flags[iProp]);
             pValue = CFGMR3GetNextValue (pValue);
-    }
-    /* In a second stage, we remove any extra data keys corresponding to
-     * properties which aren't in the CFGM node. */
-    Bstr strExtraDataKey;
-    for (;;)
-    {
-        using namespace guestProp;
-        Bstr strNextExtraDataKey;
-        Bstr strExtraDataValue;
-
-        /* get the next key */
-        int hrc = mMachine->GetNextExtraDataKey(strExtraDataKey, strNextExtraDataKey.asOutParam(),
-                                                strExtraDataValue.asOutParam());
-
-        /* stop if for some reason there's nothing more to request */
-        if (FAILED(hrc) || !strNextExtraDataKey)
-            break;
-
-        strExtraDataKey = strNextExtraDataKey;
-        Utf8Str strExtraDataKeyUtf8 = Utf8Str(strExtraDataKey);
-
-        /* we only care about keys starting with VBOX_SHARED_INFO_KEY_PREFIX */
-        if (strncmp(strExtraDataKeyUtf8.raw(), VBOX_SHARED_INFO_KEY_PREFIX, VBOX_SHARED_INFO_PREFIX_LEN) != 0)
-            continue;
-        char *pszCFGMValueName = (char*)strExtraDataKeyUtf8.raw() + VBOX_SHARED_INFO_PREFIX_LEN;
-
-        /* Now see if a lookup of the name in the CFGM node succeeds. */
-        char szKeyValue[MAX_VALUE_LEN + 1];
-        vrc = CFGMR3QueryString (pRegistry, pszCFGMValueName, szKeyValue, sizeof(szKeyValue));
-        /* And delete it from the extra data if it failed. */
-        if (VERR_CFGM_VALUE_NOT_FOUND == vrc)
-            mMachine->SetExtraData(strExtraDataKey, NULL);
-    }
+            ++iProp;
+            if (iProp >= cValues)
+                vrc = VERR_TOO_MUCH_DATA;
+        }
+    }
+    if (RT_SUCCESS(vrc) || (VERR_TOO_MUCH_DATA == vrc))
+        mControl->PushGuestProperties(ComSafeArrayAsInParam (names),
+                                      ComSafeArrayAsInParam (values),
+                                      ComSafeArrayAsInParam (timestamps),
+                                      ComSafeArrayAsInParam (flags));
 # endif /* VBOX_WITH_GUEST_PROPS defined */
 #endif /* VBOX_HGCM */
Index: /trunk/src/VBox/Main/ConsoleImpl2.cpp
===================================================================
--- /trunk/src/VBox/Main/ConsoleImpl2.cpp	(revision 11082)
+++ /trunk/src/VBox/Main/ConsoleImpl2.cpp	(revision 11083)
@@ -47,4 +47,6 @@
 #ifdef VBOX_WITH_GUEST_PROPS
 # include <VBox/HostServices/GuestPropertySvc.h>
+# include <VBox/com/defs.h>
+# include <VBox/com/array.h>
 #endif /* VBOX_WITH_GUEST_PROPS */
 #include <VBox/intnet.h>
@@ -1721,42 +1723,24 @@
         else
         {
-            rc = CFGMR3InsertNode(pRoot,       "GuestProps", &pGuestProps);              RC_CHECK();
-            rc = CFGMR3InsertNode(pGuestProps, "Values", &pValues);                      RC_CHECK();
-            rc = CFGMR3InsertNode(pGuestProps, "Timestamps", &pTimestamps);              RC_CHECK();
-            rc = CFGMR3InsertNode(pGuestProps, "Flags", &pFlags);                        RC_CHECK();
-            /* Load the saved machine registry.  This is stored as extra data
-             * keys in the machine XML file, starting with the prefix
-             * VBOX_SHARED_INFO_KEY_PREFIX. */
-            Bstr strExtraDataKey;
-            for (;;)
-            {
-                Bstr strNextExtraDataKey;
-                Bstr strExtraDataValue;
-
-                /* get the next key */
-                hrc = pMachine->GetNextExtraDataKey(strExtraDataKey, strNextExtraDataKey.asOutParam(),
-                                                    strExtraDataValue.asOutParam());
-
-                /* stop if for some reason there's nothing more to request */
-                if (FAILED(hrc) || !strNextExtraDataKey)
-                    break;
-
-                strExtraDataKey = strNextExtraDataKey;
-                Utf8Str strExtraDataKeyUtf8 = Utf8Str(strExtraDataKey);
-
-                /* we only care about keys starting with VBOX_SHARED_INFO_KEY_PREFIX */
-                if (strncmp(strExtraDataKeyUtf8.raw(), VBOX_SHARED_INFO_KEY_PREFIX, VBOX_SHARED_INFO_PREFIX_LEN) != 0)
-                    continue;
-                char *pszCFGMValueName = (char*)strExtraDataKeyUtf8.raw() + VBOX_SHARED_INFO_PREFIX_LEN;
-
-                /* now let's have a look at the value */
-                Utf8Str strCFGMValueUtf8 = Utf8Str(strExtraDataValue);
-                const char *pszCFGMValue = strCFGMValueUtf8.raw();
-                /* empty value means remove value which we've already done */
-                if (pszCFGMValue && *pszCFGMValue)
-                {
-                    rc = CFGMR3InsertString(pValues, pszCFGMValueName, pszCFGMValue);
-                    AssertMsgRC(rc, ("failed to insert CFGM value '%s' to key '%s'\n", pszCFGMValue, pszCFGMValueName));
-                }
+            rc = CFGMR3InsertNode(pRoot,       "GuestProps", &pGuestProps);             RC_CHECK();
+            rc = CFGMR3InsertNode(pGuestProps, "Values", &pValues);                     RC_CHECK();
+            rc = CFGMR3InsertNode(pGuestProps, "Timestamps", &pTimestamps);             RC_CHECK();
+            rc = CFGMR3InsertNode(pGuestProps, "Flags", &pFlags);                       RC_CHECK();
+
+            /* Pull over the properties from the server. */
+            SafeArray <BSTR> names;
+            SafeArray <BSTR> values;
+            SafeArray <ULONG64> timestamps;
+            SafeArray <BSTR> flags;
+            hrc = pConsole->mControl->PullGuestProperties(ComSafeArrayAsOutParam(names),
+                                                ComSafeArrayAsOutParam(values),
+                                                ComSafeArrayAsOutParam(timestamps),
+                                                ComSafeArrayAsOutParam(flags));                H();
+            size_t cProps = names.size();
+            for (size_t i = 0; i < cProps; ++i)
+            {
+                rc = CFGMR3InsertString(pValues, Utf8Str(names[i]).raw(), Utf8Str(values[i]).raw()); RC_CHECK();
+                rc = CFGMR3InsertInteger(pTimestamps, Utf8Str(names[i]).raw(), timestamps[i]);           RC_CHECK();
+                rc = CFGMR3InsertString(pFlags, Utf8Str(names[i]).raw(), Utf8Str(flags[i]).raw());   RC_CHECK();
             }
 
Index: /trunk/src/VBox/Main/MachineImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/MachineImpl.cpp	(revision 11082)
+++ /trunk/src/VBox/Main/MachineImpl.cpp	(revision 11083)
@@ -2691,4 +2691,7 @@
 STDMETHODIMP Machine::GetGuestProperty (INPTR BSTR aKey, BSTR *aValue, ULONG64 *aTimestamp, BSTR *aFlags)
 {
+#if !defined (VBOX_WITH_GUEST_PROPS)
+    return E_NOTIMPL;
+#else
     if (!VALID_PTR (aKey))
         return E_INVALIDARG;
@@ -2699,18 +2702,4 @@
     if (!VALID_PTR (aFlags))
         return E_POINTER;
-    *aTimestamp = 0;
-    Bstr().cloneTo(aFlags);
-    return GetGuestPropertyValue (aKey, aValue);
-}
-
-STDMETHODIMP Machine::GetGuestPropertyValue (INPTR BSTR aKey, BSTR *aValue)
-{
-#if !defined (VBOX_WITH_GUEST_PROPS)
-    return E_NOTIMPL;
-#else
-    if (!VALID_PTR (aKey))
-        return E_INVALIDARG;
-    if (!VALID_PTR (aValue))
-        return E_POINTER;
 
     AutoCaller autoCaller (this);
@@ -2719,51 +2708,37 @@
     AutoReadLock alock (this);
 
+    HRESULT rc = checkStateDependency (MutableStateDep);
+    CheckComRCReturnRC (rc);
+
     using namespace guestProp;
-    HRESULT rc = E_FAIL;
-
-    switch (mData->mSession.mState)
-    {
-        case SessionState_Closed:
-        {
-            /* The "+ 1" in the length is the null terminator. */
-            Bstr strKey (Bstr (aKey).length() + VBOX_SHARED_INFO_PREFIX_LEN + 1);
-            BSTR strKeyRaw = strKey.mutableRaw();
-
-            /* String manipulation in Main is pretty painful, especially given
-             * how often it is needed. */
-            for (unsigned i = 0; i < VBOX_SHARED_INFO_PREFIX_LEN; ++i)
-                /* I take it this is legal, at least g++ accepts it. */
-                strKeyRaw [i] = VBOX_SHARED_INFO_KEY_PREFIX[i];
-            /* The "+ 1" in the length is the null terminator. */
-            for (unsigned i = 0, len = Bstr (aKey).length() + 1; i < len; ++i)
-                strKeyRaw [i + VBOX_SHARED_INFO_PREFIX_LEN] = aKey [i];
-            rc = GetExtraData (strKey, aValue);
-            break;
-        }
-        case SessionState_Open:
-        {
-            if (mData->mSession.mState != SessionState_Open)
+    rc = E_FAIL;
+
+    if (!mHWData->mPropertyServiceActive)
+    {
+        bool found = false;
+        for (HWData::GuestPropertyList::const_iterator it = mHWData->mGuestProperties.begin();
+             (it != mHWData->mGuestProperties.end()) && !found; ++it)
+        {
+            if (it->mName == aKey)
             {
-                rc = setError (E_FAIL,
-                    tr ("Session is not open (session state: %d)"),
-                    mData->mSession.mState);
-                break;
+                it->mValue.cloneTo(aValue);
+                *aTimestamp = it->mTimestamp;
+                it->mFlags.cloneTo(aFlags);
+                found = true;
             }
-
-            ComPtr <IInternalSessionControl> directControl =
-                mData->mSession.mDirectControl;
-
-            /* just be on the safe side when calling another process */
-            alock.unlock();
-
-            rc = directControl->AccessGuestProperty (aKey, NULL,
-                                                     false /* isSetter */,
-                                                     aValue);
-            break;
-        }
-        default:
-            rc = setError (E_FAIL,
-                tr ("Session is currently transitioning (session state: %d)"),
-                mData->mSession.mState);
+        }
+        rc = S_OK;
+    }
+    else
+    {
+        ComPtr <IInternalSessionControl> directControl =
+            mData->mSession.mDirectControl;
+
+        /* just be on the safe side when calling another process */
+        alock.unlock();
+
+        rc = directControl->AccessGuestProperty (aKey, NULL, NULL,
+                                                 false /* isSetter */,
+                                                 aValue, aTimestamp, aFlags);
     }
     return rc;
@@ -2771,21 +2746,19 @@
 }
 
+STDMETHODIMP Machine::GetGuestPropertyValue (INPTR BSTR aKey, BSTR *aValue)
+{
+    ULONG64 dummyTimestamp;
+    BSTR dummyFlags;
+    return GetGuestProperty(aKey, aValue, &dummyTimestamp, &dummyFlags);
+}
+
 STDMETHODIMP Machine::GetGuestPropertyTimestamp (INPTR BSTR aKey, ULONG64 *aTimestamp)
 {
-    return E_NOTIMPL;
+    BSTR dummyValue;
+    BSTR dummyFlags;
+    return GetGuestProperty(aKey, &dummyValue, aTimestamp, &dummyFlags);
 }
 
 STDMETHODIMP Machine::SetGuestProperty (INPTR BSTR aKey, INPTR BSTR aValue, INPTR BSTR aFlags)
-{
-    if (!VALID_PTR (aKey))
-        return E_INVALIDARG;
-    if ((aValue != NULL) && !VALID_PTR (aValue))
-        return E_INVALIDARG;
-    if ((aFlags != NULL) && !VALID_PTR (aFlags))
-        return E_INVALIDARG;
-    return SetGuestPropertyValue (aKey, aValue);
-}
-
-STDMETHODIMP Machine::SetGuestPropertyValue (INPTR BSTR aKey, INPTR BSTR aValue)
 {
 #if !defined (VBOX_WITH_GUEST_PROPS)
@@ -2796,62 +2769,81 @@
     if ((aValue != NULL) && !VALID_PTR (aValue))
         return E_INVALIDARG;
+    if ((aFlags != NULL) && !VALID_PTR (aFlags))
+        return E_INVALIDARG;
+
+    /* For now there are no valid flags, so check this. */
+    if (aFlags != NULL)
+        for (size_t i = 0; aFlags[i] != '\0'; ++i)
+            if (aFlags[i] != ' ')
+                return E_INVALIDARG;
 
     AutoCaller autoCaller (this);
     CheckComRCReturnRC (autoCaller.rc());
 
-    /* SetExtraData() needs a write lock */
     AutoWriteLock alock (this);
 
+    HRESULT rc = checkStateDependency (MutableStateDep);
+    CheckComRCReturnRC (rc);
+
     using namespace guestProp;
-    HRESULT rc = E_FAIL;
-
-    switch (mData->mSession.mState)
-    {
-        case SessionState_Closed:
-        {
-            /* The "+ 1" in the length is the null terminator. */
-            Bstr strKey (Bstr (aKey).length() + VBOX_SHARED_INFO_PREFIX_LEN + 1);
-            BSTR strKeyRaw = strKey.mutableRaw();
-
-            /* String manipulation in Main is pretty painful, especially given
-             * how often it is needed. */
-            for (unsigned i = 0; i < VBOX_SHARED_INFO_PREFIX_LEN; ++i)
-                /* I take it this is legal, at least g++ accepts it. */
-                strKeyRaw [i] = VBOX_SHARED_INFO_KEY_PREFIX[i];
-            /* The "+ 1" in the length is the null terminator. */
-            for (unsigned i = 0, len = Bstr (aKey).length() + 1; i < len; ++i)
-                strKeyRaw [i + VBOX_SHARED_INFO_PREFIX_LEN] = aKey [i];
-            rc = SetExtraData (strKey, aValue);
-            break;
-        }
-        case SessionState_Open:
-        {
-            if (mData->mSession.mState != SessionState_Open)
+    rc = E_FAIL;
+
+    if (!mHWData->mPropertyServiceActive)
+    {
+        bool found = false;
+        HWData::GuestPropertyList::iterator targetIt = mHWData->mGuestProperties.end();
+        for (HWData::GuestPropertyList::iterator it = mHWData->mGuestProperties.begin();
+             (it != mHWData->mGuestProperties.end()) && !found; ++it)
+            if (it->mName == aKey)
             {
-                rc = setError (E_FAIL,
-                    tr ("Session is not open (session state: %d)"),
-                    mData->mSession.mState);
-                break;
+                targetIt = it;
+                found = true;
             }
-
-            ComPtr <IInternalSessionControl> directControl =
-                mData->mSession.mDirectControl;
-
-            /* just be on the safe side when calling another process */
-            alock.leave();
-
-            BSTR dummy = NULL;
-            rc = directControl->AccessGuestProperty (aKey, aValue,
-                                                     true /* isSetter */,
-                                                     &dummy);
-            break;
-        }
-        default:
-            rc = setError (E_FAIL,
-                tr ("Session is currently transitioning (session state: %d)"),
-                mData->mSession.mState);
+        if (targetIt != mHWData->mGuestProperties.end())
+        {
+            mHWData.backup();
+            if (NULL == aValue)
+                mHWData->mGuestProperties.erase(targetIt);
+            else
+            {
+                targetIt->mValue = aValue;
+                targetIt->mTimestamp = RTTimeMilliTS();
+                if (aFlags != NULL)
+                    targetIt->mFlags = aFlags;
+            }
+        }
+        else if (aValue != NULL)
+        {
+            mHWData.backup();
+            HWData::GuestProperty property;
+            property.mName = aKey;
+            property.mValue = aValue;
+            property.mTimestamp = RTTimeMilliTS();
+            property.mFlags = (aFlags != NULL ? Bstr(aFlags) : Bstr(""));
+            mHWData->mGuestProperties.push_back(property);
+        }
+        rc = S_OK;
+    }
+    else
+    {
+        ComPtr <IInternalSessionControl> directControl =
+            mData->mSession.mDirectControl;
+
+        /* just be on the safe side when calling another process */
+        alock.leave();
+
+        BSTR dummy = NULL;
+        ULONG64 dummy64;
+        rc = directControl->AccessGuestProperty (aKey, aValue, aFlags,
+                                                 true /* isSetter */,
+                                                 &dummy, &dummy64, &dummy);
     }
     return rc;
 #endif /* else !defined (VBOX_WITH_GUEST_PROPS) */
+}
+
+STDMETHODIMP Machine::SetGuestPropertyValue (INPTR BSTR aName, INPTR BSTR aValue)
+{
+    return SetGuestProperty(aName, aValue, NULL);
 }
 
@@ -4836,4 +4828,29 @@
     }
 
+    /* Guest properties (optional) */
+    {
+        Key guestPropertiesNode = aNode.findKey ("GuestProperties");
+        if (!guestPropertiesNode.isNull())
+        {
+            Key::List properties = guestPropertiesNode.keys ("GuestProperty");
+            for (Key::List::const_iterator it = properties.begin();
+                 it != properties.end(); ++ it)
+            {
+                /* property name (required) */
+                Bstr name = (*it).stringValue ("name");
+                /* property value (required) */
+                Bstr value = (*it).stringValue ("value");
+                /* property timestamp (optional, defaults to 0) */
+                ULONG64 timestamp = (*it).value<ULONG64> ("timestamp");
+                /* property flags (optional, defaults to empty) */
+                Bstr flags = (*it).stringValue ("flags");
+    
+                HWData::GuestProperty property = { name, value, timestamp, flags };
+                mHWData->mGuestProperties.push_back(property);
+            }
+        }
+        mHWData->mPropertyServiceActive = false;
+    }
+
     AssertComRC (rc);
     return rc;
@@ -6181,4 +6198,23 @@
         guestNode.setValue <ULONG> ("statisticsUpdateInterval",
                                     mHWData->mStatisticsUpdateInterval);
+    }
+
+    /* Guest properties */
+    {
+        Key guestPropertiesNode = aNode.createKey ("GuestProperties");
+
+        for (HWData::GuestPropertyList::const_iterator it = mHWData->mGuestProperties.begin();
+             it != mHWData->mGuestProperties.end();
+             ++ it)
+        {
+            HWData::GuestProperty property = *it;
+
+            Key propertyNode = guestPropertiesNode.appendKey ("GuestProperty");
+
+            propertyNode.setValue <Bstr> ("name", property.mName);
+            propertyNode.setValue <Bstr> ("value", property.mValue);
+            propertyNode.setValue <ULONG64> ("timestamp", property.mTimestamp);
+            propertyNode.setValue <Bstr> ("flags", property.mFlags);
+        }
     }
 
@@ -8731,4 +8767,84 @@
 }
 
+STDMETHODIMP SessionMachine::PullGuestProperties (ComSafeArrayOut(BSTR, aNames), ComSafeArrayOut(BSTR, aValues),
+              ComSafeArrayOut(ULONG64, aTimestamps), ComSafeArrayOut(BSTR, aFlags))
+{
+    LogFlowThisFunc (("\n"));
+
+    AutoCaller autoCaller (this);
+    AssertComRCReturn (autoCaller.rc(), autoCaller.rc());
+
+    AutoReadLock alock (this);
+
+    AssertReturn(!ComSafeArrayOutIsNull (aNames), E_POINTER);
+    AssertReturn(!ComSafeArrayOutIsNull (aValues), E_POINTER);
+    AssertReturn(!ComSafeArrayOutIsNull (aTimestamps), E_POINTER);
+    AssertReturn(!ComSafeArrayOutIsNull (aFlags), E_POINTER);
+
+    unsigned cEntries = mHWData->mGuestProperties.size();
+    com::SafeArray <BSTR> names(cEntries);
+    com::SafeArray <BSTR> values(cEntries);
+    com::SafeArray <ULONG64> timestamps(cEntries);
+    com::SafeArray <BSTR> flags(cEntries);
+    unsigned i = 0;
+    for (HWData::GuestPropertyList::iterator it = mHWData->mGuestProperties.begin();
+         it != mHWData->mGuestProperties.end(); ++it)
+    {
+        it->mName.cloneTo(&names[i]);
+        it->mValue.cloneTo(&values[i]);
+        timestamps[i] = it->mTimestamp;
+        it->mFlags.cloneTo(&flags[i]);
+        ++i;
+    }
+    names.detachTo(ComSafeArrayOutArg (aNames));
+    values.detachTo(ComSafeArrayOutArg (aValues));
+    timestamps.detachTo(ComSafeArrayOutArg (aTimestamps));
+    flags.detachTo(ComSafeArrayOutArg (aFlags));
+    mHWData->mPropertyServiceActive = true;
+    return S_OK;
+}
+
+STDMETHODIMP SessionMachine::PushGuestProperties (ComSafeArrayIn(INPTR BSTR, aNames),
+                                                  ComSafeArrayIn(INPTR BSTR, aValues),
+                                                  ComSafeArrayIn(ULONG64, aTimestamps),
+                                                  ComSafeArrayIn(INPTR BSTR, aFlags))
+{
+    LogFlowThisFunc (("\n"));
+    AutoCaller autoCaller (this);
+    AssertComRCReturn (autoCaller.rc(), autoCaller.rc());
+
+    AutoWriteLock alock (this);
+
+    mData->mRegistered = FALSE;
+    HRESULT rc = checkStateDependency (MutableStateDep);
+    LogRel(("checkStateDependency (MutableStateDep) returned 0x%x\n", rc));
+    CheckComRCReturnRC (rc);
+
+    // ComAssertRet (mData->mMachineState < MachineState_Running, E_FAIL);
+
+    AssertReturn(!ComSafeArrayInIsNull (aNames), E_POINTER);
+    AssertReturn(!ComSafeArrayInIsNull (aValues), E_POINTER);
+    AssertReturn(!ComSafeArrayInIsNull (aTimestamps), E_POINTER);
+    AssertReturn(!ComSafeArrayInIsNull (aFlags), E_POINTER);
+
+    com::SafeArray <INPTR BSTR> names(ComSafeArrayInArg(aNames));
+    com::SafeArray <INPTR BSTR> values(ComSafeArrayInArg(aValues));
+    com::SafeArray <ULONG64> timestamps(ComSafeArrayInArg(aTimestamps));
+    com::SafeArray <INPTR BSTR> flags(ComSafeArrayInArg(aFlags));
+    mHWData.backup();
+    mHWData->mGuestProperties.erase(mHWData->mGuestProperties.begin(),
+                                    mHWData->mGuestProperties.end());
+    for (unsigned i = 0; i < names.size(); ++i)
+    {
+        HWData::GuestProperty property = { names[i], values[i], timestamps[i], flags[i] };
+        mHWData->mGuestProperties.push_back(property);
+    }
+    mHWData->mPropertyServiceActive = false;
+    alock.unlock();
+    SaveSettings();
+    mData->mRegistered = TRUE;
+    return S_OK;
+}
+
 // public methods only for internal purposes
 /////////////////////////////////////////////////////////////////////////////
Index: /trunk/src/VBox/Main/SessionImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/SessionImpl.cpp	(revision 11082)
+++ /trunk/src/VBox/Main/SessionImpl.cpp	(revision 11083)
@@ -654,6 +654,6 @@
 }
 
-STDMETHODIMP Session::AccessGuestProperty (INPTR BSTR aKey, INPTR BSTR aValue,
-                                           BOOL aIsSetter, BSTR *aRetValue)
+STDMETHODIMP Session::AccessGuestProperty (INPTR BSTR aName, INPTR BSTR aValue, INPTR BSTR aFlags,
+                                           BOOL aIsSetter, BSTR *aRetValue, ULONG64 *aRetTimestamp, BSTR *aRetFlags)
 {
 #ifdef VBOX_WITH_GUEST_PROPS
@@ -666,15 +666,22 @@
             mState);
     AssertReturn (mType == SessionType_Direct, E_UNEXPECTED);
-    if (!VALID_PTR (aKey))
+    if (!VALID_PTR (aName))
         return E_POINTER;
     if (!aIsSetter && !VALID_PTR (aRetValue))
+        return E_POINTER;
+    if (!aIsSetter && !VALID_PTR (aRetTimestamp))
+        return E_POINTER;
+    if (!aIsSetter && !VALID_PTR (aRetFlags))
         return E_POINTER;
     /* aValue can be NULL for a setter call if the property is to be deleted. */
     if (aIsSetter && (aValue != NULL) && !VALID_PTR (aValue))
         return E_INVALIDARG;
+    /* aFlags can be null if it is to be left as is */
+    if (aIsSetter && (aFlags != NULL) && !VALID_PTR (aFlags))
+        return E_INVALIDARG;
     if (!aIsSetter)
-        return mConsole->getGuestProperty (aKey, aRetValue);
+        return mConsole->getGuestProperty (aName, aRetValue, aRetTimestamp, aRetFlags);
     else
-        return mConsole->setGuestProperty (aKey, aValue);
+        return mConsole->setGuestProperty (aName, aValue, aFlags);
 #else /* VBOX_WITH_GUEST_PROPS not defined */
     return E_NOTIMPL;
Index: /trunk/src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 11082)
+++ /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 11083)
@@ -2225,5 +2225,5 @@
   <interface
      name="IInternalMachineControl" extends="$unknown"
-     uuid="1063893c-4c38-4304-aee9-73e072c181cc"
+     uuid="de04566a-7125-444b-949e-34e9f3ec3676"
      internal="yes"
      wsmap="suppress"
@@ -2462,4 +2462,65 @@
     </method>
 
+    <method name="pullGuestProperties">
+      <desc>
+        Get the list of the guest properties matching a set of patterns along
+        with their values, timestamps and flags and give responsibility for
+        managing properties to the console.
+      </desc>
+      <param name="name" type="wstring" dir="out" safearray="yes">
+        <desc>
+          The names of the properties returned.
+        </desc>
+      </param>
+      <param name="value" type="wstring" dir="out" safearray="yes">
+        <desc>
+          The values of the properties returned.  The array entries match the
+          corresponding entries in the @a name array.
+        </desc>
+      </param>
+      <param name="timestamp" type="unsigned long long" dir="out" safearray="yes">
+        <desc>
+          The timestamps of the properties returned.  The array entries match
+          the corresponding entries in the @a name array.
+        </desc>
+      </param>
+      <param name="flags" type="wstring" dir="out" safearray="yes">
+        <desc>
+          The flags of the properties returned.  The array entries match the
+          corresponding entries in the @a name array.
+        </desc>
+      </param>
+    </method>
+
+    <method name="pushGuestProperties">
+      <desc>
+        Set the list of the guest properties matching a set of patterns along
+        with their values, timestamps and flags and return responsibility for
+        managing properties to IMachine.
+      </desc>
+      <param name="name" type="wstring" dir="in" safearray="yes">
+        <desc>
+          The names of the properties returned.
+        </desc>
+      </param>
+      <param name="value" type="wstring" dir="in" safearray="yes">
+        <desc>
+          The values of the properties returned.  The array entries match the
+          corresponding entries in the @a name array.
+        </desc>
+      </param>
+      <param name="timestamp" type="unsigned long long" dir="in" safearray="yes">
+        <desc>
+          The timestamps of the properties returned.  The array entries match
+          the corresponding entries in the @a name array.
+        </desc>
+      </param>
+      <param name="flags" type="wstring" dir="in" safearray="yes">
+        <desc>
+          The flags of the properties returned.  The array entries match the
+          corresponding entries in the @a name array.
+        </desc>
+      </param>
+    </method>
   </interface>
 
@@ -9780,5 +9841,5 @@
   <interface
      name="IInternalSessionControl" extends="$unknown"
-     uuid="0dc8dc04-2d4c-45e7-885c-a0afe7e4dfa7"
+     uuid="2581845a-5a9d-45fb-bc3b-2476552dd970"
      internal="yes"
      wsmap="suppress"
@@ -9939,8 +10000,11 @@
         modify guest properties.
       </desc>
-      <param name="key" type="wstring" dir="in"/>
+      <param name="name" type="wstring" dir="in"/>
       <param name="value" type="wstring" dir="in"/>
+      <param name="flags" type="wstring" dir="in"/>
       <param name="isSetter" type="boolean" dir="in"/>
-      <param name="retValue" type="wstring" dir="return"/>
+      <param name="retValue" type="wstring" dir="out"/>
+      <param name="retTimestamp" type="unsigned long long" dir="out"/>
+      <param name="retFlags" type="wstring" dir="out"/>
     </method>
 
Index: /trunk/src/VBox/Main/include/ConsoleImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/ConsoleImpl.h	(revision 11082)
+++ /trunk/src/VBox/Main/include/ConsoleImpl.h	(revision 11083)
@@ -182,6 +182,6 @@
     HRESULT onUSBDeviceAttach (IUSBDevice *aDevice, IVirtualBoxErrorInfo *aError, ULONG aMaskedIfs);
     HRESULT onUSBDeviceDetach (INPTR GUIDPARAM aId, IVirtualBoxErrorInfo *aError);
-    HRESULT getGuestProperty (INPTR BSTR aKey, BSTR *aValue);
-    HRESULT setGuestProperty (INPTR BSTR aKey, INPTR BSTR aValue);
+    HRESULT getGuestProperty (INPTR BSTR aKey, BSTR *aValue, ULONG64 *aTimestamp, BSTR *aFlags);
+    HRESULT setGuestProperty (INPTR BSTR aKey, INPTR BSTR aValue, INPTR BSTR aFlags);
     HRESULT enumerateGuestProperties (INPTR BSTR aPatterns, ComSafeArrayOut(BSTR, aNames), ComSafeArrayOut(BSTR, aValues), ComSafeArrayOut(ULONG64, aTimestamps), ComSafeArrayOut(BSTR, aFlags));
     VMMDev *getVMMDev() { return mVMMDev; }
Index: /trunk/src/VBox/Main/include/MachineImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/MachineImpl.h	(revision 11082)
+++ /trunk/src/VBox/Main/include/MachineImpl.h	(revision 11083)
@@ -229,4 +229,18 @@
     struct HWData
     {
+        /**
+         * Data structure to hold information about a guest property.
+         */
+        struct GuestProperty {
+            /** Property name */
+            Bstr mName;
+            /** Property value */
+            Bstr mValue;
+            /** Property timestamp */
+            ULONG64 mTimestamp;
+            /** Property flags */
+            Bstr mFlags;
+        };
+
         HWData();
         ~HWData();
@@ -248,4 +262,7 @@
         SharedFolderList mSharedFolders;
         ClipboardMode_T mClipboardMode;
+        typedef std::list <GuestProperty> GuestPropertyList;
+        GuestPropertyList mGuestProperties;
+        BOOL           mPropertyServiceActive;
     };
 
@@ -523,10 +540,10 @@
     STDMETHOD(CanShowConsoleWindow) (BOOL *aCanShow);
     STDMETHOD(ShowConsoleWindow) (ULONG64 *aWinId);
-    STDMETHOD(GetGuestProperty) (INPTR BSTR aKey, BSTR *aValue, ULONG64 *aTimestamp, BSTR *aFlags);
-    STDMETHOD(GetGuestPropertyValue) (INPTR BSTR aKey, BSTR *aValue);
-    STDMETHOD(GetGuestPropertyTimestamp) (INPTR BSTR aKey, ULONG64 *aTimestamp);
-    STDMETHOD(SetGuestProperty) (INPTR BSTR aKey, INPTR BSTR aValue, INPTR BSTR aFlags);
-    STDMETHOD(SetGuestPropertyValue) (INPTR BSTR aKey, INPTR BSTR aValue);
-    STDMETHOD(EnumerateGuestProperties) (INPTR BSTR aPattern, ComSafeArrayOut(BSTR, aKeys), ComSafeArrayOut(BSTR, aValues), ComSafeArrayOut(ULONG64, aTimestamps), ComSafeArrayOut(BSTR, aFlags));
+    STDMETHOD(GetGuestProperty) (INPTR BSTR aName, BSTR *aValue, ULONG64 *aTimestamp, BSTR *aFlags);
+    STDMETHOD(GetGuestPropertyValue) (INPTR BSTR aName, BSTR *aValue);
+    STDMETHOD(GetGuestPropertyTimestamp) (INPTR BSTR aName, ULONG64 *aTimestamp);
+    STDMETHOD(SetGuestProperty) (INPTR BSTR aName, INPTR BSTR aValue, INPTR BSTR aFlags);
+    STDMETHOD(SetGuestPropertyValue) (INPTR BSTR aName, INPTR BSTR aValue);
+    STDMETHOD(EnumerateGuestProperties) (INPTR BSTR aPattern, ComSafeArrayOut(BSTR, aNames), ComSafeArrayOut(BSTR, aValues), ComSafeArrayOut(ULONG64, aTimestamps), ComSafeArrayOut(BSTR, aFlags));
 
     // public methods only for internal purposes
@@ -824,4 +841,8 @@
     STDMETHOD(DiscardCurrentSnapshotAndState) (
         IConsole *aInitiator, MachineState_T *aMachineState, IProgress **aProgress);
+    STDMETHOD(PullGuestProperties) (ComSafeArrayOut(BSTR, aNames), ComSafeArrayOut(BSTR, aValues),
+              ComSafeArrayOut(ULONG64, aTimestamps), ComSafeArrayOut(BSTR, aFlags));
+    STDMETHOD(PushGuestProperties) (ComSafeArrayIn(INPTR BSTR, aNames), ComSafeArrayIn(INPTR BSTR, aValues),
+              ComSafeArrayIn(ULONG64, aTimestamps), ComSafeArrayIn(INPTR BSTR, aFlags));
 
     // public methods only for internal purposes
Index: /trunk/src/VBox/Main/include/SessionImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/SessionImpl.h	(revision 11082)
+++ /trunk/src/VBox/Main/include/SessionImpl.h	(revision 11083)
@@ -106,6 +106,6 @@
     STDMETHOD(OnUSBDeviceDetach) (INPTR GUIDPARAM aId, IVirtualBoxErrorInfo *aError);
     STDMETHOD(OnShowWindow) (BOOL aCheck, BOOL *aCanShow, ULONG64 *aWinId);
-    STDMETHOD(AccessGuestProperty) (INPTR BSTR aKey, INPTR BSTR aValue,
-                                    BOOL aIsSetter, BSTR *aRetValue);
+    STDMETHOD(AccessGuestProperty) (INPTR BSTR aName, INPTR BSTR aValue, INPTR BSTR aFlags,
+                                    BOOL aIsSetter, BSTR *aRetValue, ULONG64 *aRetTimestamp, BSTR *aRetFlags);
     STDMETHOD(EnumerateGuestProperties) (INPTR BSTR aPatterns,
                                          ComSafeArrayOut(BSTR, aNames),
Index: /trunk/src/VBox/Main/xml/VirtualBox-settings-common.xsd
===================================================================
--- /trunk/src/VBox/Main/xml/VirtualBox-settings-common.xsd	(revision 11082)
+++ /trunk/src/VBox/Main/xml/VirtualBox-settings-common.xsd	(revision 11083)
@@ -687,4 +687,17 @@
 </xsd:complexType>
 
+<xsd:complexType name="TGuestProperty">
+  <xsd:attribute name="name"      type="xsd:string"       use="required"/>
+  <xsd:attribute name="value"     type="xsd:string"       use="required"/>
+  <xsd:attribute name="timestamp" type="xsd:unsignedLong" default="0"/>
+  <xsd:attribute name="flags"     type="xsd:string"       default=""/>
+</xsd:complexType>
+
+<xsd:complexType name="TGuestProperties">
+  <xsd:sequence>
+    <xsd:element name="GuestProperty" type="TGuestProperty" minOccurs="0" maxOccurs="unbounded"/>
+  </xsd:sequence>
+</xsd:complexType>
+
 <xsd:complexType name="THardware">
   <xsd:all>
@@ -731,4 +744,10 @@
     <xsd:element name="Clipboard" type="TClipboard"/>
     <xsd:element name="Guest" type="TGuest"/>
+    <xsd:element name="GuestProperties" type="TGuestProperties" minOccurs="0">
+      <xsd:unique name="THardware-GuestProperties-GuestProperty">
+        <xsd:selector xpath="vb:GuestProperty"/>
+        <xsd:field xpath="@name"/>
+      </xsd:unique>
+    </xsd:element>
   </xsd:all>
 </xsd:complexType>
