Index: /trunk/include/VBox/VMMDev.h
===================================================================
--- /trunk/include/VBox/VMMDev.h	(revision 35886)
+++ /trunk/include/VBox/VMMDev.h	(revision 35887)
@@ -4,5 +4,5 @@
 
 /*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * Copyright (C) 2006-2011 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -670,4 +670,5 @@
 /**
  * Guest status facility.
+ * This needs to be kept in sync with AdditionsFacility of the Main API!
  */
 typedef enum
@@ -676,5 +677,5 @@
     VBoxGuestStatusFacility_VBoxGuestDriver = 20,
     VBoxGuestStatusFacility_VBoxService     = 100,
-    VBoxGuestStatusFacility_VBoxTray        = 101,
+    VBoxGuestStatusFacility_VBoxTrayClient  = 101, /* VBoxTray (Windows), VBoxClient (Linux, Unix). */
     VBoxGuestStatusFacility_All             = 999,
     VBoxGuestStatusFacility_SizeHack        = 0x7fffffff
@@ -682,4 +683,5 @@
 AssertCompileSize(VBoxGuestStatusFacility, 4);
 
+
 /**
  * The current guest status of a facility.
@@ -689,4 +691,5 @@
     VBoxGuestStatusCurrent_Disabled    = 0,
     VBoxGuestStatusCurrent_Inactive    = 1,
+    VBoxGuestStatusCurrent_Paused      = 2,
     VBoxGuestStatusCurrent_PreInit     = 20,
     VBoxGuestStatusCurrent_Init        = 30,
@@ -694,4 +697,5 @@
     VBoxGuestStatusCurrent_Terminating = 100,
     VBoxGuestStatusCurrent_Terminated  = 101,
+    VBoxGuestStatusCurrent_Unknown     = 999,
     VBoxGuestStatusCurrent_SizeHack    = 0x7fffffff
 } VBoxGuestStatusCurrent;
Index: /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxHelpers.cpp
===================================================================
--- /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxHelpers.cpp	(revision 35886)
+++ /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxHelpers.cpp	(revision 35887)
@@ -30,5 +30,5 @@
 int hlpReportStatus(VBoxGuestStatusCurrent statusCurrent)
 {
-    int rc = VbglR3ReportAdditionsStatus(VBoxGuestStatusFacility_VBoxTray,
+    int rc = VbglR3ReportAdditionsStatus(VBoxGuestStatusFacility_VBoxTrayClient,
                                          statusCurrent,
                                          0 /* Flags */);
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageInfo.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageInfo.cpp	(revision 35886)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageInfo.cpp	(revision 35887)
@@ -110,5 +110,4 @@
                         t.u8Hour, t.u8Minute, t.u8Second);
 }
-
 
 const char *stateToName(MachineState_T machineState, bool fShort)
@@ -787,7 +786,7 @@
     }
 
-    /* get the maximum amount of NICS */    
+    /* get the maximum amount of NICS */
     ULONG maxNICs = getMaxNics(virtualBox, machine);
-   
+
     for (ULONG currentNIC = 0; currentNIC < maxNICs; currentNIC++)
     {
@@ -2005,4 +2004,14 @@
         RTPrintf("Guest:\n\n");
 
+    ULONG guestVal;
+    rc = machine->COMGETTER(MemoryBalloonSize)(&guestVal);
+    if (SUCCEEDED(rc))
+    {
+        if (details == VMINFO_MACHINEREADABLE)
+            RTPrintf("GuestMemoryBalloon=%d\n", guestVal);
+        else
+            RTPrintf("Configured memory balloon size:      %d MB\n", guestVal);
+    }
+
     if (console)
     {
@@ -2043,17 +2052,52 @@
                         RTPrintf("Additions version:                   %lS\n\n", guestString.raw());
                 }
-            }
-        }
-    }
-
-    ULONG guestVal;
-    rc = machine->COMGETTER(MemoryBalloonSize)(&guestVal);
-    if (SUCCEEDED(rc))
-    {
-        if (details == VMINFO_MACHINEREADABLE)
-            RTPrintf("GuestMemoryBalloon=%d\n", guestVal);
-        else
-            RTPrintf("Configured memory balloon size:      %d MB\n", guestVal);
-    }
+
+                if (details != VMINFO_MACHINEREADABLE)
+                    RTPrintf("\nGuest Components:\n\n");
+
+                /* Print information about important Guest Additions parts: */
+                /** @todo Add a makeFacilityStatusStr() to translate facility states into a human readable string! */
+                AdditionsFacilityStatus faStatus;
+                LONGLONG lLastUpdatedMS = 0;
+                char szLastUpdated[32];
+                rc = guest->GetFacilityStatus(AdditionsFacilityType_VBoxGuestDriver, &lLastUpdatedMS, &faStatus);
+                if (SUCCEEDED(rc))
+                {
+                    makeTimeStr(szLastUpdated, sizeof(szLastUpdated), lLastUpdatedMS);
+                    if (details == VMINFO_MACHINEREADABLE)
+                        RTPrintf("GuestAdditionsFacilityStatusGuestDriver=%u,%ld\n",
+                                 faStatus, lLastUpdatedMS);
+                    else
+                        RTPrintf("Guest driver:                        %u (last update: %s)\n",
+                                 faStatus, szLastUpdated);
+                }
+
+                rc = guest->GetFacilityStatus(AdditionsFacilityType_VBoxService, &lLastUpdatedMS, &faStatus);
+                if (SUCCEEDED(rc))
+                {
+                    makeTimeStr(szLastUpdated, sizeof(szLastUpdated), lLastUpdatedMS);
+                    if (details == VMINFO_MACHINEREADABLE)
+                        RTPrintf("GuestAdditionsFacilityStatusVBoxService=%u,%ld\n",
+                                 faStatus, lLastUpdatedMS);
+                    else
+                        RTPrintf("VBoxService:                         %u (last update: %s)\n",
+                                 faStatus, szLastUpdated);
+                }
+
+                rc = guest->GetFacilityStatus(AdditionsFacilityType_VBoxTrayClient, &lLastUpdatedMS, &faStatus);
+                if (SUCCEEDED(rc))
+                {
+                    makeTimeStr(szLastUpdated, sizeof(szLastUpdated), lLastUpdatedMS);
+                    if (details == VMINFO_MACHINEREADABLE)
+                        RTPrintf("GuestAdditionsFacilityStatusVBoxTrayClient=%u,%ld\n",
+                                 faStatus, lLastUpdatedMS);
+                    else
+                        RTPrintf("VBoxTray / VBoxClient:               %u (last update: %s)\n",
+                                 faStatus, szLastUpdated);
+                }
+            }
+        }
+    }
+
     if (details != VMINFO_MACHINEREADABLE)
         RTPrintf("\n");
Index: /trunk/src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 35886)
+++ /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 35887)
@@ -7879,4 +7879,66 @@
 
   <enum
+    name="AdditionsFacilityType"
+    uuid="bcf4f5e7-86d6-4b8c-99cd-449a79114fb4"
+    >
+    <desc>
+      Guest Additions facility IDs.
+    </desc>
+
+    <const name="None"                    value="0">
+      <desc>No/invalid facility.</desc>
+    </const>
+    <const name="VBoxGuestDriver"         value="20">
+      <desc>VBoxGuest base driver.</desc>
+    </const>
+    <const name="VBoxService"             value="100">
+      <desc>VBoxService.</desc>
+    </const>
+    <const name="VBoxTrayClient"          value="101">
+      <desc>VBoxTray (Windows) / VBoxClient (Non-Windows).</desc>
+    </const>
+    <const name="All"                     value="999">
+      <desc>All facilities selected.</desc>
+    </const>
+  </enum>
+
+  <enum
+    name="AdditionsFacilityStatus"
+    uuid="f49bf8c0-e40b-44dd-9db5-8f4196bfda94"
+    >
+    <desc>
+      Guest Additions facility states.
+    </desc>
+
+    <const name="Disabled"                value="0">
+      <desc>Facility is disabled.</desc>
+    </const>
+    <const name="Inactive"                value="1">
+      <desc>Facility is enabled but inactive.</desc>
+    </const>
+    <const name="Paused"                  value="2">
+      <desc>Facility has been paused.</desc>
+    </const>
+    <const name="PreInit"                 value="20">
+      <desc>Facility is preparing to initialize.</desc>
+    </const>
+    <const name="Init"                    value="30">
+      <desc>Facility is initializing.</desc>
+    </const>
+    <const name="Active"                  value="50">
+      <desc>Facility is up and running.</desc>
+    </const>
+    <const name="Terminating"             value="100">
+      <desc>Facility is shutting down.</desc>
+    </const>
+    <const name="Terminated"              value="101">
+      <desc>Facility successfully shut down.</desc>
+    </const>
+    <const name="Unknown"                 value="999">
+      <desc>Facility status is unknown.</desc>
+    </const>
+  </enum>
+
+  <enum
     name="AdditionsRunLevelType"
     uuid="a25417ee-a9dd-4f5b-b0dc-377860087754"
@@ -8004,5 +8066,5 @@
   <interface
     name="IGuest" extends="$unknown"
-    uuid="7ce7e4d8-cdaa-4d83-a0f4-510c8ee70aea"
+    uuid="09c2e2e0-f6f9-45ec-91a1-aaab3fad9f1f"
     wsmap="managed"
     >
@@ -8111,4 +8173,19 @@
       <param name="memSharedTotal" type="unsigned long" dir="out">
         <desc>Total amount of shared memory in the hypervisor</desc>
+      </param>
+    </method>
+
+    <method name="getFacilityStatus">
+      <desc>
+        Get the current status of a Guest Additions facility.
+      </desc>
+      <param name="facility" type="AdditionsFacilityType" dir="in">
+        <desc>Facility to check status for.</desc>
+      </param>
+      <param name="timestamp" type="long long" dir="out">
+        <desc>Timestamp (in ms) of last status update of this facility seen by the host.</desc>
+      </param>
+      <param name="status" type="AdditionsFacilityStatus" dir="return">
+        <desc>The current (latest) facility status.</desc>
       </param>
     </method>
Index: /trunk/src/VBox/Main/include/GuestImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/GuestImpl.h	(revision 35886)
+++ /trunk/src/VBox/Main/include/GuestImpl.h	(revision 35887)
@@ -4,5 +4,5 @@
 
 /*
- * Copyright (C) 2006-2010 Oracle Corporation
+ * Copyright (C) 2006-2011 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -20,4 +20,5 @@
 #include "VirtualBoxBase.h"
 #include <iprt/list.h>
+#include <iprt/time.h>
 #include <VBox/ostypes.h>
 
@@ -88,4 +89,5 @@
 
     // IGuest methods
+    STDMETHOD(GetFacilityStatus)(AdditionsFacilityType aType, LONGLONG *aTimestamp, AdditionsFacilityStatus *aStatus);
     STDMETHOD(GetAdditionsStatus)(AdditionsRunLevelType_T aLevel, BOOL *aActive);
     STDMETHOD(SetCredentials)(IN_BSTR aUserName, IN_BSTR aPassword,
@@ -129,11 +131,11 @@
 
 private:
-
-    // Internal tasks
+#ifdef VBOX_WITH_GUEST_CONTROL
+    // Internal tasks.
     struct TaskGuest; /* Worker thread helper. */
-#ifdef VBOX_WITH_GUEST_CONTROL
     HRESULT taskCopyFile(TaskGuest *aTask);
     HRESULT taskUpdateGuestAdditions(TaskGuest *aTask);
 
+    // Internal callback context handling.
     struct CallbackContext
     {
@@ -183,4 +185,12 @@
 # endif
 
+    struct FacilityData
+    {
+        RTTIMESPEC                  tsLastUpdated;
+        AdditionsFacilityStatus_T   curStatus;
+    };
+    typedef std::map< AdditionsFacilityType_T, FacilityData > FacilityMap;
+    typedef std::map< AdditionsFacilityType_T, FacilityData >::iterator FacilityMapIter;
+
     struct Data
     {
@@ -190,4 +200,6 @@
 
         Bstr                    mOSTypeId;
+
+        FacilityMap             mFacilityMap;
         AdditionsRunLevelType_T mAdditionsRunLevel;
         Bstr                    mAdditionsVersion;
Index: /trunk/src/VBox/Main/src-client/GuestImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/GuestImpl.cpp	(revision 35886)
+++ /trunk/src/VBox/Main/src-client/GuestImpl.cpp	(revision 35887)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2006-2010 Oracle Corporation
+ * Copyright (C) 2006-2011 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -438,4 +438,41 @@
 }
 
+/**
+ * Returns the status of a specified Guest Additions facility.
+ *
+ * @return  aStatus         Current status of specified facility.
+ * @param   aType           Facility to get the status from.
+ * @param   aTimestamp      Timestamp of last facility status update in ms (optional).
+ */
+STDMETHODIMP Guest::GetFacilityStatus(AdditionsFacilityType aType, LONGLONG *aTimestamp, AdditionsFacilityStatus *aStatus)
+{
+    AutoCaller autoCaller(this);
+    if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    CheckComArgNotNull(aStatus);
+    /* Not checking for aTimestamp is intentional; it's optional. */
+
+    FacilityMapIter it = mData.mFacilityMap.find(aType);
+    if (it != mData.mFacilityMap.end())
+    {
+        *aStatus = it->second.curStatus;
+        if (aTimestamp)
+            *aTimestamp = RTTimeSpecGetMilli(&it->second.tsLastUpdated);
+    }
+    else
+    {
+        /*
+         * Do not fail here -- could be that the facility never has been brought up (yet) but
+         * the host wants to have its status anyway. So just tell we don't know at this point.
+         */
+        *aStatus = AdditionsFacilityStatus_Unknown;
+        if (aTimestamp)
+            *aTimestamp = RTTimeMilliTS();
+    }
+    return S_OK;
+}
+
 STDMETHODIMP Guest::GetAdditionsStatus(AdditionsRunLevelType_T aLevel, BOOL *aActive)
 {
@@ -600,7 +637,10 @@
     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
 
+    /*
+     * Set overall additions run level.
+     */
+
+    /* First check for disabled status. */
     uint32_t uCurFacility = Facility + (Status == VBoxGuestStatusCurrent_Active ? 0 : -1);
-
-    /* First check for disabled status. */
     if (   Facility < VBoxGuestStatusFacility_VBoxGuestDriver
         || (   Facility == VBoxGuestStatusFacility_All
@@ -613,5 +653,5 @@
         mData.mAdditionsRunLevel = AdditionsRunLevelType_None;
     }
-    else if (uCurFacility >= VBoxGuestStatusFacility_VBoxTray)
+    else if (uCurFacility >= VBoxGuestStatusFacility_VBoxTrayClient)
     {
         mData.mAdditionsRunLevel = AdditionsRunLevelType_Desktop;
@@ -627,4 +667,20 @@
     else /* Should never happen! */
         AssertMsgFailed(("Invalid facility status/run level detected! uCurFacility=%ld\n", uCurFacility));
+
+    /*
+     * Set a specific facility status.
+     */
+    if (Facility)
+    {
+        Assert(Facility < UINT32_MAX);
+        FacilityData *pData = &mData.mFacilityMap[(AdditionsFacilityType_T)Facility];
+        AssertPtr(pData);
+
+        RTTimeNow(&pData->tsLastUpdated);
+        pData->curStatus = (AdditionsFacilityStatus_T)Status;
+
+        LogFlowFunc(("Setting guest facility %u = %u (%u)\n",
+                     Facility, pData->curStatus, pData->tsLastUpdated));
+    }
 }
 
