Index: /trunk/include/VBox/com/errorprint.h
===================================================================
--- /trunk/include/VBox/com/errorprint.h	(revision 33765)
+++ /trunk/include/VBox/com/errorprint.h	(revision 33766)
@@ -57,4 +57,33 @@
 
 /**
+ * Same as CHECK_ERROR except that it also executes the statement |stmt| on
+ * failure.
+ */
+#define CHECK_ERROR_STMT(iface, method, stmt) \
+    do { \
+        rc = iface->method; \
+        if (FAILED(rc)) \
+        { \
+            com::GlueHandleComError(iface, #method, rc, __FILE__, __LINE__); \
+            stmt; \
+        } \
+    } while (0)
+
+/**
+ * Same as CHECK_ERROR_STMT except that it uses an internal variable |hrcCheck|
+ * for holding the result.
+ */
+#define CHECK_ERROR2_STMT(iface, method, stmt) \
+    do { \
+        HRESULT hrcCheck = iface->method; \
+        if (FAILED(hrcCheck)) \
+        { \
+            com::GlueHandleComError(iface, #method, hrcCheck, __FILE__, __LINE__); \
+            stmt; \
+        } \
+    } while (0)
+
+
+/**
  *  Does the same as CHECK_ERROR(), but executes the |break| statement on
  *  failure.
@@ -100,4 +129,27 @@
 
 /**
+ * Does the same as CHECK_ERROR(), but returns @a ret on failure.
+ *
+ * Unlike CHECK_ERROR and CHECK_ERROR_RET, this macro does not presuppose a
+ * |rc| variable but instead employs a local variable |hrcCheck| in its own
+ * scope.  This |hrcCheck| variable can be referenced by the @a rcRet
+ * parameter.
+ *
+ * @param   iface       The interface pointer (can be a smart pointer object).
+ * @param   method      The method to invoke together with the parameters.
+ * @param   rcRet       What to return on failure.  Use |hrcCheck| to return
+ *                      the status code of the method call.
+ */
+#define CHECK_ERROR2_RET(iface, method, rcRet) \
+    do { \
+        HRESULT hrcCheck = iface->method; \
+        if (FAILED(hrcCheck)) \
+        { \
+            com::GlueHandleComError(iface, #method, hrcCheck, __FILE__, __LINE__); \
+            return (rcRet); \
+        } \
+    } while (0)
+
+/**
  *  Asserts the given expression is true. When the expression is false, prints
  *  a line containing the failed function/line/file; otherwise does nothing.
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp	(revision 33765)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp	(revision 33766)
@@ -401,4 +401,5 @@
             { "dhcpserver",       USAGE_DHCPSERVER,        handleDHCPServer},
             { "vrde",             USAGE_VRDE,              handleVRDE},
+            { "extpack",          USAGE_EXTPACK,           handleExtPack},
             { NULL,               0,                       NULL }
         };
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManage.h
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManage.h	(revision 33765)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManage.h	(revision 33766)
@@ -98,4 +98,5 @@
 #define USAGE_PASSWORDHASH          RT_BIT_64(54)
 #define USAGE_VRDE                  RT_BIT_64(55)
+#define USAGE_EXTPACK               RT_BIT_64(56)
 #define USAGE_ALL                   (~(uint64_t)0)
 /** @} */
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp	(revision 33765)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp	(revision 33766)
@@ -115,5 +115,5 @@
                      "                            hostcpuids|hddbackends|hdds|dvds|floppies|\n"
                      "                            usbhost|usbfilters|systemproperties|\n"
-                     "                            vrdelibraries\n"
+                     "                            vrdelibraries|extpacks\n"
                      "\n");
     }
@@ -727,4 +727,11 @@
                      "\n");
     }
+    if (u64Cmd & USAGE_EXTPACK)
+    {
+        RTStrmPrintf(pStrm,
+                     "VBoxManage extpack          install <tarball>\n"
+                     "VBoxManage extpack          uninstall [--force] <name>\n"
+                     "\n");
+    }
 }
 
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageList.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageList.cpp	(revision 33765)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageList.cpp	(revision 33766)
@@ -185,4 +185,57 @@
     }
 }
+
+
+/**
+ * List extension packs.
+ *
+ * @returns See produceList.
+ * @param   rptrVirtualBox      Reference to the IVirtualBox smart pointer.
+ */
+static HRESULT listExtensionPacks(const ComPtr<IVirtualBox> &rptrVirtualBox)
+{
+    ComObjPtr<IExtPackManager> ptrExtPackMgr;
+    CHECK_ERROR2_RET(rptrVirtualBox, COMGETTER(ExtensionPackManager)(ptrExtPackMgr.asOutParam()), hrcCheck);
+
+    SafeIfaceArray<IExtPack> extPacks;
+    CHECK_ERROR2_RET(ptrExtPackMgr, COMGETTER(InstalledExtPacks)(ComSafeArrayAsOutParam(extPacks)), hrcCheck);
+    RTPrintf("Extension Packs: %u\n", extPacks.size());
+
+    HRESULT hrc = S_OK;
+    for (size_t i = 0; i < extPacks.size(); i++)
+    {
+        /* Read all the properties. */
+        Bstr    bstrName;
+        CHECK_ERROR2_STMT(extPacks[i], COMGETTER(Name)(bstrName.asOutParam()),          hrc = hrcCheck; bstrName.setNull());
+        Bstr    bstrDesc;
+        CHECK_ERROR2_STMT(extPacks[i], COMGETTER(Description)(bstrDesc.asOutParam()),   hrc = hrcCheck; bstrDesc.setNull());
+        Bstr    bstrVersion;
+        CHECK_ERROR2_STMT(extPacks[i], COMGETTER(Version)(bstrVersion.asOutParam()),    hrc = hrcCheck; bstrVersion.setNull());
+        ULONG   uRevision;
+        CHECK_ERROR2_STMT(extPacks[i], COMGETTER(Revision)(&uRevision),                 hrc = hrcCheck; uRevision = 0);
+        BOOL    fUsable;
+        CHECK_ERROR2_STMT(extPacks[i], COMGETTER(Usable)(&fUsable),                     hrc = hrcCheck; fUsable = FALSE);
+        Bstr    bstrWhy;
+        CHECK_ERROR2_STMT(extPacks[i], COMGETTER(WhyUnusable)(bstrWhy.asOutParam()),    hrc = hrcCheck; bstrWhy.setNull());
+
+        /* Display them. */
+        if (i)
+            RTPrintf("\n");
+        RTPrintf("Pack no.%2zu:   %lS\n"
+                 "Version:      %lS\n"
+                 "Revision:     %u\n"
+                 "Description:  %lS\n"
+                 "Usable:       %RTbool\n"
+                 "Why unusable: %lS\n",
+                 i, bstrName.raw(),
+                 bstrVersion.raw(),
+                 uRevision,
+                 bstrDesc.raw(),
+                 fUsable != FALSE,
+                 bstrWhy.raw());
+    }
+    return hrc;
+}
+
 
 /**
@@ -211,5 +264,6 @@
     kListSystemProperties,
     kListDhcpServers,
-    kListVrdeLibraries
+    kListVrdeLibraries,
+    kListExtPacks
 };
 
@@ -613,5 +667,5 @@
             CHECK_ERROR_RET(rptrVirtualBox, COMGETTER(Host)(Host.asOutParam()), 1);
 
-            SafeIfaceArray <IHostUSBDevice> CollPtr;
+            SafeIfaceArray<IHostUSBDevice> CollPtr;
             CHECK_ERROR_RET(Host, COMGETTER(USBDevices)(ComSafeArrayAsOutParam(CollPtr)), 1);
 
@@ -870,11 +924,18 @@
             SafeArray<BSTR> libs;
             CHECK_ERROR(rptrVirtualBox, VRDEListLibraries(ComSafeArrayAsOutParam(libs)));
-            for (size_t i = 0; i < libs.size(); ++i)
-            {
-                Bstr bstrName(libs[i]);
-                RTPrintf("%lS\n", bstrName.raw());
-            }
-            break;
-        }
+            if (SUCCEEDED(rc))
+            {
+                for (size_t i = 0; i < libs.size(); ++i)
+                {
+                    Bstr bstrName(libs[i]);
+                    RTPrintf("%lS\n", bstrName.raw());
+                }
+            }
+            break;
+        }
+
+        case kListExtPacks:
+            rc = listExtensionPacks(rptrVirtualBox);
+            break;
 
         /* No default here, want gcc warnings. */
@@ -922,4 +983,5 @@
         { "dhcpservers",        kListDhcpServers,        RTGETOPT_REQ_NOTHING },
         { "vrdelibraries",      kListVrdeLibraries,      RTGETOPT_REQ_NOTHING },
+        { "extpacks",           kListExtPacks,           RTGETOPT_REQ_NOTHING },
     };
 
@@ -964,4 +1026,5 @@
             case kListDhcpServers:
             case kListVrdeLibraries:
+            case kListExtPacks:
                 enmOptCommand = (enum enmListType)ch;
                 if (fOptMultiple)
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageMisc.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageMisc.cpp	(revision 33765)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageMisc.cpp	(revision 33766)
@@ -911,2 +911,69 @@
 }
 
+int handleExtPack(HandlerArg *a)
+{
+    if (a->argc < 2)
+        return errorSyntax(USAGE_EXTPACK, "Incorrect number of parameters");
+
+    ComObjPtr<IExtPackManager> ptrExtPackMgr;
+    CHECK_ERROR2_RET(a->virtualBox, COMGETTER(ExtensionPackManager)(ptrExtPackMgr.asOutParam()), RTEXITCODE_FAILURE);
+
+    RTGETOPTSTATE   GetState;
+    RTGETOPTUNION   ValueUnion;
+    int             ch;
+    HRESULT         hrc = S_OK;
+
+    if (!strcmp(a->argv[0], "install"))
+    {
+        if (a->argc > 2)
+            return errorSyntax(USAGE_EXTPACK, "Too many parameters given to \"extpack install\"");
+
+        Bstr bstrTarball(a->argv[1]);
+        Bstr bstrName;
+        CHECK_ERROR2_RET(ptrExtPackMgr, Install(bstrTarball.raw(), bstrName.asOutParam()), RTEXITCODE_FAILURE);
+        RTPrintf("Successfully installed \"%lS\".\n", bstrName.raw());
+    }
+    else if (!strcmp(a->argv[0], "uninstall"))
+    {
+        const char *pszName = NULL;
+        bool        fForced = false;
+
+        static const RTGETOPTDEF s_aUninstallOptions[] =
+        {
+            { "--forced",  'f', RTGETOPT_REQ_NOTHING },
+        };
+
+        RTGetOptInit(&GetState, a->argc, a->argv, s_aUninstallOptions, RT_ELEMENTS(s_aUninstallOptions),
+                     1, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
+        while ((ch = RTGetOpt(&GetState, &ValueUnion)))
+        {
+            switch (ch)
+            {
+                case 'f':
+                    fForced = true;
+                    break;
+
+                case VINF_GETOPT_NOT_OPTION:
+                    if (pszName)
+                        return errorSyntax(USAGE_EXTPACK, "Too many extension pack names given to \"extpack uninstall\"");
+                    pszName = ValueUnion.psz;
+                    break;
+
+                default:
+                    return errorGetOpt(USAGE_EXTPACK, ch, &ValueUnion);
+            }
+        }
+        if (!pszName)
+            return errorSyntax(USAGE_EXTPACK, "Not extension pack name was given to \"extpack uninstall\"");
+
+        Bstr bstrName(pszName);
+        CHECK_ERROR2_RET(ptrExtPackMgr, Uninstall(bstrName.raw(), fForced), RTEXITCODE_FAILURE);
+        RTPrintf("Successfully uninstalled \"%s\".\n", pszName);
+    }
+    else
+        return errorSyntax(USAGE_EXTPACK, "Unknown command \"%s\"", a->argv[0]);
+
+    return RTEXITCODE_SUCCESS;
+}
+
+
