Index: /trunk/include/VBox/ExtPack/ExtPack.h
===================================================================
--- /trunk/include/VBox/ExtPack/ExtPack.h	(revision 73824)
+++ /trunk/include/VBox/ExtPack/ExtPack.h	(revision 73825)
@@ -190,4 +190,93 @@
                                                  const char *pszPluginLibrary));
 
+    /**
+     * Creates an IProgress object instance for a long running extension
+     * pack provided API operation which is executed asynchronously.
+     *
+     * This implicitly creates a cancellable progress object, since anything
+     * else is user unfriendly. You need to design your code to handle
+     * cancellation with reasonable response time.
+     *
+     * @returns COM status code.
+     * @param   pHlp            Pointer to this helper structure.
+     * @param   pInitiator      Pointer to the initiating object.
+     * @param   pcszDescription Description of the overall task.
+     * @param   cOperations     Number of operations for this task.
+     * @param   uTotalOperationsWeight        Overall weight for the entire task.
+     * @param   pcszFirstOperationDescription Description of the first operation.
+     * @param   uFirstOperationWeight         Weight for the first operation.
+     * @param   ppProgressOut   Output parameter for the IProgress object reference.
+     */
+    DECLR3CALLBACKMEMBER(uint32_t, pfnCreateProgress,(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IUnknown) *pInitiator,
+                                                      const char *pcszDescription, uint32_t cOperations,
+                                                      uint32_t uTotalOperationsWeight, const char *pcszFirstOperationDescription,
+                                                      uint32_t uFirstOperationWeight, VBOXEXTPACK_IF_CS(IProgress) **ppProgressOut));
+
+    /**
+     * Checks if the Progress object is marked as canceled.
+     *
+     * @returns COM status code.
+     * @param   pHlp            Pointer to this helper structure.
+     * @param   pProgress       Pointer to the IProgress object reference returned
+     *                          by pfnCreateProgress.
+     * @param   pfCanceled      @c true if canceled, @c false otherwise.
+     */
+    DECLR3CALLBACKMEMBER(uint32_t, pfnGetCanceledProgress,(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IProgress) *pProgress,
+                                                           bool *pfCanceled));
+
+    /**
+     * Updates the percentage value of the current operation of the
+     * Progress object.
+     *
+     * @returns COM status code.
+     * @param   pHlp            Pointer to this helper structure.
+     * @param   pProgress       Pointer to the IProgress object reference returned
+     *                          by pfnCreateProgress.
+     * @param   uPercent        Result of the overall task.
+     */
+    DECLR3CALLBACKMEMBER(uint32_t, pfnUpdateProgress,(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IProgress) *pProgress,
+                                                      uint32_t uPercent));
+
+    /**
+     * Signals that the current operation is successfully completed and
+     * advances to the next operation. The operation percentage is reset
+     * to 0.
+     *
+     * If the operation count is exceeded this returns an error.
+     *
+     * @returns COM status code.
+     * @param   pHlp            Pointer to this helper structure.
+     * @param   pProgress       Pointer to the IProgress object reference returned
+     *                          by pfnCreateProgress.
+     * @param   pcszNextOperationDescription Description of the next operation.
+     * @param   uNextOperationWeight         Weight for the next operation.
+     */
+    DECLR3CALLBACKMEMBER(uint32_t, pfnNextOperationProgress,(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IProgress) *pProgress,
+                                                             const char *pcszNextOperationDescription,
+                                                             uint32_t uNextOperationWeight));
+
+    /**
+     * Marks the whole task as complete and sets the result code.
+     *
+     * If the result code indicates a failure then this method will store
+     * the currently set COM error info from the current thread in the
+     * the errorInfo attribute of this Progress object instance. If there
+     * is no error information available then an error is returned.
+     *
+     * If the result code indicates success then the task is terminated,
+     * without paying attention to the current operation being the last.
+     *
+     * Note that this must be called only once for the given Progress
+     * object. Subsequent calls will return errors.
+     *
+     * @returns COM status code.
+     * @param   pHlp            Pointer to this helper structure.
+     * @param   pProgress       Pointer to the IProgress object reference returned
+     *                          by pfnCreateProgress.
+     * @param   uResultCode     Result of the overall task.
+     */
+    DECLR3CALLBACKMEMBER(uint32_t, pfnCompleteProgress,(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IProgress) *pProgress,
+                                                        uint32_t uResultCode));
+
     DECLR3CALLBACKMEMBER(int, pfnReserved1,(PCVBOXEXTPACKHLP pHlp)); /**< Reserved for minor structure revisions. */
     DECLR3CALLBACKMEMBER(int, pfnReserved2,(PCVBOXEXTPACKHLP pHlp)); /**< Reserved for minor structure revisions. */
@@ -201,5 +290,5 @@
 } VBOXEXTPACKHLP;
 /** Current version of the VBOXEXTPACKHLP structure.  */
-#define VBOXEXTPACKHLP_VERSION          RT_MAKE_U32(2, 1)
+#define VBOXEXTPACKHLP_VERSION          RT_MAKE_U32(3, 0)
 
 
Index: /trunk/src/VBox/Main/include/ExtPackManagerImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/ExtPackManagerImpl.h	(revision 73824)
+++ /trunk/src/VBox/Main/include/ExtPackManagerImpl.h	(revision 73825)
@@ -103,5 +103,5 @@
     HRESULT     FinalConstruct();
     void        FinalRelease();
-    HRESULT     initWithDir(VBOXEXTPACKCTX a_enmContext, const char *a_pszName, const char *a_pszDir);
+    HRESULT     initWithDir(VirtualBox *a_pVirtualBox, VBOXEXTPACKCTX a_enmContext, const char *a_pszName, const char *a_pszDir);
     void        uninit();
     RTMEMEF_NEW_AND_DELETE_OPERATORS();
@@ -151,4 +151,17 @@
     static DECLCALLBACK(int)    i_hlpLoadVDPlugin(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IVirtualBox) *pVirtualBox, const char *pszPluginLibrary);
     static DECLCALLBACK(int)    i_hlpUnloadVDPlugin(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IVirtualBox) *pVirtualBox, const char *pszPluginLibrary);
+    static DECLCALLBACK(uint32_t) i_hlpCreateProgress(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IUnknown) *pInitiator,
+                                                      const char *pcszDescription, uint32_t cOperations,
+                                                      uint32_t uTotalOperationsWeight, const char *pcszFirstOperationDescription,
+                                                      uint32_t uFirstOperationWeight, VBOXEXTPACK_IF_CS(IProgress) **ppProgressOut);
+    static DECLCALLBACK(uint32_t) i_hlpGetCanceledProgress(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IProgress) *pProgress,
+                                                           bool *pfCanceled);
+    static DECLCALLBACK(uint32_t) i_hlpUpdateProgress(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IProgress) *pProgress,
+                                                      uint32_t uPercent);
+    static DECLCALLBACK(uint32_t) i_hlpNextOperationProgress(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IProgress) *pProgress,
+                                                             const char *pcszNextOperationDescription,
+                                                             uint32_t uNextOperationWeight);
+    static DECLCALLBACK(uint32_t) i_hlpCompleteProgress(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IProgress) *pProgress,
+                                                        uint32_t uResultCode);
     static DECLCALLBACK(int)    i_hlpReservedN(PCVBOXEXTPACKHLP pHlp);
     /** @}  */
Index: /trunk/src/VBox/Main/src-all/ExtPackManagerImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-all/ExtPackManagerImpl.cpp	(revision 73824)
+++ /trunk/src/VBox/Main/src-all/ExtPackManagerImpl.cpp	(revision 73825)
@@ -143,4 +143,8 @@
     /** Set if we've made the pfnVirtualBoxReady or pfnConsoleReady call. */
     bool                fMadeReadyCall;
+#ifndef VBOX_COM_INPROC
+    /** Pointer to the VirtualBox object so we can create a progress object. */
+    VirtualBox         *pVirtualBox;
+#endif
 
     RTMEMEF_NEW_AND_DELETE_OPERATORS();
@@ -720,4 +724,5 @@
  *
  * @returns COM status code.
+ * @param   a_pVirtualBox   The VirtualBox object.
  * @param   a_enmContext    The context we're in.
  * @param   a_pszName       The name of the extension pack.  This is also the
@@ -726,5 +731,5 @@
  * @param   a_pszDir        The extension pack directory name.
  */
-HRESULT ExtPack::initWithDir(VBOXEXTPACKCTX a_enmContext, const char *a_pszName, const char *a_pszDir)
+HRESULT ExtPack::initWithDir(VirtualBox *a_pVirtualBox, VBOXEXTPACKCTX a_enmContext, const char *a_pszName, const char *a_pszDir)
 {
     AutoInitSpan autoInitSpan(this);
@@ -744,4 +749,9 @@
         /* pfnLoadVDPlugin      = */ ExtPack::i_hlpLoadVDPlugin,
         /* pfnUnloadVDPlugin    = */ ExtPack::i_hlpUnloadVDPlugin,
+        /* pfnCreateProgress    = */ ExtPack::i_hlpCreateProgress,
+        /* pfnGetCanceledProgress = */ ExtPack::i_hlpGetCanceledProgress,
+        /* pfnUpdateProgress    = */ ExtPack::i_hlpUpdateProgress,
+        /* pfnNextOperationProgress = */ ExtPack::i_hlpNextOperationProgress,
+        /* pfnCompleteProgress  = */ ExtPack::i_hlpCompleteProgress,
         /* pfnReserved1         = */ ExtPack::i_hlpReservedN,
         /* pfnReserved2         = */ ExtPack::i_hlpReservedN,
@@ -774,4 +784,9 @@
     m->enmContext                   = a_enmContext;
     m->fMadeReadyCall               = false;
+#ifndef VBOX_COM_INPROC
+    m->pVirtualBox                  = a_pVirtualBox;
+#else
+    RT_NOREF(a_pVirtualBox);
+#endif
 
     /*
@@ -1723,4 +1738,112 @@
 }
 
+/*static*/ DECLCALLBACK(uint32_t)
+ExtPack::i_hlpCreateProgress(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IUnknown) *pInitiator,
+                             const char *pcszDescription, uint32_t cOperations,
+                             uint32_t uTotalOperationsWeight, const char *pcszFirstOperationDescription,
+                             uint32_t uFirstOperationWeight, VBOXEXTPACK_IF_CS(IProgress) **ppProgressOut)
+{
+    /*
+     * Validate the input and get our bearings.
+     */
+    AssertPtrReturn(pcszDescription, E_INVALIDARG);
+    AssertReturn(cOperations >= 1, E_INVALIDARG);
+    AssertReturn(uTotalOperationsWeight >= 1, E_INVALIDARG);
+    AssertPtrReturn(pcszFirstOperationDescription, E_INVALIDARG);
+    AssertReturn(uFirstOperationWeight >= 1, E_INVALIDARG);
+    AssertPtrReturn(ppProgressOut, E_INVALIDARG);
+
+    AssertPtrReturn(pHlp, VERR_INVALID_POINTER);
+    AssertReturn(pHlp->u32Version == VBOXEXTPACKHLP_VERSION, VERR_INVALID_POINTER);
+#ifndef VBOX_COM_INPROC
+    ExtPack::Data *m = RT_FROM_CPP_MEMBER(pHlp, Data, Hlp);
+#endif
+
+    ComObjPtr<Progress> pProgress;
+    HRESULT hrc = pProgress.createObject();
+    if (FAILED(hrc))
+        return hrc;
+    hrc = pProgress->init(
+#ifndef VBOX_COM_INPROC
+                          m->pVirtualBox,
+#endif
+                          pInitiator, pcszDescription, TRUE /* aCancelable */,
+                          cOperations, uTotalOperationsWeight,
+                          pcszFirstOperationDescription, uFirstOperationWeight);
+    if (FAILED(hrc))
+        return hrc;
+
+    return pProgress.queryInterfaceTo(ppProgressOut);
+}
+
+/*static*/ DECLCALLBACK(uint32_t)
+ExtPack::i_hlpGetCanceledProgress(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IProgress) *pProgress,
+                                  bool *pfCanceled)
+{
+    /*
+     * Validate the input and get our bearings.
+     */
+    AssertPtrReturn(pProgress, E_INVALIDARG);
+    AssertPtrReturn(pfCanceled, E_INVALIDARG);
+
+    AssertPtrReturn(pHlp, VERR_INVALID_POINTER);
+    AssertReturn(pHlp->u32Version == VBOXEXTPACKHLP_VERSION, VERR_INVALID_POINTER);
+
+    BOOL fCanceled = FALSE;
+    HRESULT hrc = pProgress->GetCanceled(&fCanceled);
+    *pfCanceled  = !!fCanceled;
+    return hrc;
+}
+
+/*static*/ DECLCALLBACK(uint32_t)
+ExtPack::i_hlpUpdateProgress(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IProgress) *pProgress,
+                             uint32_t uPercent)
+{
+    /*
+     * Validate the input and get our bearings.
+     */
+    AssertPtrReturn(pProgress, E_INVALIDARG);
+    AssertReturn(uPercent <= 100, E_INVALIDARG);
+
+    AssertPtrReturn(pHlp, VERR_INVALID_POINTER);
+    AssertReturn(pHlp->u32Version == VBOXEXTPACKHLP_VERSION, VERR_INVALID_POINTER);
+
+    return pProgress->SetCurrentOperationProgress(uPercent);
+}
+
+/*static*/ DECLCALLBACK(uint32_t)
+ExtPack::i_hlpNextOperationProgress(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IProgress) *pProgress,
+                                    const char *pcszNextOperationDescription,
+                                    uint32_t uNextOperationWeight)
+{
+    /*
+     * Validate the input and get our bearings.
+     */
+    AssertPtrReturn(pProgress, E_INVALIDARG);
+    AssertPtrReturn(pcszNextOperationDescription, E_INVALIDARG);
+    AssertReturn(uNextOperationWeight >= 1, E_INVALIDARG);
+
+    AssertPtrReturn(pHlp, VERR_INVALID_POINTER);
+    AssertReturn(pHlp->u32Version == VBOXEXTPACKHLP_VERSION, VERR_INVALID_POINTER);
+
+    return pProgress->SetNextOperation(Bstr(pcszNextOperationDescription).raw(), uNextOperationWeight);
+}
+
+/*static*/ DECLCALLBACK(uint32_t)
+ExtPack::i_hlpCompleteProgress(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IProgress) *pProgress,
+                               uint32_t uResultCode)
+{
+    /*
+     * Validate the input and get our bearings.
+     */
+    AssertPtrReturn(pProgress, E_INVALIDARG);
+
+    AssertPtrReturn(pHlp, VERR_INVALID_POINTER);
+    AssertReturn(pHlp->u32Version == VBOXEXTPACKHLP_VERSION, VERR_INVALID_POINTER);
+
+    Progress *pProgressInt = static_cast<Progress *>(pProgress);
+    return pProgressInt->i_notifyComplete(uResultCode);
+}
+
 /*static*/ DECLCALLBACK(int)
 ExtPack::i_hlpReservedN(PCVBOXEXTPACKHLP pHlp)
@@ -2005,5 +2128,5 @@
                         HRESULT hrc2 = NewExtPack.createObject();
                         if (SUCCEEDED(hrc2))
-                            hrc2 = NewExtPack->initWithDir(a_enmContext, pstrName->c_str(), szExtPackDir);
+                            hrc2 = NewExtPack->initWithDir(a_pVirtualBox, a_enmContext, pstrName->c_str(), szExtPackDir);
                         delete pstrName;
                         if (SUCCEEDED(hrc2))
@@ -2590,5 +2713,5 @@
             hrc = ptrNewExtPack.createObject();
             if (SUCCEEDED(hrc))
-                hrc = ptrNewExtPack->initWithDir(m->enmContext, a_pszName, szDir);
+                hrc = ptrNewExtPack->initWithDir(m->pVirtualBox, m->enmContext, a_pszName, szDir);
             if (SUCCEEDED(hrc))
             {
