Index: /trunk/src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 37068)
+++ /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 37069)
@@ -8691,5 +8691,5 @@
   <interface
     name="IProgress" extends="$unknown"
-    uuid="A163C98F-8635-4AA8-B770-A9941737F3EF"
+    uuid="c20238e4-3221-4d3f-8891-81ce92d9f913"
     wsmap="managed"
     >
@@ -8885,4 +8885,32 @@
         </desc>
       </param>
+    </method>
+
+    <method name="waitForAsyncProgressCompletion">
+      <desc>
+         Waits until the other task is completed (including all
+         sub-operations) and forward all changes from the other progress to
+         this progress. This means sub-operation number, description, percent
+         and so on.
+         
+         You have to take care on setting up at least the same count on
+         sub-operations in this progress object like there are in the other
+         progress object. 
+
+         If the other progress object supports cancel and this object gets any
+         cancel request (when here enabled as well), it will be forwarded to
+         the other progress object.
+
+         If there is an error in the other progress, this error isn't
+         automatically transfered to this progress object. So you have to
+         check any operation error within the other progress object, after
+         this method returns.
+      </desc>
+
+     <param name="pProgressAsync" type="IProgress" dir="in">
+       <desc>
+         The progress object of the asynchrony process.
+       </desc>
+     </param>
     </method>
 
Index: /trunk/src/VBox/Main/include/ProgressImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/ProgressImpl.h	(revision 37068)
+++ /trunk/src/VBox/Main/include/ProgressImpl.h	(revision 37069)
@@ -242,4 +242,5 @@
     STDMETHOD(WaitForCompletion)(LONG aTimeout);
     STDMETHOD(WaitForOperationCompletion)(ULONG aOperation, LONG aTimeout);
+    STDMETHOD(WaitForAsyncProgressCompletion)(IProgress *pProgressAsync);
     STDMETHOD(Cancel)();
 
Index: /trunk/src/VBox/Main/src-all/ProgressImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-all/ProgressImpl.cpp	(revision 37068)
+++ /trunk/src/VBox/Main/src-all/ProgressImpl.cpp	(revision 37069)
@@ -914,4 +914,87 @@
 
     return S_OK;
+}
+
+STDMETHODIMP Progress::WaitForAsyncProgressCompletion(IProgress *pProgressAsync)
+{
+    LogFlowThisFuncEnter();
+
+    CheckComArgNotNull(pProgressAsync);
+
+    AutoCaller autoCaller(this);
+    if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+    /* Note: we don't lock here, cause we just using public methods. */
+
+    HRESULT rc           = S_OK;
+    BOOL fCancelable     = FALSE;
+    BOOL fCompleted      = FALSE;
+    BOOL fCanceled       = FALSE;
+    ULONG currentPercent = 0;
+    ULONG cOp            = 0;
+    /* Is the async process cancelable? */
+    rc = pProgressAsync->COMGETTER(Cancelable)(&fCancelable);
+    if (FAILED(rc)) return rc;
+    /* Loop as long as the sync process isn't completed. */
+    while (SUCCEEDED(pProgressAsync->COMGETTER(Completed(&fCompleted))))
+    {
+        /* We can forward any cancel request to the async process only when
+         * it is cancelable. */
+        if (fCancelable)
+        {
+            rc = COMGETTER(Canceled)(&fCanceled);
+            if (FAILED(rc)) return rc;
+            if (fCanceled)
+            {
+                rc = pProgressAsync->Cancel();
+                if (FAILED(rc)) return rc;
+            }
+        }
+        /* Even if the user canceled the process, we have to wait until the
+           async task has finished his work (cleanup and such). Otherwise there
+           will be sync trouble (still wrong state, dead locks, ...) on the
+           used objects. So just do nothing, but wait for the complete
+           notification. */
+        if (!fCanceled)
+        {
+            /* Check if the current operation has changed. It is also possible that
+             * in the meantime more than one async operation was finished. So we
+             * have to loop as long as we reached the same operation count. */
+            ULONG curOp;
+            for(;;)
+            {
+                rc = pProgressAsync->COMGETTER(Operation(&curOp));
+                if (FAILED(rc)) return rc;
+                if (cOp != curOp)
+                {
+                    Bstr bstr;
+                    ULONG currentWeight;
+                    rc = pProgressAsync->COMGETTER(OperationDescription(bstr.asOutParam()));
+                    if (FAILED(rc)) return rc;
+                    rc = pProgressAsync->COMGETTER(OperationWeight(&currentWeight));
+                    if (FAILED(rc)) return rc;
+                    rc = SetNextOperation(bstr.raw(), currentWeight);
+                    if (FAILED(rc)) return rc;
+                    ++cOp;
+                }else
+                    break;
+            }
+
+            rc = pProgressAsync->COMGETTER(OperationPercent(&currentPercent));
+            if (FAILED(rc)) return rc;
+            rc = SetCurrentOperationProgress(currentPercent);
+            if (FAILED(rc)) return rc;
+        }
+        if (fCompleted)
+            break;
+
+        /* Make sure the loop is not too tight */
+        rc = pProgressAsync->WaitForCompletion(100);
+        if (FAILED(rc)) return rc;
+    }
+
+    LogFlowThisFuncLeave();
+
+    return rc;
 }
 
