Index: trunk/src/VBox/Main/include/AdditionsFacilityImpl.h
===================================================================
--- trunk/src/VBox/Main/include/AdditionsFacilityImpl.h	(revision 39886)
+++ trunk/src/VBox/Main/include/AdditionsFacilityImpl.h	(revision 39890)
@@ -41,5 +41,6 @@
 
     // public initializer/uninitializer for internal purposes only
-    HRESULT init(Guest *aParent, AdditionsFacilityType_T enmFacility, AdditionsFacilityStatus_T enmStatus);
+    HRESULT init(Guest *a_pParent, AdditionsFacilityType_T a_enmFacility, AdditionsFacilityStatus_T a_enmStatus,
+                 uint32_t a_fFlags, PCRTTIMESPEC a_pTimeSpecTS);
     void uninit();
 
@@ -65,5 +66,5 @@
         AdditionsFacilityClass_T mClass;
     };
-    static const FacilityInfo sFacilityInfo[8];
+    static const FacilityInfo s_aFacilityInfo[8];
 
     // public internal methods
@@ -74,5 +75,5 @@
     AdditionsFacilityStatus_T getStatus() const;
     AdditionsFacilityType_T getType() const;
-    HRESULT update(AdditionsFacilityStatus_T aStatus, RTTIMESPEC aTimestamp);
+    void update(AdditionsFacilityStatus_T a_enmStatus, uint32_t a_fFlags, PCRTTIMESPEC a_pTimeSpecTS);
 
 private:
Index: trunk/src/VBox/Main/include/GuestImpl.h
===================================================================
--- trunk/src/VBox/Main/include/GuestImpl.h	(revision 39886)
+++ trunk/src/VBox/Main/include/GuestImpl.h	(revision 39890)
@@ -136,6 +136,6 @@
     void setAdditionsInfo2(uint32_t a_uFullVersion, const char *a_pszName, uint32_t a_uRevision, uint32_t a_fFeatures);
     bool facilityIsActive(VBoxGuestFacilityType enmFacility);
-    HRESULT facilityUpdate(VBoxGuestFacilityType enmFacility, VBoxGuestFacilityStatus enmStatus);
-    void setAdditionsStatus(VBoxGuestFacilityType enmFacility, VBoxGuestFacilityStatus enmStatus, ULONG aFlags);
+    void facilityUpdate(VBoxGuestFacilityType a_enmFacility, VBoxGuestFacilityStatus a_enmStatus, uint32_t a_fFlags, PCRTTIMESPEC a_pTimeSpecTS);
+    void setAdditionsStatus(VBoxGuestFacilityType a_enmFacility, VBoxGuestFacilityStatus a_enmStatus, uint32_t a_fFlags, PCRTTIMESPEC a_pTimeSpecTS);
     void setSupportedFeatures(uint32_t aCaps);
     HRESULT setStatistic(ULONG aCpuId, GUESTSTATTYPE enmType, ULONG aVal);
Index: trunk/src/VBox/Main/src-client/AdditionsFacilityImpl.cpp
===================================================================
--- trunk/src/VBox/Main/src-client/AdditionsFacilityImpl.cpp	(revision 39886)
+++ trunk/src/VBox/Main/src-client/AdditionsFacilityImpl.cpp	(revision 39890)
@@ -23,5 +23,5 @@
 
 /* static */
-const AdditionsFacility::FacilityInfo AdditionsFacility::sFacilityInfo[8] =
+const AdditionsFacility::FacilityInfo AdditionsFacility::s_aFacilityInfo[8] =
 {
     /* NOTE: We assume that unknown is always the first entry! */
@@ -56,7 +56,8 @@
 /////////////////////////////////////////////////////////////////////////////
 
-HRESULT AdditionsFacility::init(Guest *aParent, AdditionsFacilityType_T enmFacility, AdditionsFacilityStatus_T enmStatus)
-{
-    LogFlowThisFunc(("aParent=%p\n", aParent));
+HRESULT AdditionsFacility::init(Guest *a_pParent, AdditionsFacilityType_T a_enmFacility, AdditionsFacilityStatus_T a_enmStatus,
+                                uint32_t a_fFlags, PCRTTIMESPEC a_pTimeSpecTS)
+{
+    LogFlowThisFunc(("a_pParent=%p\n", a_pParent));
 
     /* Enclose the state transition NotReady->InInit->Ready. */
@@ -64,8 +65,9 @@
     AssertReturn(autoInitSpan.isOk(), E_FAIL);
 
-    RTTimeNow(&mData.mLastUpdated);
-    mData.mStatus = enmStatus;
-    mData.mType = enmFacility;
+    mData.mStatus       = a_enmStatus;
+    mData.mType         = a_enmFacility;
+    mData.mLastUpdated  = *a_pTimeSpecTS;
     /** @todo mClass is not initialized here. */
+    NOREF(a_fFlags);
 
     /* Confirm a successful initialization when it's the case. */
@@ -171,10 +173,10 @@
 const AdditionsFacility::FacilityInfo &AdditionsFacility::typeToInfo(AdditionsFacilityType_T aType)
 {
-    for (size_t i = 0; i < RT_ELEMENTS(sFacilityInfo); ++i)
+    for (size_t i = 0; i < RT_ELEMENTS(s_aFacilityInfo); ++i)
     {
-        if (sFacilityInfo[i].mType == aType)
-            return sFacilityInfo[i];
+        if (s_aFacilityInfo[i].mType == aType)
+            return s_aFacilityInfo[i];
     }
-    return sFacilityInfo[0]; /* Return unknown type. */
+    return s_aFacilityInfo[0]; /* Return unknown type. */
 }
 
@@ -204,10 +206,12 @@
 }
 
-HRESULT AdditionsFacility::update(AdditionsFacilityStatus_T aStatus, RTTIMESPEC aTimestamp)
-{
-    mData.mStatus = aStatus;
-    mData.mLastUpdated = aTimestamp;
-
-    return S_OK;
-}
-
+/**
+ * Method used by IGuest::facilityUpdate to make updates.
+ */
+void AdditionsFacility::update(AdditionsFacilityStatus_T a_enmStatus, uint32_t a_fFlags, PCRTTIMESPEC a_pTimeSpecTS)
+{
+    mData.mStatus       = a_enmStatus;
+    mData.mLastUpdated  = *a_pTimeSpecTS;
+    NOREF(a_fFlags);
+}
+
Index: trunk/src/VBox/Main/src-client/GuestImpl.cpp
===================================================================
--- trunk/src/VBox/Main/src-client/GuestImpl.cpp	(revision 39886)
+++ trunk/src/VBox/Main/src-client/GuestImpl.cpp	(revision 39890)
@@ -290,5 +290,5 @@
 STDMETHODIMP Guest::COMGETTER(Facilities)(ComSafeArrayOut(IAdditionsFacility*, aFacilities))
 {
-    CheckComArgOutPointerValid(aFacilities);
+    CheckComArgOutSafeArrayPointerValid(aFacilities);
 
     AutoCaller autoCaller(this);
@@ -726,8 +726,12 @@
 void Guest::setAdditionsInfo(Bstr aInterfaceVersion, VBOXOSTYPE aOsType)
 {
+    RTTIMESPEC TimeSpecTS;
+    RTTimeNow(&TimeSpecTS);
+
     AutoCaller autoCaller(this);
     AssertComRCReturnVoid(autoCaller.rc());
 
     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
 
     /*
@@ -765,5 +769,5 @@
              * interface version.
              */
-            facilityUpdate(VBoxGuestFacilityType_Graphics, VBoxGuestFacilityStatus_Active);
+            facilityUpdate(VBoxGuestFacilityType_Graphics, VBoxGuestFacilityStatus_Active,  0 /*fFlags*/, &TimeSpecTS);
         }
     }
@@ -774,6 +778,19 @@
      * and use the setSupportedFeatures function instead.
      */
-    facilityUpdate(VBoxGuestFacilityType_Graphics, facilityIsActive(VBoxGuestFacilityType_VBoxGuestDriver) ?
-                   VBoxGuestFacilityStatus_Active : VBoxGuestFacilityStatus_Inactive);
+    /** @todo r=bird: I don't get the above comment nor the code below...
+     * One talks about capability bits, the one always does something to a facility.
+     * Then there is the comment below it all, which is placed like it addresses the
+     * mOSTypeId, but talks about something which doesn't remotely like mOSTypeId...
+     *
+     * Andy, could you please try clarify and make the comments shorter and more
+     * coherent! Also, explain why this is important and what depends on it.
+     *
+     * PS. There is the VMMDEV_GUEST_SUPPORTS_GRAPHICS capability* report... It
+     * should come in pretty quickly after this update, normally.
+     */
+    facilityUpdate(VBoxGuestFacilityType_Graphics,
+                   facilityIsActive(VBoxGuestFacilityType_VBoxGuestDriver)
+                   ? VBoxGuestFacilityStatus_Active : VBoxGuestFacilityStatus_Inactive,
+                   0 /*fFlags*/, &TimeSpecTS); /** @todo the timestamp isn't gonna be right here on saved state restore. */
 
     /*
@@ -844,109 +861,81 @@
 }
 
-HRESULT Guest::facilityUpdate(VBoxGuestFacilityType enmFacility, VBoxGuestFacilityStatus enmStatus)
-{
-    ComAssertRet(enmFacility < INT32_MAX, E_INVALIDARG);
-
-    HRESULT rc;
-    RTTIMESPEC tsNow;
-    RTTimeNow(&tsNow);
-
-    FacilityMapIter it = mData.mFacilityMap.find((AdditionsFacilityType_T)enmFacility);
+void Guest::facilityUpdate(VBoxGuestFacilityType a_enmFacility, VBoxGuestFacilityStatus a_enmStatus,
+                           uint32_t a_fFlags, PCRTTIMESPEC a_pTimeSpecTS)
+{
+    AssertReturnVoid(   a_enmFacility < VBoxGuestFacilityType_All
+                     && a_enmFacility > VBoxGuestFacilityType_Unknown);
+
+    FacilityMapIter it = mData.mFacilityMap.find((AdditionsFacilityType_T)a_enmFacility);
     if (it != mData.mFacilityMap.end())
     {
         AdditionsFacility *pFac = it->second;
-        rc = pFac->update((AdditionsFacilityStatus_T)enmStatus, tsNow);
+        pFac->update((AdditionsFacilityStatus_T)a_enmStatus, a_fFlags, a_pTimeSpecTS);
     }
     else
     {
-        ComObjPtr<AdditionsFacility> pFacility;
-        pFacility.createObject();
-        ComAssert(!pFacility.isNull());
-        rc = pFacility->init(this,
-                             (AdditionsFacilityType_T)enmFacility,
-                             (AdditionsFacilityStatus_T)enmStatus);
-        if (SUCCEEDED(rc))
-            mData.mFacilityMap.insert(std::make_pair((AdditionsFacilityType_T)enmFacility, pFacility));
-    }
-
-    LogFlowFunc(("Returned with rc=%Rrc\n"));
-    return rc;
+        if (mData.mFacilityMap.size() > 64)
+        {
+            /* The easy way out for now. We could automatically destroy
+               inactive facilities like VMMDev does if we like... */
+            AssertFailedReturnVoid();
+        }
+
+        ComObjPtr<AdditionsFacility> ptrFac;
+        ptrFac.createObject();
+        AssertReturnVoid(!ptrFac.isNull());
+
+        HRESULT hrc = ptrFac->init(this, (AdditionsFacilityType_T)a_enmFacility, (AdditionsFacilityStatus_T)a_enmStatus,
+                                   a_fFlags, a_pTimeSpecTS);
+        if (SUCCEEDED(hrc))
+            mData.mFacilityMap.insert(std::make_pair((AdditionsFacilityType_T)a_enmFacility, ptrFac));
+    }
 }
 
 /**
  * Sets the status of a certain Guest Additions facility.
- * Gets called by vmmdevUpdateGuestStatus.
  *
- * @param enmFacility   Facility to set the status for.
- * @param enmStatus     Actual status to set.
- * @param aFlags
+ * Gets called by vmmdevUpdateGuestStatus, which just passes the report along.
+ *
+ * @param   a_pInterface        Pointer to this interface.
+ * @param   a_enmFacility       The facility.
+ * @param   a_enmStatus         The status.
+ * @param   a_fFlags            Flags assoicated with the update. Currently
+ *                              reserved and should be ignored.
+ * @param   a_pTimeSpecTS       Pointer to the timestamp of this report.
+ * @sa      PDMIVMMDEVCONNECTOR::pfnUpdateGuestStatus, vmmdevUpdateGuestStatus
+ * @thread  The emulation thread.
  */
-void Guest::setAdditionsStatus(VBoxGuestFacilityType enmFacility, VBoxGuestFacilityStatus enmStatus, ULONG aFlags)
-{
+void Guest::setAdditionsStatus(VBoxGuestFacilityType a_enmFacility, VBoxGuestFacilityStatus a_enmStatus,
+                               uint32_t a_fFlags, PCRTTIMESPEC a_pTimeSpecTS)
+{
+    Assert(   a_enmFacility > VBoxGuestFacilityType_Unknown
+           && a_enmFacility <= VBoxGuestFacilityType_All); /* Paranoia, VMMDev checks for this. */
+
     AutoCaller autoCaller(this);
     AssertComRCReturnVoid(autoCaller.rc());
 
     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
-    /*
-     * Set overall additions run level.
-     */
-
-    /* First check for disabled status. */
-    uint32_t uCurFacility = enmFacility + (enmStatus == VBoxGuestFacilityStatus_Active ? 0 : -1);
-    if (   enmFacility < VBoxGuestFacilityType_VBoxGuestDriver
-        || (   enmFacility == VBoxGuestFacilityType_All
-            && enmStatus   == VBoxGuestFacilityStatus_Inactive)
-       )
-    {
-        mData.mAdditionsRunLevel = AdditionsRunLevelType_None;
-    }
-    else if (uCurFacility >= VBoxGuestFacilityType_VBoxTrayClient)
-    {
-        mData.mAdditionsRunLevel = AdditionsRunLevelType_Desktop;
-    }
-    else if (uCurFacility >= VBoxGuestFacilityType_VBoxService)
-    {
-        mData.mAdditionsRunLevel = AdditionsRunLevelType_Userland;
-    }
-    else if (uCurFacility >= VBoxGuestFacilityType_VBoxGuestDriver)
-    {
-        mData.mAdditionsRunLevel = AdditionsRunLevelType_System;
-    }
-    else /* Should never happen! */
-        AssertMsgFailed(("Invalid facility status/run level detected! uCurFacility=%d\n", uCurFacility));
-
-    /** @todo Above is wrong. The runlevel has to be recalculated from the
-     *        facilities.  A user can stop VBoxService before logging out.
-     *        The runlevel should then drop to System, not Userland.
-     *
-     * Also, if given enmFacility = VBoxGuestFacilityType_Unknown, we'll be
-     * bosting the runlevel to Desktop (0 - 1 = UINT32_MAX; UINT32_MAX >=
-     * VBoxGuestFacilityType_VBoxTrayClient). */
-
-    /** @todo VBoxGuest (the driver) should track VMMDevReq_ReportGuestStatus
-     * calls per session and automatically send VBoxGuestFacilityStatus_Failed
-     * for the facilites that does not have the status
-     * VBoxGuestFacilityStatus_Terminated, VBoxGuestFacilityStatus_Failed or
-     * VBoxGuestFacilityStatus_Inactive.  Not doing so means this
-     * information is not reliable. */
 
     /*
      * Set a specific facility status.
      */
-    if (enmFacility > VBoxGuestFacilityType_Unknown)
-    {
-        if (enmFacility == VBoxGuestFacilityType_All)
-        {
-            FacilityMapIter it = mData.mFacilityMap.begin();
-            while (it != mData.mFacilityMap.end())
-            {
-                facilityUpdate((VBoxGuestFacilityType)it->first, enmStatus);
-                it++;
-            }
-        }
-        else /* Update one facility only. */
-            facilityUpdate(enmFacility, enmStatus);
-    }
+    if (a_enmFacility == VBoxGuestFacilityType_All)
+        for (FacilityMapIter it = mData.mFacilityMap.begin(); it != mData.mFacilityMap.end(); ++it)
+            facilityUpdate((VBoxGuestFacilityType)it->first, a_enmStatus, a_fFlags, a_pTimeSpecTS);
+    else /* Update one facility only. */
+        facilityUpdate(a_enmFacility, a_enmStatus, a_fFlags, a_pTimeSpecTS);
+
+    /*
+     * Recalc the runlevel.
+     */
+    if (facilityIsActive(VBoxGuestFacilityType_VBoxTrayClient))
+        mData.mAdditionsRunLevel = AdditionsRunLevelType_Desktop;
+    else if (facilityIsActive(VBoxGuestFacilityType_VBoxService))
+        mData.mAdditionsRunLevel = AdditionsRunLevelType_Userland;
+    else if (facilityIsActive(VBoxGuestFacilityType_VBoxGuestDriver))
+        mData.mAdditionsRunLevel = AdditionsRunLevelType_System;
+    else
+        mData.mAdditionsRunLevel = AdditionsRunLevelType_None;
 }
 
@@ -963,9 +952,17 @@
     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
 
-    facilityUpdate(VBoxGuestFacilityType_Seamless, aCaps & VMMDEV_GUEST_SUPPORTS_SEAMLESS ?
-                   VBoxGuestFacilityStatus_Active : VBoxGuestFacilityStatus_Inactive);
+    /** @todo A nit: The timestamp is wrong on saved state restore. Would be better
+     *  to move the graphics and seamless capability -> facility translation to
+     *  VMMDev so this could be saved.  */
+    RTTIMESPEC TimeSpecTS;
+    RTTimeNow(&TimeSpecTS);
+
+    facilityUpdate(VBoxGuestFacilityType_Seamless,
+                   aCaps & VMMDEV_GUEST_SUPPORTS_SEAMLESS ? VBoxGuestFacilityStatus_Active : VBoxGuestFacilityStatus_Inactive,
+                   0 /*fFlags*/, &TimeSpecTS);
     /** @todo Add VMMDEV_GUEST_SUPPORTS_GUEST_HOST_WINDOW_MAPPING */
-    facilityUpdate(VBoxGuestFacilityType_Graphics, aCaps & VMMDEV_GUEST_SUPPORTS_GRAPHICS ?
-                   VBoxGuestFacilityStatus_Active : VBoxGuestFacilityStatus_Inactive);
+    facilityUpdate(VBoxGuestFacilityType_Graphics,
+                   aCaps & VMMDEV_GUEST_SUPPORTS_GRAPHICS ? VBoxGuestFacilityStatus_Active : VBoxGuestFacilityStatus_Inactive,
+                   0 /*fFlags*/, &TimeSpecTS);
 }
 /* vi: set tabstop=4 shiftwidth=4 expandtab: */
Index: trunk/src/VBox/Main/src-client/VMMDevInterface.cpp
===================================================================
--- trunk/src/VBox/Main/src-client/VMMDevInterface.cpp	(revision 39886)
+++ trunk/src/VBox/Main/src-client/VMMDevInterface.cpp	(revision 39890)
@@ -158,19 +158,10 @@
 
 /**
- * Reports Guest Additions status.
- * Called whenever the Additions issue a guest status report request or the VM is reset.
- *
- * @param   pInterface          Pointer to this interface.
- * @param   guestInfo           Pointer to guest information structure
- * @thread  The emulation thread.
- */
-DECLCALLBACK(void) vmmdevUpdateGuestStatus(PPDMIVMMDEVCONNECTOR pInterface, const VBoxGuestStatus *guestStatus)
-{
-    PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
-
-    Assert(guestStatus);
-    if (!guestStatus)
-        return;
-
+ * @interface_method_impl{PDMIVMMDEVCONNECTOR,pfnUpdateGuestStatus}
+ */
+DECLCALLBACK(void) vmmdevUpdateGuestStatus(PPDMIVMMDEVCONNECTOR pInterface, uint32_t uFacility, uint16_t uStatus,
+                                           uint32_t fFlags, PCRTTIMESPEC pTimeSpecTS)
+{
+    PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
     Console *pConsole = pDrv->pVMMDev->getParent();
 
@@ -181,5 +172,5 @@
         return;
 
-    guest->setAdditionsStatus(guestStatus->facility, guestStatus->status, guestStatus->flags);
+    guest->setAdditionsStatus((VBoxGuestFacilityType)uFacility, (VBoxGuestFacilityStatus)uStatus, fFlags, pTimeSpecTS);
     pConsole->onAdditionsStateChange();
 }
@@ -237,7 +228,7 @@
          *        while holding down the. */
         guest->setAdditionsInfo2(0, "", 0,  0); /* Clear Guest Additions version. */
-        guest->setAdditionsStatus(VBoxGuestFacilityType_All,
-                                  VBoxGuestFacilityStatus_Inactive,
-                                  0); /* Flags; not used. */
+        RTTIMESPEC TimeSpecTS;
+        RTTimeNow(&TimeSpecTS);
+        guest->setAdditionsStatus(VBoxGuestFacilityType_All, VBoxGuestFacilityStatus_Inactive, 0 /*fFlags*/, &TimeSpecTS);
         pConsole->onAdditionsStateChange();
     }
