Index: /trunk/src/VBox/Main/include/AdditionsFacilityImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/AdditionsFacilityImpl.h	(revision 35997)
+++ /trunk/src/VBox/Main/include/AdditionsFacilityImpl.h	(revision 35997)
@@ -0,0 +1,94 @@
+/** @file
+ *
+ * VirtualBox COM class implementation
+ */
+
+/*
+ * Copyright (C) 2011 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef ____H_ADDITIONSFACILITYIMPL
+#define ____H_ADDITIONSFACILITYIMPL
+
+#include "VirtualBoxBase.h"
+#include <iprt/time.h>
+
+class Guest;
+
+class ATL_NO_VTABLE AdditionsFacility :
+    public VirtualBoxBase,
+    VBOX_SCRIPTABLE_IMPL(IAdditionsFacility)
+{
+public:
+    VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT(AdditionsFacility, IAdditionsFacility)
+
+    DECLARE_NOT_AGGREGATABLE(AdditionsFacility)
+
+    DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+    BEGIN_COM_MAP(AdditionsFacility)
+        VBOX_DEFAULT_INTERFACE_ENTRIES(IAdditionsFacility)
+    END_COM_MAP()
+
+    DECLARE_EMPTY_CTOR_DTOR(AdditionsFacility)
+
+    // public initializer/uninitializer for internal purposes only
+    HRESULT init(Guest *aParent, AdditionsFacilityType_T enmFacility, AdditionsFacilityStatus_T enmStatus);
+    void uninit();
+
+    HRESULT FinalConstruct();
+    void FinalRelease();
+
+    // IAdditionsFacility properties
+    STDMETHOD(COMGETTER(ClassType))(AdditionsFacilityClass_T *aClass);
+    STDMETHOD(COMGETTER(LastUpdated))(LONG64 *aTimestamp);
+    STDMETHOD(COMGETTER(Name))(BSTR *aName);
+    STDMETHOD(COMGETTER(Status))(AdditionsFacilityStatus_T *aStatus);
+    STDMETHOD(COMGETTER(Type))(AdditionsFacilityType_T *aType);
+
+public:
+    /** Facility <-> string mappings. */
+    struct FacilityInfo
+    {
+        /** The facilitie's name. */
+        const char            *mName; /* utf-8 */
+        /** The facilitie's type. */
+        AdditionsFacilityType_T  mType;
+        /** The facilitie's class. */
+        AdditionsFacilityClass_T mClass;
+    };
+    static const FacilityInfo sFacilityInfo[8];
+
+    // public internal methods
+    static const AdditionsFacility::FacilityInfo &typeToInfo(AdditionsFacilityType_T aType);
+    AdditionsFacilityClass_T getClass() const;
+    LONG64 getLastUpdated() const;
+    Bstr getName() const;
+    AdditionsFacilityStatus_T getStatus() const;
+    AdditionsFacilityType_T getType() const;
+    HRESULT update(AdditionsFacilityStatus_T aStatus, RTTIMESPEC aTimestamp);
+
+private:
+    struct Data
+    {
+        /** Timestamp of last updated status.
+         *  @todo Add a UpdateRecord struct to keep track of all
+         *        status changed + their time; nice for some GUIs. */
+        RTTIMESPEC mLastUpdated;
+        /** The facilitie's current status. */
+        AdditionsFacilityStatus_T mStatus;
+        /** The facilitie's ID/type. */
+        AdditionsFacilityType_T mType;
+    } mData;
+};
+
+#endif // ____H_ADDITIONSFACILITYIMPL
+
Index: /trunk/src/VBox/Main/src-client/AdditionsFacilityImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/AdditionsFacilityImpl.cpp	(revision 35997)
+++ /trunk/src/VBox/Main/src-client/AdditionsFacilityImpl.cpp	(revision 35997)
@@ -0,0 +1,212 @@
+/** @file
+ *
+ * VirtualBox COM class implementation
+ */
+
+/*
+ * Copyright (C) 2011 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include "AdditionsFacilityImpl.h"
+#include "Global.h"
+
+#include "AutoCaller.h"
+#include "Logging.h"
+
+/* static */
+const AdditionsFacility::FacilityInfo AdditionsFacility::sFacilityInfo[8] =
+{
+    /* NOTE: We assume that unknown is always the first entry! */
+    { "Unknown", AdditionsFacilityType_None, AdditionsFacilityClass_None },
+    { "VirtualBox Base Driver", AdditionsFacilityType_VBoxGuestDriver, AdditionsFacilityClass_Driver },
+    { "VirtualBox System Service", AdditionsFacilityType_VBoxService, AdditionsFacilityClass_Service },
+    { "VirtualBox Desktop Integration", AdditionsFacilityType_VBoxTrayClient, AdditionsFacilityClass_Program },
+    { "Seamless Mode", AdditionsFacilityType_Seamless, AdditionsFacilityClass_Feature },
+    { "Graphics Mode", AdditionsFacilityType_Graphics, AdditionsFacilityClass_Feature },
+};
+
+// constructor / destructor
+/////////////////////////////////////////////////////////////////////////////
+
+DEFINE_EMPTY_CTOR_DTOR (AdditionsFacility)
+
+HRESULT AdditionsFacility::FinalConstruct()
+{
+    LogFlowThisFunc(("\n"));
+    return BaseFinalConstruct();
+}
+
+void AdditionsFacility::FinalRelease()
+{
+    LogFlowThisFuncEnter();
+    uninit();
+    BaseFinalRelease();
+    LogFlowThisFuncLeave();
+}
+
+// public initializer/uninitializer for internal purposes only
+/////////////////////////////////////////////////////////////////////////////
+
+HRESULT AdditionsFacility::init(Guest *aParent, AdditionsFacilityType_T enmFacility, AdditionsFacilityStatus_T enmStatus)
+{
+    LogFlowThisFunc(("aParent=%p\n", aParent));
+
+    /* Enclose the state transition NotReady->InInit->Ready. */
+    AutoInitSpan autoInitSpan(this);
+    AssertReturn(autoInitSpan.isOk(), E_FAIL);
+
+    RTTimeNow (&mData.mLastUpdated);
+    mData.mStatus = enmStatus;
+    mData.mType = enmFacility;
+
+    /* Confirm a successful initialization when it's the case. */
+    autoInitSpan.setSucceeded();
+
+    return S_OK;
+}
+
+/**
+ * Uninitializes the instance.
+ * Called from FinalRelease().
+ */
+void AdditionsFacility::uninit()
+{
+    LogFlowThisFunc(("\n"));
+
+    /* Enclose the state transition Ready->InUninit->NotReady. */
+    AutoUninitSpan autoUninitSpan(this);
+    if (autoUninitSpan.uninitDone())
+        return;
+}
+
+STDMETHODIMP AdditionsFacility::COMGETTER(ClassType)(AdditionsFacilityClass_T *aClass)
+{
+    LogFlowThisFuncEnter();
+
+    CheckComArgOutPointerValid(aClass);
+
+    AutoCaller autoCaller(this);
+    if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    *aClass = getClass();
+
+    return S_OK;
+}
+
+STDMETHODIMP AdditionsFacility::COMGETTER(Name)(BSTR *aName)
+{
+    LogFlowThisFuncEnter();
+
+    CheckComArgOutPointerValid(aName);
+
+    AutoCaller autoCaller(this);
+    if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    Bstr(getName()).cloneTo(aName);
+
+    return S_OK;
+}
+
+STDMETHODIMP AdditionsFacility::COMGETTER(LastUpdated)(LONG64 *aTimestamp)
+{
+    LogFlowThisFuncEnter();
+
+    CheckComArgOutPointerValid(aTimestamp);
+
+    AutoCaller autoCaller(this);
+    if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    *aTimestamp = getLastUpdated();
+
+    return S_OK;
+}
+
+STDMETHODIMP AdditionsFacility::COMGETTER(Status)(AdditionsFacilityStatus_T *aStatus)
+{
+    LogFlowThisFuncEnter();
+
+    CheckComArgOutPointerValid(aStatus);
+
+    AutoCaller autoCaller(this);
+    if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    *aStatus = getStatus();
+
+    return S_OK;
+}
+
+STDMETHODIMP AdditionsFacility::COMGETTER(Type)(AdditionsFacilityType_T *aType)
+{
+    LogFlowThisFuncEnter();
+
+    CheckComArgOutPointerValid(aType);
+
+    AutoCaller autoCaller(this);
+    if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    *aType = getType();
+
+    return S_OK;
+}
+
+const AdditionsFacility::FacilityInfo &AdditionsFacility::typeToInfo(AdditionsFacilityType_T aType)
+{
+    for (size_t i = 0; i < RT_ELEMENTS(sFacilityInfo); ++i)
+    {
+        if (sFacilityInfo[i].mType == aType)
+            return sFacilityInfo[i];
+    }
+    return sFacilityInfo[0]; /* Return unknown type. */
+}
+
+AdditionsFacilityClass_T AdditionsFacility::getClass() const
+{
+    return AdditionsFacility::typeToInfo(mData.mType).mClass;
+}
+
+Bstr AdditionsFacility::getName() const
+{
+    return AdditionsFacility::typeToInfo(mData.mType).mName;
+}
+
+LONG64 AdditionsFacility::getLastUpdated() const
+{
+    return RTTimeSpecGetMilli(&mData.mLastUpdated);
+}
+
+AdditionsFacilityStatus_T AdditionsFacility::getStatus() const
+{
+    return mData.mStatus;
+}
+
+AdditionsFacilityType_T AdditionsFacility::getType() const
+{
+    return mData.mType;
+}
+
+HRESULT AdditionsFacility::update(AdditionsFacilityStatus_T aStatus, RTTIMESPEC aTimestamp)
+{
+    mData.mStatus = aStatus;
+    mData.mLastUpdated = aTimestamp;
+
+    return S_OK;
+}
+
