Index: /trunk/src/VBox/Main/ExtPackManagerImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/ExtPackManagerImpl.cpp	(revision 33474)
+++ /trunk/src/VBox/Main/ExtPackManagerImpl.cpp	(revision 33474)
@@ -0,0 +1,403 @@
+/* $Id$ */
+/** @file
+ * VirtualBox Main - interface for Extension Packs, VBoxSVC & VBoxC.
+ */
+
+/*
+ * Copyright (C) 2010 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.
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "ExtPackManagerImpl.h"
+
+#include <iprt/dir.h>
+#include <iprt/ldr.h>
+#include <iprt/param.h>
+#include <iprt/path.h>
+
+#include <VBox/com/array.h>
+#include "AutoCaller.h"
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+/**
+ * Private extension pack data.
+ */
+struct ExtPack::Data
+{
+    /** @name IExtPack Attributes.
+     * @{ */
+    /** The name. */
+    Utf8Str     strName;
+    /** The version string. */
+    Utf8Str     strVersion;
+    /** The revision. */
+    uint32_t    uRevision;
+    /** Whether it's usable or not. */
+    bool        fUsable;
+    /** Why it is unusable. */
+    Utf8Str     strWhyUnusable;
+    /** @}  */
+
+    /** Where the extension pack is located. */
+    Utf8Str     strPath;
+    /** The module handle of the main extension pack module. */
+    RTLDRMOD    hMainMod;
+};
+
+/** List of extension packs. */
+typedef std::list< ComObjPtr<ExtPack> > ExtPackList;
+
+/**
+ * Private extension pack manager data.
+ */
+struct ExtPackManager::Data
+{
+    /** Where the directory where the extension packs are installed. */
+    Utf8Str     strBasePath;
+    /** The list of installed extension packs. */
+    ExtPackList llInstalledExtPacks;
+};
+
+
+DEFINE_EMPTY_CTOR_DTOR(ExtPack)
+
+/**
+ * Called by ComObjPtr::createObject when creating the object.
+ *
+ * Just initialize the basic object state, do the rest in init().
+ *
+ * @returns S_OK.
+ */
+HRESULT ExtPack::FinalConstruct()
+{
+    m = NULL;
+    return S_OK;
+}
+
+/**
+ * Initializes the extension pack by reading its file.
+ *
+ * @returns COM status code.
+ * @param   a_pszName       The name of the extension pack.  This is also the
+ *                          name of the subdirector under @a a_pszParentDir
+ *                          where the extension pack is installed.
+ * @param   a_pszParentDir  The parent directory.
+ */
+HRESULT ExtPack::init(const char *a_pszName, const char *a_pszParentDir)
+{
+    /*
+     * Figure out where we live and allocate+initialize our private data.
+     */
+    char szDir[RTPATH_MAX];
+    int vrc = RTPathJoin(szDir, sizeof(szDir), a_pszParentDir, a_pszName);
+    AssertLogRelRCReturn(vrc, E_FAIL);
+
+    m = new Data;
+    m->strName          = a_pszName;
+    m->strVersion       = "";
+    m->uRevision        = 0;
+    m->fUsable          = false;
+    m->strWhyUnusable   = tr("ExtPack::init failed");
+
+    m->strPath          = szDir;
+    m->hMainMod         = NIL_RTLDRMOD;
+
+    /*
+     * Read the description file.
+     */
+
+
+    return S_OK;
+}
+
+/**
+ * COM cruft.
+ */
+void ExtPack::FinalRelease()
+{
+    uninit();
+}
+
+/**
+ * Do the actual cleanup.
+ */
+void ExtPack::uninit()
+{
+    /* Enclose the state transition Ready->InUninit->NotReady */
+    AutoUninitSpan autoUninitSpan(this);
+    if (!autoUninitSpan.uninitDone() && m != NULL)
+    {
+        if (m->hMainMod != NIL_RTLDRMOD)
+        {
+            RTLdrClose(m->hMainMod);
+            m->hMainMod = NIL_RTLDRMOD;
+        }
+
+        delete m;
+        m = NULL;
+    }
+}
+
+
+
+
+STDMETHODIMP ExtPack::COMGETTER(Name)(BSTR *a_pbstrName)
+{
+    CheckComArgOutPointerValid(a_pbstrName);
+
+    AutoCaller autoCaller(this);
+    HRESULT hrc = autoCaller.rc();
+    if (SUCCEEDED(hrc))
+        m->strName.cloneTo(a_pbstrName);
+    return hrc;
+}
+
+STDMETHODIMP ExtPack::COMGETTER(Version)(BSTR *a_pbstrVersion)
+{
+    CheckComArgOutPointerValid(a_pbstrVersion);
+
+    AutoCaller autoCaller(this);
+    HRESULT hrc = autoCaller.rc();
+    if (SUCCEEDED(hrc))
+        m->strVersion.cloneTo(a_pbstrVersion);
+    return hrc;
+}
+
+STDMETHODIMP ExtPack::COMGETTER(Revision)(ULONG *a_puRevision)
+{
+    CheckComArgOutPointerValid(a_puRevision);
+
+    AutoCaller autoCaller(this);
+    HRESULT hrc = autoCaller.rc();
+    if (SUCCEEDED(hrc))
+        *a_puRevision = m->uRevision;
+    return hrc;
+}
+
+STDMETHODIMP ExtPack::COMGETTER(Usable)(BOOL *a_pfUsable)
+{
+    CheckComArgOutPointerValid(a_pfUsable);
+
+    AutoCaller autoCaller(this);
+    HRESULT hrc = autoCaller.rc();
+    if (SUCCEEDED(hrc))
+        *a_pfUsable = m->fUsable;
+    return hrc;
+}
+
+STDMETHODIMP ExtPack::COMGETTER(WhyUnusable)(BSTR *a_pbstrWhy)
+{
+    CheckComArgOutPointerValid(a_pbstrWhy);
+
+    AutoCaller autoCaller(this);
+    HRESULT hrc = autoCaller.rc();
+    if (SUCCEEDED(hrc))
+        m->strWhyUnusable.cloneTo(a_pbstrWhy);
+    return hrc;
+}
+
+
+
+void *ExtPack::getCallbackTable()
+{
+    return NULL;
+}
+
+
+
+
+DEFINE_EMPTY_CTOR_DTOR(ExtPackManager)
+
+/**
+ * Called by ComObjPtr::createObject when creating the object.
+ *
+ * Just initialize the basic object state, do the rest in init().
+ *
+ * @returns S_OK.
+ */
+HRESULT ExtPackManager::FinalConstruct()
+{
+    m = NULL;
+    return S_OK;
+}
+
+/**
+ * Initializes the extension pack manager.
+ *
+ * @returns COM status code.
+ */
+HRESULT ExtPackManager::init()
+{
+    /*
+     * Figure some stuff out before creating the instance data.
+     */
+    char szBasePath[RTPATH_MAX];
+    int rc = RTPathAppPrivateArch(szBasePath, sizeof(szBasePath));
+    AssertLogRelRCReturn(rc, E_FAIL);
+    rc = RTPathAppend(szBasePath, sizeof(szBasePath), "ExtensionPacks");
+    AssertLogRelRCReturn(rc, E_FAIL);
+
+    /*
+     * Allocate and initialize the instance data.
+     */
+    m = new Data;
+    m->strBasePath = szBasePath;
+
+    /*
+     * Go looking for extensions.  The RTDirOpen may fail if nothing has been
+     * installed yet, or if root is paranoid and has revoked our access to them.
+     *
+     * We ASSUME that there are no files, directories or stuff in the directory
+     * that exceed the max name length in RTDIRENTRYEX.
+     */
+    PRTDIR pDir;
+    int vrc = RTDirOpen(&pDir, szBasePath);
+    if (RT_FAILURE(vrc))
+        return S_OK;
+    HRESULT hrc = S_OK;
+    for (;;)
+    {
+        RTDIRENTRYEX Entry;
+        vrc = RTDirReadEx(pDir, &Entry, NULL /*pcbDirEntry*/, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
+        if (RT_FAILURE(vrc))
+        {
+            AssertLogRelMsg(vrc == VERR_NO_MORE_FILES, ("%Rrc\n", vrc));
+            break;
+        }
+        if (   RTFS_IS_DIRECTORY(Entry.Info.Attr.fMode)
+            && strcmp(Entry.szName, ".")  != 0
+            && strcmp(Entry.szName, "..") != 0 )
+        {
+            /*
+             * All directories are extensions, the shall be nothing but
+             * extensions in this subdirectory.
+             */
+            ComObjPtr<ExtPack> NewExtPack;
+            HRESULT hrc2 = NewExtPack.createObject();
+            if (SUCCEEDED(hrc2))
+                hrc2 = NewExtPack->init(Entry.szName, szBasePath);
+            if (SUCCEEDED(hrc2))
+                m->llInstalledExtPacks.push_back(NewExtPack);
+            else if (SUCCEEDED(rc))
+                hrc = hrc2;
+        }
+    }
+    RTDirClose(pDir);
+
+    return hrc;
+}
+
+/**
+ * COM cruft.
+ */
+void ExtPackManager::FinalRelease()
+{
+    uninit();
+}
+
+/**
+ * Do the actual cleanup.
+ */
+void ExtPackManager::uninit()
+{
+    /* Enclose the state transition Ready->InUninit->NotReady */
+    AutoUninitSpan autoUninitSpan(this);
+    if (!autoUninitSpan.uninitDone() && m != NULL)
+    {
+        /** @todo do unload notifications */
+
+        delete m;
+        m = NULL;
+    }
+}
+
+
+STDMETHODIMP ExtPackManager::COMGETTER(InstalledExtPacks)(ComSafeArrayOut(IExtPack *, a_paExtPacks))
+{
+    CheckComArgSafeArrayNotNull(a_paExtPacks);
+
+    AutoCaller autoCaller(this);
+    HRESULT hrc = autoCaller.rc();
+    if (SUCCEEDED(hrc))
+    {
+        AutoReadLock autoLock(this COMMA_LOCKVAL_SRC_POS);
+
+        SafeIfaceArray<IExtPack> SaExtPacks(m->llInstalledExtPacks);
+        SaExtPacks.detachTo(ComSafeArrayOutArg(a_paExtPacks));
+    }
+
+    return hrc;
+}
+
+STDMETHODIMP ExtPackManager::Find(IN_BSTR a_bstrName, IExtPack **a_pExtPack)
+{
+    CheckComArgNotNull(a_bstrName);
+    CheckComArgOutPointerValid(a_pExtPack);
+    Utf8Str strName(a_bstrName);
+
+    AutoCaller autoCaller(this);
+    HRESULT hrc = autoCaller.rc();
+    if (SUCCEEDED(hrc))
+    {
+        AutoReadLock autoLock(this COMMA_LOCKVAL_SRC_POS);
+
+        hrc = VBOX_E_OBJECT_NOT_FOUND;
+        for (ExtPackList::iterator it = m->llInstalledExtPacks.begin();
+             it != m->llInstalledExtPacks.end();
+             it++)
+        {
+            ExtPack::Data *pExtPackData = (*it)->m;
+            if (   pExtPackData
+                && pExtPackData->strName.compare(strName) == 0)
+            {
+                (*it).queryInterfaceTo(a_pExtPack);
+                hrc = S_OK;
+                break;
+            }
+        }
+    }
+
+    return hrc;
+}
+
+STDMETHODIMP ExtPackManager::Install(IN_BSTR a_bstrTarball, BSTR *a_pbstrName)
+{
+    NOREF(a_bstrTarball); NOREF(a_pbstrName);
+    return E_NOTIMPL;
+}
+
+STDMETHODIMP ExtPackManager::Uninstall(IN_BSTR a_bstrName, BOOL a_fForcedRemoval)
+{
+    NOREF(a_bstrName); NOREF(a_fForcedRemoval);
+    return E_NOTIMPL;
+}
+
+
+
+int ExtPackManager::callAllConfigHooks(IConsole *a_pConsole, PVM a_pVM)
+{
+    NOREF(a_pConsole); NOREF(a_pVM);
+    return VINF_SUCCESS;
+}
+
+int ExtPackManager::callAllNewMachineHooks(IMachine *a_pMachine)
+{
+    NOREF(a_pMachine);
+    return VINF_SUCCESS;
+}
+
+/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Index: /trunk/src/VBox/Main/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Main/Makefile.kmk	(revision 33473)
+++ /trunk/src/VBox/Main/Makefile.kmk	(revision 33474)
@@ -228,8 +228,9 @@
 	$(if $(VBOX_USB_WITH_INOTIFY),VBOX_USB_WITH_INOTIFY,) \
 	$(if $(VBOX_WITH_LIVE_MIGRATION),VBOX_WITH_LIVE_MIGRATION,) \
+	$(if $(VBOX_WITH_EXTPACK),VBOX_WITH_EXTPACK,) \
 	$(if $(VBOX_WITH_VUSB),VBOX_WITH_VUSB,)
 ifdef VBOX_WITH_USB
  VBoxSVC_DEFS += \
-VBOX_WITH_USB \
+	VBOX_WITH_USB \
 	$(if $(VBOX_WITH_EHCI),VBOX_WITH_EHCI,) \
 	$(if $(VBOX_WITH_NEW_USB_CODE_ON_DARWIN),VBOX_WITH_NEW_USB_CODE_ON_DARWIN,)
@@ -320,5 +321,6 @@
 	$(if $(VBOX_WITH_VRDP),VRDPServerImpl.cpp,) \
 	$(if $(VBOX_WITH_XPCOM),xpcom/server.cpp,) \
-	$(VBOX_XML_SCHEMADEFS_CPP)
+	$(VBOX_XML_SCHEMADEFS_CPP) \
+	$(if $(VBOX_WITH_EXTPACK),ExtPackManagerImpl.cpp,)
 
 $(VBOX_AUTOGEN_EVENT_CPP): $(VBOX_PATH_MAIN_SRC)/idl/comimpl.xsl $(VBOX_XIDL_FILE) | $$(dir $$@)
@@ -564,19 +566,11 @@
 	$(if $(VBOX_WITH_PDM_ASYNC_COMPLETION),VBOX_WITH_PDM_ASYNC_COMPLETION,) \
 	$(if $(VBOX_WITH_LIVE_MIGRATION),VBOX_WITH_LIVE_MIGRATION,) \
-	$(if $(VBOX_WITH_VUSB),VBOX_WITH_VUSB,)
-ifdef VBOX_WITH_USB
-VBoxC_DEFS += \
-	VBOX_WITH_USB \
-	$(if $(VBOX_WITH_EHCI),VBOX_WITH_EHCI,)
-endif
-ifdef VBOX_WITH_OLD_VBVA_LOCK
-VBoxC_DEFS += VBOX_WITH_OLD_VBVA_LOCK
-endif
-ifdef VBOX_WITH_HGSMI
-VBoxC_DEFS += VBOX_WITH_HGSMI
-endif
-ifdef VBOX_WITH_VIDEOHWACCEL
-VBoxC_DEFS += VBOX_WITH_VIDEOHWACCEL
-endif
+	$(if $(VBOX_WITH_VUSB),VBOX_WITH_VUSB,) \
+	$(if $(VBOX_WITH_OLD_VBVA_LOCK),VBOX_WITH_OLD_VBVA_LOCK,) \
+	$(if $(VBOX_WITH_HGSMI),VBOX_WITH_HGSMI,) \
+	$(if $(VBOX_WITH_VIDEOHWACCEL),VBOX_WITH_VIDEOHWACCEL,) \
+	$(if $(VBOX_WITH_USB),VBOX_WITH_USB,) \
+	$(if-expr defined(VBOX_WITH_EHCI) && defined(VBOX_WITH_USB),VBOX_WITH_EHCI,) \
+	$(if $(VBOX_WITH_EXTPACK),VBOX_WITH_EXTPACK,)
 
 VBoxC_DEFS.darwin.x86 = VBOX_WITH_2X_4GB_ADDR_SPACE
@@ -645,5 +639,6 @@
 	EventImpl.cpp \
 	$(VBOX_AUTOGEN_EVENT_CPP) \
-	$(VBOX_XML_SCHEMADEFS_CPP)
+	$(VBOX_XML_SCHEMADEFS_CPP) \
+	$(if $(VBOX_WITH_EXTPACK),ExtPackManagerImpl.cpp,)
 VBoxC_SOURCES.win = \
 	win/dllmain.cpp \
Index: /trunk/src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 33473)
+++ /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 33474)
@@ -13953,4 +13953,109 @@
   </interface>
 
+  <!--
+  // IExtPackManager
+  /////////////////////////////////////////////////////////////////////////
+  -->
+
+  <interface
+    name="IExtPack" extends="$unknown"
+    uuid="1b69431b-b22f-454a-977d-7d50986defcb"
+    wsmap="suppress"
+    >
+    <desc>
+      Interface for querying interfaces and information relating to an
+      extension pack.  The extension pack specific interfaces can be queried
+      via the IUnknown::QueryInterface method.
+    </desc>
+    <attribute name="name" type="wstring" readonly="yes">
+      <desc>The extension pack name.  This is unique.</desc>
+    </attribute>
+    <attribute name="version" type="wstring" readonly="yes">
+      <desc>
+        The extension pack version string.  This is on the same form as
+        other VirtualBox version strings, i.e.: "1.2.3", "1.2.3_BETA1",
+        "1.2.3-OSE", "1.2.3r45678", "1.2.3r45678-OSE", "1.2.3_BETA1-r45678"
+        or "1.2.3_BETA1-r45678-OSE"
+      </desc>
+    </attribute>
+    <attribute name="revision" type="unsigned long" readonly="yes">
+      <desc>The extension pack internal revision number.</desc>
+    </attribute>
+    <attribute name="usable" type="boolean" readonly="yes">
+      <desc>
+        Indicates whether the extension pack is usable or not.  An
+        extension pack that is not compatible with the current VirtualBox
+        version will be flagged as not usable.
+      </desc>
+    </attribute>
+    <attribute name="whyUnusable" type="wstring" readonly="yes">
+      <desc>
+        String indicating why the extension pack is not usable.  This is an
+        empty string if usable and always a non-empty string if not usable.
+      </desc>
+    </attribute>
+  </interface>
+
+  <interface
+    name="IExtPackManager" extends="$unknown"
+    uuid="ba1fbfca-53f1-471c-b5a1-416386f0f52b"
+    wsmap="suppress"
+    >
+    <desc>
+      Interface for managing VirtualBox Extension Packs.
+
+      TODO: Describe extension packs, how they are managed and how to create
+            one.
+    </desc>
+
+    <attribute name="installedExtPacks" type="IExtPack" safearray="yes" readonly="yes">
+      <desc>
+        List of the installed extension packs.
+      </desc>
+    </attribute>
+
+    <method name="find">
+      <desc>
+        Returns the extension pack with the specified name if found.
+
+        <result name="VBOX_E_OBJECT_NOT_FOUND">
+          No extension pack matching @a name was found.
+        </result>
+      </desc>
+      <param name="name" type="wstring" dir="in">
+        <desc>The name of the extension pack to locate.</desc>
+      </param>
+      <param name="returnData" type="IExtPack" dir="return">
+        <desc>The extension pack if found.</desc>
+      </param>
+    </method>
+
+    <method name="install">
+      <param name="path" type="wstring" dir="in">
+        <desc>The path of the extension pack tarball.</desc>
+      </param>
+      <param name="name" type="wstring" dir="out">
+        <desc>The name of the installed extension pack.</desc>
+      </param>
+    </method>
+
+    <method name="uninstall">
+      <desc>Uninstalls an extension pack, removing all related files.</desc>
+      <param name="name" type="wstring" dir="in">
+        <desc>The name of the extension pack to uninstall.</desc>
+      </param>
+      <param name="forcedRemoval" type="boolean" dir="in">
+        <desc>
+          Forced removal of the extension pack.  This means that the uninstall
+          hook will not be called.
+        </desc>
+      </param>
+    </method>
+  </interface>
+
+  <!--
+  // Events
+  /////////////////////////////////////////////////////////////////////////
+  -->
   <enum
      name="VBoxEventType"
Index: /trunk/src/VBox/Main/include/ExtPackManagerImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/ExtPackManagerImpl.h	(revision 33474)
+++ /trunk/src/VBox/Main/include/ExtPackManagerImpl.h	(revision 33474)
@@ -0,0 +1,122 @@
+/* $Id$ */
+/** @file
+ * VirtualBox Main - interface for Extension Packs, VBoxSVC & VBoxC.
+ */
+
+/*
+ * Copyright (C) 2010 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_EXTPACKMANAGERIMPL
+#define ____H_EXTPACKMANAGERIMPL
+
+#include "VirtualBoxBase.h"
+#include <VBox/ExtPack/ExtPack.h>
+
+
+/**
+ * An extension pack.
+ *
+ * This
+ */
+class ATL_NO_VTABLE ExtPack :
+    public VirtualBoxBase,
+    VBOX_SCRIPTABLE_IMPL(IExtPack)
+{
+public:
+    /** @name COM and internal init/term/mapping cruft.
+     * @{ */
+    VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT(ExtPack, IExtPack)
+    DECLARE_NOT_AGGREGATABLE(ExtPack)
+    DECLARE_PROTECT_FINAL_CONSTRUCT()
+    BEGIN_COM_MAP(ExtPack)
+        COM_INTERFACE_ENTRY(ISupportErrorInfo)
+        COM_INTERFACE_ENTRY(IExtPack)
+        COM_INTERFACE_ENTRY(IDispatch)
+    END_COM_MAP()
+    DECLARE_EMPTY_CTOR_DTOR(ExtPack)
+
+    HRESULT     FinalConstruct();
+    void        FinalRelease();
+    HRESULT     init(const char *a_pszName, const char *a_pszParentDir);
+    void        uninit();
+    /** @}  */
+
+    /** @name IExtPack interfaces
+     * @{ */
+    STDMETHOD(COMGETTER(Name))(BSTR *a_pbstrName);
+    STDMETHOD(COMGETTER(Version))(BSTR *a_pbstrVersion);
+    STDMETHOD(COMGETTER(Revision))(ULONG *a_puRevision);
+    STDMETHOD(COMGETTER(Usable))(BOOL *a_pfUsable);
+    STDMETHOD(COMGETTER(WhyUnusable))(BSTR *a_pbstrWhy);
+    /** @}  */
+
+    /** @name Internal interfaces used by ExtPackManager.
+     * @{ */
+    void *getCallbackTable();
+    /** @}  */
+
+private:
+    struct Data;
+    /** Pointer to the private instance. */
+    Data *m;
+
+    friend class ExtPackManager;
+};
+
+
+/**
+ * Extension pack manager.
+ */
+class ATL_NO_VTABLE ExtPackManager :
+    public VirtualBoxBase,
+    VBOX_SCRIPTABLE_IMPL(IExtPackManager)
+{
+    /** @name COM and internal init/term/mapping cruft.
+     * @{ */
+    VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT(ExtPackManager, IExtPackManager)
+    DECLARE_NOT_AGGREGATABLE(ExtPackManager)
+    DECLARE_PROTECT_FINAL_CONSTRUCT()
+    BEGIN_COM_MAP(ExtPackManager)
+        COM_INTERFACE_ENTRY(ISupportErrorInfo)
+        COM_INTERFACE_ENTRY(IExtPackManager)
+        COM_INTERFACE_ENTRY(IDispatch)
+    END_COM_MAP()
+    DECLARE_EMPTY_CTOR_DTOR(ExtPackManager)
+
+    HRESULT     FinalConstruct();
+    void        FinalRelease();
+    HRESULT     init();
+    void        uninit();
+    /** @}  */
+
+    /** @name IExtPack interfaces
+     * @{ */
+    STDMETHOD(COMGETTER(InstalledExtPacks))(ComSafeArrayOut(IExtPack *, a_paExtPacks));
+    STDMETHOD(Find)(IN_BSTR a_bstrName, IExtPack **a_pExtPack);
+    STDMETHOD(Install)(IN_BSTR a_bstrTarball, BSTR *a_pbstrName);
+    STDMETHOD(Uninstall)(IN_BSTR a_bstrName, BOOL a_fForcedRemoval);
+    /** @}  */
+
+    /** @name Internal interfaces used by other Main classes.
+     * @{ */
+    int callAllConfigHooks(IConsole *a_pConsole, PVM a_pVM);
+    int callAllNewMachineHooks(IMachine *a_pMachine);
+    /** @}  */
+
+private:
+    struct Data;
+    /** Pointer to the private instance. */
+    Data *m;
+};
+
+#endif
+/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Index: /trunk/src/VBox/Main/xpcom/server.cpp
===================================================================
--- /trunk/src/VBox/Main/xpcom/server.cpp	(revision 33473)
+++ /trunk/src/VBox/Main/xpcom/server.cpp	(revision 33474)
@@ -92,4 +92,7 @@
 #include <AudioAdapterImpl.h>
 #include <SystemPropertiesImpl.h>
+#ifdef VBOX_WITH_EXTPACK
+# include <ExtPackManagerImpl.h>
+#endif
 
 /* implement nsISupports parts of our objects with support for nsIClassInfo */
@@ -202,4 +205,12 @@
 NS_DECL_CLASSINFO(BIOSSettings)
 NS_IMPL_THREADSAFE_ISUPPORTS1_CI(BIOSSettings, IBIOSSettings)
+
+#ifdef VBOX_WITH_EXTPACK
+NS_DECL_CLASSINFO(ExtPack)
+NS_IMPL_THREADSAFE_ISUPPORTS1_CI(ExtPack, IExtPack)
+
+NS_DECL_CLASSINFO(ExtPackManager)
+NS_IMPL_THREADSAFE_ISUPPORTS1_CI(ExtPackManager, IExtPackManager)
+#endif
 
 ////////////////////////////////////////////////////////////////////////////////
