Index: trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp
===================================================================
--- trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp	(revision 34829)
+++ trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp	(revision 34831)
@@ -201,6 +201,17 @@
 static int ctrlPrintProgressError(ComPtr<IProgress> progress)
 {
-    com::ProgressErrorInfo ErrInfo(progress);
-    return ctrlPrintError(ErrInfo);
+    int rc;
+    BOOL fCanceled;
+    if (   SUCCEEDED(progress->COMGETTER(Canceled(&fCanceled)))
+        && fCanceled)
+    {
+        rc = VERR_CANCELLED;
+    }
+    else
+    {
+        com::ProgressErrorInfo ErrInfo(progress);
+        rc = ctrlPrintError(ErrInfo);
+    }
+    return rc;
 }
 
@@ -954,4 +965,5 @@
  * @return  IPRT status code.
  * @param   pGuest          IGuest interface pointer.
+ * @param   fVerbose        Verbose flag.
  * @param   pszSource       Source path of existing host file to copy.
  * @param   pszDest         Destination path on guest to copy the file to.
@@ -960,5 +972,5 @@
  * @param   uFlags          Copy flags.
  */
-static int ctrlCopyFileToGuest(IGuest *pGuest, const char *pszSource, const char *pszDest,
+static int ctrlCopyFileToGuest(IGuest *pGuest, bool fVerbose, const char *pszSource, const char *pszDest,
                                const char *pszUserName, const char *pszPassword,
                                uint32_t uFlags)
@@ -978,52 +990,7 @@
     else
     {
-        /* Setup signal handling if cancelable. */
-        ASSERT(progress);
-        bool fCanceledAlready = false;
-        BOOL fCancelable = FALSE;
-        HRESULT hrc = progress->COMGETTER(Cancelable)(&fCancelable);
-        if (fCancelable)
-            ctrlSignalHandlerInstall();
-
-        /* Wait for process to exit ... */
-        BOOL fCompleted = FALSE;
-        BOOL fCanceled = FALSE;
-        while (   SUCCEEDED(progress->COMGETTER(Completed(&fCompleted)))
-               && !fCompleted)
-        {
-            /* Process async cancelation */
-            if (g_fGuestCtrlCanceled && !fCanceledAlready)
-            {
-                hrc = progress->Cancel();
-                if (SUCCEEDED(hrc))
-                    fCanceledAlready = TRUE;
-                else
-                    g_fGuestCtrlCanceled = false;
-            }
-
-            /* Progress canceled by Main API? */
-            if (   SUCCEEDED(progress->COMGETTER(Canceled(&fCanceled)))
-                && fCanceled)
-            {
-                break;
-            }
-        }
-
-        /* Undo signal handling. */
-        if (fCancelable)
-            ctrlSignalHandlerUninstall();
-
-        if (fCanceled)
-        {
-            /* Nothing to do here right now. */
-        }
-        else if (   fCompleted
-                 && SUCCEEDED(rc))
-        {
-            LONG iRc;
-            CHECK_ERROR_RET(progress, COMGETTER(ResultCode)(&iRc), rc);
-            if (FAILED(iRc))
-                vrc = ctrlPrintProgressError(progress);
-        }
+        rc = showProgress(progress);
+        if (FAILED(rc))
+            vrc = ctrlPrintProgressError(progress);
     }
     return vrc;
@@ -1208,5 +1175,5 @@
                         /* Finally copy the desired file (if no dry run selected). */
                         if (!fDryRun)
-                            vrc = ctrlCopyFileToGuest(guest, pNode->pszSourcePath, pNode->pszDestPath,
+                            vrc = ctrlCopyFileToGuest(guest, fVerbose, pNode->pszSourcePath, pNode->pszDestPath,
                                                       Utf8UserName.c_str(), Utf8Password.c_str(), uFlags);
                     }
Index: trunk/src/VBox/Main/GuestImpl.cpp
===================================================================
--- trunk/src/VBox/Main/GuestImpl.cpp	(revision 34829)
+++ trunk/src/VBox/Main/GuestImpl.cpp	(revision 34831)
@@ -31,4 +31,5 @@
 #ifdef VBOX_WITH_GUEST_CONTROL
 # include <VBox/com/array.h>
+# include <VBox/com/ErrorInfo.h>
 #endif
 #include <iprt/cpp/utils.h>
@@ -54,4 +55,7 @@
     enum TaskType
     {
+        /** Copies a file to the guest. */
+        CopyFile = 50,
+
         /** Update Guest Additions by directly copying the required installer
          *  off the .ISO file, transfer it to the guest and execute the installer
@@ -72,4 +76,7 @@
     static int uploadProgress(unsigned uPercent, void *pvUser);
 
+    static HRESULT setProgressErrorInfo(HRESULT hr, ComObjPtr<Progress> pProgress, const char * pszText, ...);
+    static HRESULT setProgressErrorInfo(HRESULT hr, ComObjPtr<Progress> pProgress, ComObjPtr<Guest> pGuest);
+
     TaskType taskType;
     Guest *pGuest;
@@ -79,5 +86,8 @@
     /* Task data. */
     Utf8Str strSource;
-    ULONG uFlags;
+    Utf8Str strDest;
+    Utf8Str strUserName;
+    Utf8Str strPassword;
+    ULONG   uFlags;
 };
 
@@ -110,4 +120,9 @@
     {
 #ifdef VBOX_WITH_GUEST_CONTROL
+        case TaskGuest::CopyFile:
+        {
+            rc = pGuest->taskCopyFile(task.get());
+            break;
+        }
         case TaskGuest::UpdateGuestAdditions:
         {
@@ -144,5 +159,241 @@
 }
 
+/* static */
+HRESULT Guest::TaskGuest::setProgressErrorInfo(HRESULT hr, ComObjPtr<Progress> pProgress, const char *pszText, ...)
+{
+    BOOL fCanceled;
+    BOOL fCompleted;
+    if (   SUCCEEDED(pProgress->COMGETTER(Canceled(&fCanceled)))
+        && !fCanceled
+        && SUCCEEDED(pProgress->COMGETTER(Completed(&fCompleted)))
+        && !fCompleted)
+    {
+        va_list va;
+        va_start(va, pszText);
+        HRESULT hr2 = pProgress->notifyComplete(hr,
+                                                COM_IIDOF(IGuest),
+                                                Guest::getStaticComponentName(),
+                                                va);
+        va_end(va);
+        if (hr2 == S_OK) /* If unable to retrieve error, return input error. */
+            hr2 = hr;
+        return hr2;
+    }
+    return S_OK;
+}
+
+/* static */
+HRESULT Guest::TaskGuest::setProgressErrorInfo(HRESULT hr, ComObjPtr<Progress> pProgress, ComObjPtr<Guest> pGuest)
+{
+    return setProgressErrorInfo(hr, pProgress,
+                                Utf8Str(com::ErrorInfo((IGuest*)pGuest, COM_IIDOF(IGuest)).getText()).c_str());
+}
+
 #ifdef VBOX_WITH_GUEST_CONTROL
+HRESULT Guest::taskCopyFile(TaskGuest *aTask)
+{
+    LogFlowFuncEnter();
+
+    AutoCaller autoCaller(this);
+    if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+    /*
+     * Do *not* take a write lock here since we don't (and won't)
+     * touch any class-specific data (of IGuest) here - only the member functions
+     * which get called here can do that.
+     */
+
+    HRESULT rc = S_OK;
+
+    try
+    {
+        Guest *pGuest = aTask->pGuest;
+        AssertPtr(pGuest);
+
+        /* Does our source file exist? */
+        if (!RTFileExists(aTask->strSource.c_str()))
+        {
+            /* Since this task runs in another thread than the main Guest object
+             * we cannot rely on notifyComplete's internal lookup - so do this ourselves. */
+            rc = VBOX_E_IPRT_ERROR;
+            aTask->progress->notifyComplete(rc,
+                                            COM_IIDOF(IGuest),
+                                            Guest::getStaticComponentName(),
+                                            Guest::tr("Source file \"%s\" does not exist"), aTask->strSource.c_str());
+        }
+        else
+        {
+            RTFILE fileSource;
+            int vrc = RTFileOpen(&fileSource, aTask->strSource.c_str(),
+                                 RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE);
+            if (RT_FAILURE(vrc))
+            {
+                rc = TaskGuest::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->progress,
+                                                     Guest::tr("Could not open source file \"%s\" for reading (%Rrc)"),
+                                                     aTask->strSource.c_str(),  vrc);
+            }
+            else
+            {
+                uint64_t cbSize;
+                vrc = RTFileGetSize(fileSource, &cbSize);
+                if (RT_FAILURE(vrc))
+                {
+                    rc = TaskGuest::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->progress,
+                                                         Guest::tr("Could not query file size of \"%s\" (%Rrc)"),
+                                                         aTask->strSource.c_str(), vrc);
+                }
+                else
+                {
+                    com::SafeArray<IN_BSTR> args;
+                    com::SafeArray<IN_BSTR> env;
+
+                    /*
+                     * Prepare tool command line.
+                     */
+                    char szOutput[RTPATH_MAX];
+                    if (RTStrPrintf(szOutput, sizeof(szOutput), "--output=%s", aTask->strDest.c_str()) <= sizeof(szOutput) - 1)
+                    {
+                        /*
+                         * Normalize path slashes, based on the detected guest.
+                         */
+                        Utf8Str osType = mData.mOSTypeId;
+                        if (   osType.contains("Microsoft", Utf8Str::CaseInsensitive)
+                            || osType.contains("Windows", Utf8Str::CaseInsensitive))
+                        {
+                            /* We have a Windows guest. */
+                            RTPathChangeToDosSlashes(szOutput, true /* Force conversion. */);
+                        }
+                        else /* ... or something which isn't from Redmond ... */
+                        {
+                            RTPathChangeToUnixSlashes(szOutput, true /* Force conversion. */);
+                        }
+
+                        args.push_back(Bstr(VBOXSERVICE_TOOL_CAT).raw()); /* The actual (internal) tool to use (as argv[0]). */
+                        args.push_back(Bstr(szOutput).raw());             /* We want to write a file ... */
+                    }
+                    else
+                    {
+                        rc = TaskGuest::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->progress,
+                                                             Guest::tr("Error preparing command line"));
+                    }
+
+                    ComPtr<IProgress> execProgress;
+                    ULONG uPID;
+                    if (SUCCEEDED(rc))
+                    {
+                        LogRel(("Copying file \"%s\" to guest \"%s\" (%u bytes) ...\n",
+                                aTask->strSource.c_str(), aTask->strDest.c_str(), cbSize));
+                        /*
+                         * Okay, since we gathered all stuff we need until now to start the
+                         * actual copying, start the guest part now.
+                         */
+                        rc = pGuest->ExecuteProcess(Bstr(VBOXSERVICE_TOOL_CAT).raw(),
+                                                      ExecuteProcessFlag_Hidden
+                                                    | ExecuteProcessFlag_WaitForProcessStartOnly,
+                                                    ComSafeArrayAsInParam(args),
+                                                    ComSafeArrayAsInParam(env),
+                                                    Bstr(aTask->strUserName).raw(),
+                                                    Bstr(aTask->strPassword).raw(),
+                                                    5 * 1000 /* Wait 5s for getting the process started. */,
+                                                    &uPID, execProgress.asOutParam());
+                        if (FAILED(rc))
+                            rc = TaskGuest::setProgressErrorInfo(rc, aTask->progress, pGuest);
+                    }
+
+                    if (SUCCEEDED(rc))
+                    {
+                        BOOL fCompleted = FALSE;
+                        BOOL fCanceled = FALSE;
+
+                        size_t cbToRead = cbSize;
+                        size_t cbTransfered = 0;
+                        size_t cbRead;
+                        SafeArray<BYTE> aInputData(_1M);
+                        while (   SUCCEEDED(execProgress->COMGETTER(Completed(&fCompleted)))
+                               && !fCompleted)
+                        {
+                            vrc = RTFileRead(fileSource, (uint8_t*)aInputData.raw(), RT_MIN(cbToRead, _1M), &cbRead);
+                            /*
+                             * Some other error occured? There might be a chance that RTFileRead
+                             * could not resolve/map the native error code to an IPRT code, so just
+                             * print a generic error.
+                             */
+                            if (RT_FAILURE(vrc))
+                            {
+                                rc = TaskGuest::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->progress,
+                                                                     Guest::tr("Could not read from file \"%s\" (%Rrc)"),
+                                                                     aTask->strSource.c_str(), vrc);
+                                break;
+                            }
+
+                            /* Resize buffer to reflect amount we just have read. */
+                            aInputData.resize(cbRead);
+
+                            ULONG uFlags = ProcessInputFlag_None;
+                            /* Did we reach the end of the content we want to transfer (last chunk)? */
+                            if (   (cbRead < _1M)
+                                /* ... or does the user want to cancel? */
+                                || (   SUCCEEDED(aTask->progress->COMGETTER(Canceled(&fCanceled)))
+                                    && fCanceled)
+                               )
+                            {
+                                uFlags |= ProcessInputFlag_EndOfFile;
+                            }
+
+                            /* Transfer the current chunk ... */
+                            ULONG uBytesWritten;
+                            rc = pGuest->SetProcessInput(uPID, uFlags,
+                                                         ComSafeArrayAsInParam(aInputData), &uBytesWritten);
+                            if (FAILED(rc))
+                            {
+                                rc = TaskGuest::setProgressErrorInfo(rc, aTask->progress, pGuest);
+                                break;
+                            }
+
+                            Assert(cbRead <= cbToRead);
+                            cbToRead -= cbRead;
+                            Assert(cbToRead >= 0);
+
+                            cbTransfered += uBytesWritten;
+                            Assert(cbTransfered <= cbSize);
+                            aTask->progress->SetCurrentOperationProgress(cbTransfered / (cbSize / 100));
+
+                            /* End of file reached? */
+                            if (cbToRead == 0)
+                                break;
+
+                            /* Progress canceled by Main API? */
+                            if (   SUCCEEDED(execProgress->COMGETTER(Canceled(&fCanceled)))
+                                && fCanceled)
+                            {
+                                rc = TaskGuest::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->progress,
+                                                                     Guest::tr("Copy operation of file \"%s\" was canceled on guest side"),
+                                                                     aTask->strSource.c_str());
+                                break;
+                            }
+                        }
+
+                        if (SUCCEEDED(rc))
+                            aTask->progress->notifyComplete(S_OK);
+                    }
+                }
+                RTFileClose(fileSource);
+            }
+        }
+    }
+    catch (HRESULT aRC)
+    {
+        rc = aRC;
+    }
+
+    /* Clean up */
+    aTask->rc = rc;
+
+    LogFlowFunc(("rc=%Rhrc\n", rc));
+    LogFlowFuncLeave();
+
+    return VINF_SUCCESS;
+}
+
 HRESULT Guest::taskUpdateGuestAdditions(TaskGuest *aTask)
 {
@@ -307,5 +558,5 @@
 
                         /* Wait for process to exit ... */
-                        SafeArray<BYTE> aInputData(_64K);
+                        SafeArray<BYTE> aInputData(_1M);
                         while (   SUCCEEDED(progressCat->COMGETTER(Completed(&fCompleted)))
                                && !fCompleted)
@@ -314,5 +565,5 @@
                             /* cbLength contains remaining bytes of our installer file
                              * opened above to read. */
-                            size_t cbToRead = RT_MIN(cbLength, _64K);
+                            size_t cbToRead = RT_MIN(cbLength, _1M);
                             if (cbToRead)
                             {
@@ -324,5 +575,5 @@
                                      * we want to transfer (last chunk)? */
                                     ULONG uFlags = ProcessInputFlag_None;
-                                    if (cbRead < _64K)
+                                    if (cbRead < _1M)
                                     {
                                         uFlags |= ProcessInputFlag_EndOfFile;
@@ -2146,6 +2397,5 @@
         Assert(uContextID > 0);
 
-        size_t cbData = (size_t)RT_MIN(aSize, _64K);
-        com::SafeArray<BYTE> outputData(cbData);
+        com::SafeArray<BYTE> outputData((size_t)aSize);
 
         VBOXHGCMSVCPARM paParms[5];
@@ -2217,5 +2467,5 @@
                         {
                             /* Do we need to resize the array? */
-                            if (pData->cbData > cbData)
+                            if (pData->cbData > aSize)
                                 outputData.resize(pData->cbData);
 
@@ -2331,8 +2581,4 @@
 }
 
-/** @todo For having a progress object which actually reports something,
-  *       the actual copy loop (see below) needs to go to some worker thread
-  *       so that this routine can return to the caller (and the caller then
-  *       can do display a progress). */
 STDMETHODIMP Guest::CopyToGuest(IN_BSTR aSource, IN_BSTR aDest,
                                 IN_BSTR aUserName, IN_BSTR aPassword,
@@ -2342,8 +2588,8 @@
     ReturnComNotImplemented();
 #else /* VBOX_WITH_GUEST_CONTROL */
-    using namespace guestControl;
-
     CheckComArgStrNotEmptyOrNull(aSource);
     CheckComArgStrNotEmptyOrNull(aDest);
+    CheckComArgStrNotEmptyOrNull(aUserName);
+    CheckComArgStrNotEmptyOrNull(aPassword);
     CheckComArgOutPointerValid(aProgress);
 
@@ -2351,149 +2597,51 @@
     if (FAILED(autoCaller.rc())) return autoCaller.rc();
 
+    /* Validate flags. */
     if (aFlags != 0) /* Flags are not supported at the moment. */
         return setError(E_INVALIDARG, tr("Unknown flags (%#x)"), aFlags);
 
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
     HRESULT rc = S_OK;
 
+    ComObjPtr<Progress> progress;
     try
     {
-        Utf8Str Utf8Source(aSource);
-        Utf8Str Utf8Dest(aDest);
-        Utf8Str Utf8UserName(aUserName);
-        Utf8Str Utf8Password(aPassword);
-
-        /* Does our source file exist? */
-        if (!RTFileExists(Utf8Source.c_str()))
-        {
-            rc = setError(VBOX_E_FILE_ERROR,
-                          tr("Source file \"%s\" does not exist"), Utf8Source.c_str());
-        }
-        else
-        {
-            RTFILE fileSource;
-            int vrc = RTFileOpen(&fileSource, Utf8Source.c_str(),
-                                 RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE);
-            if (RT_FAILURE(vrc))
-            {
-                rc = setError(VBOX_E_IPRT_ERROR,
-                              tr("Could not open source file \"%s\" for reading, rc=%Rrc"),
-                              Utf8Source.c_str(),  vrc);
-            }
-            else
-            {
-                uint64_t cbSize;
-                vrc = RTFileGetSize(fileSource, &cbSize);
-                if (RT_FAILURE(vrc))
-                {
-                    rc = setError(VBOX_E_IPRT_ERROR,
-                                  tr("Could not query file size of \"%s\", rc=%Rrc"),
-                                  Utf8Source.c_str(),  vrc);
-                }
-                else
-                {
-                    com::SafeArray<IN_BSTR> args;
-                    com::SafeArray<IN_BSTR> env;
-
-                    /*
-                     * Prepare tool command line.
-                     */
-                    char szOutput[RTPATH_MAX];
-                    if (RTStrPrintf(szOutput, sizeof(szOutput), "--output=%s", Utf8Dest.c_str()) <= sizeof(szOutput) - 1)
-                    {
-                        /*
-                         * Normalize path slashes, based on the detected guest.
-                         */
-                        Utf8Str osType = mData.mOSTypeId;
-                        if (   osType.contains("Microsoft", Utf8Str::CaseInsensitive)
-                            || osType.contains("Windows", Utf8Str::CaseInsensitive))
-                        {
-                            /* We have a Windows guest. */
-                            RTPathChangeToDosSlashes(szOutput, true /* Force conversion. */);
-                        }
-                        else /* ... or something which isn't from Redmond ... */
-                        {
-                            RTPathChangeToUnixSlashes(szOutput, true /* Force conversion. */);
-                        }
-
-                        args.push_back(Bstr(VBOXSERVICE_TOOL_CAT).raw()); /* The actual (internal) tool to use (as argv[0]). */
-                        args.push_back(Bstr(szOutput).raw());             /* We want to write a file ... */
-                    }
-                    else
-                        rc = setError(VBOX_E_IPRT_ERROR, tr("Error preparing command line"));
-
-                    ComPtr<IProgress> execProgress;
-                    ULONG uPID;
-                    if (SUCCEEDED(rc))
-                    {
-                        LogRel(("Copying file \"%s\" to guest \"%s\" (%u bytes) ...\n",
-                                Utf8Source.c_str(), Utf8Dest.c_str(), cbSize));
-                        /*
-                         * Okay, since we gathered all stuff we need until now to start the
-                         * actual copying, start the guest part now.
-                         */
-                        rc = ExecuteProcess(Bstr(VBOXSERVICE_TOOL_CAT).raw(),
-                                              ExecuteProcessFlag_Hidden
-                                            | ExecuteProcessFlag_WaitForProcessStartOnly,
-                                            ComSafeArrayAsInParam(args),
-                                            ComSafeArrayAsInParam(env),
-                                            Bstr(Utf8UserName).raw(),
-                                            Bstr(Utf8Password).raw(),
-                                            5 * 1000 /* Wait 5s for getting the process started. */,
-                                            &uPID, execProgress.asOutParam());
-                    }
-
-                    if (SUCCEEDED(rc))
-                    {
-                        /* Wait for process to exit ... */
-                        BOOL fCompleted = FALSE;
-                        BOOL fCanceled = FALSE;
-
-                        size_t cbRead;
-                        SafeArray<BYTE> aInputData(_64K);
-                        while (   SUCCEEDED(execProgress->COMGETTER(Completed(&fCompleted)))
-                               && !fCompleted)
-                        {
-                            vrc = RTFileRead(fileSource, (uint8_t*)aInputData.raw(), _64K, &cbRead);
-                            if (   cbRead == 0
-                                || vrc == VERR_EOF)
-                                break;
-
-                            aInputData.resize(cbRead);
-
-                            /* Did we reach the end of the content
-                             * we want to transfer (last chunk)? */
-                            ULONG uFlags = ProcessInputFlag_None;
-                            if (cbRead < _64K)
-                                uFlags |= ProcessInputFlag_EndOfFile;
-
-                            /* Transfer the current chunk ... */
-                            ULONG uBytesWritten;
-                            rc = SetProcessInput(uPID, uFlags,
-                                                 ComSafeArrayAsInParam(aInputData), &uBytesWritten);
-                            if (FAILED(rc))
-                                break;
-
-                            /* Progress canceled by Main API? */
-                            if (   SUCCEEDED(execProgress->COMGETTER(Canceled(&fCanceled)))
-                                && fCanceled)
-                            {
-                                break;
-                            }
-                        }
-
-                        if (SUCCEEDED(rc))
-                        {
-                            /* Return the progress to the caller. */
-                            execProgress.queryInterfaceTo(aProgress);
-                        }
-                    }
-                }
-                RTFileClose(fileSource);
-            }
-        }
-    }
-    catch (std::bad_alloc &)
-    {
-        rc = E_OUTOFMEMORY;
+        /* Create the progress object. */
+        progress.createObject();
+
+        rc = progress->init(static_cast<IGuest*>(this),
+                            Bstr(tr("Copying file")).raw(),
+                            TRUE /* aCancelable */);
+        if (FAILED(rc)) throw rc;
+
+        /* Initialize our worker task. */
+        TaskGuest *pTask = new TaskGuest(TaskGuest::CopyFile, this, progress);
+        AssertPtr(pTask);
+        std::auto_ptr<TaskGuest> task(pTask);
+
+        /* Assign data - in that case aSource is the full path
+         * to the Guest Additions .ISO we want to mount. */
+        task->strSource   = (Utf8Str(aSource));
+        task->strDest     = (Utf8Str(aDest));
+        task->strUserName = (Utf8Str(aUserName));
+        task->strPassword = (Utf8Str(aPassword));
+        task->uFlags      = aFlags;
+
+        rc = task->startThread();
+        if (FAILED(rc)) throw rc;
+
+        /* Don't destruct on success. */
+        task.release();
+    }
+    catch (HRESULT aRC)
+    {
+        rc = aRC;
+    }
+
+    if (SUCCEEDED(rc))
+    {
+        /* Return progress to the caller. */
+        progress.queryInterfaceTo(aProgress);
     }
     return rc;
Index: trunk/src/VBox/Main/include/GuestImpl.h
===================================================================
--- trunk/src/VBox/Main/include/GuestImpl.h	(revision 34829)
+++ trunk/src/VBox/Main/include/GuestImpl.h	(revision 34831)
@@ -136,4 +136,5 @@
     struct TaskGuest; /* Worker thread helper. */
 #ifdef VBOX_WITH_GUEST_CONTROL
+    HRESULT taskCopyFile(TaskGuest *aTask);
     HRESULT taskUpdateGuestAdditions(TaskGuest *aTask);
 
