VirtualBox

Ignore:
Timestamp:
Aug 8, 2012 10:37:51 PM (12 years ago)
Author:
vboxsync
Message:

Guest Control 2.0: Update.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp

    r42691 r42693  
    3333#include <iprt/env.h>
    3434#include <iprt/file.h> /* For CopyTo/From. */
     35#include <iprt/isofs.h> /* For UpdateAdditions. */
    3536
    3637#include <VBox/com/array.h>
     
    109110}
    110111
    111 int GuestSessionTask::setProgressErrorMsg(HRESULT hr, const Utf8Str &strMsg)
     112HRESULT GuestSessionTask::setProgressErrorMsg(HRESULT hr, const Utf8Str &strMsg)
    112113{
    113114    if (mProgress.isNull()) /* Progress is optional. */
    114         return VINF_SUCCESS;
     115        return hr; /* Return original rc. */
    115116
    116117    BOOL fCanceled;
     
    126127                                               strMsg.c_str());
    127128        if (FAILED(hr2))
    128             return VERR_COM_UNEXPECTED;
    129     }
    130     return VINF_SUCCESS;
     129            return hr2;
     130    }
     131    return hr; /* Return original rc. */
    131132}
    132133
    133134SessionTaskCopyTo::SessionTaskCopyTo(GuestSession *pSession,
    134135                                     const Utf8Str &strSource, const Utf8Str &strDest, uint32_t uFlags)
    135                                      : GuestSessionTask(pSession)
     136                                     : mSourceFile(NULL),
     137                                       mSourceOffset(0),
     138                                       mSourceSize(0),
     139                                       GuestSessionTask(pSession)
    136140{
    137141    mSource = strSource;
     
    140144}
    141145
     146SessionTaskCopyTo::SessionTaskCopyTo(GuestSession *pSession,
     147                                     PRTFILE pSourceFile, size_t cbSourceOffset, size_t cbSourceSize,
     148                                     const Utf8Str &strDest, uint32_t uFlags)
     149                                     : GuestSessionTask(pSession)
     150{
     151    mSourceFile    = pSourceFile;
     152    mSourceOffset  = cbSourceOffset;
     153    mSourceSize    = cbSourceSize;
     154    mDest          = strDest;
     155    mCopyFileFlags = uFlags;
     156}
     157
    142158SessionTaskCopyTo::~SessionTaskCopyTo(void)
    143159{
     
    156172
    157173    if (mCopyFileFlags)
    158         return setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    159                                    Utf8StrFmt(GuestSession::tr("Copy flags (%#x) not implemented yet"),
    160                                               mCopyFileFlags));
     174    {
     175        setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     176                            Utf8StrFmt(GuestSession::tr("Copy flags (%#x) not implemented yet"),
     177                            mCopyFileFlags));
     178        return VERR_INVALID_PARAMETER;
     179    }
     180
    161181    int rc;
    162182
    163     /** @todo Make use of exceptions (+ finally block) here! */
    164 
    165     try
     183    RTFILE fileLocal;
     184    PRTFILE pFile = &fileLocal;
     185
     186    if (!mSourceFile)
    166187    {
    167188        /* Does our source file exist? */
     
    174195        else
    175196        {
    176             RTFILE fileSource;
    177             rc = RTFileOpen(&fileSource, mSource.c_str(),
     197            rc = RTFileOpen(pFile, mSource.c_str(),
    178198                            RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE);
    179199            if (RT_FAILURE(rc))
    180200            {
    181201                rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    182                                          Utf8StrFmt(GuestSession::tr("Could not open source file \"%s\" for reading (%Rrc)"),
     202                                         Utf8StrFmt(GuestSession::tr("Could not open source file \"%s\" for reading: %Rrc"),
    183203                                                    mSource.c_str(), rc));
    184204            }
    185205            else
    186206            {
    187                 uint64_t cbFileSize;
    188                 rc = RTFileGetSize(fileSource, &cbFileSize);
     207                rc = RTFileGetSize(*pFile, &mSourceSize);
    189208                if (RT_FAILURE(rc))
    190209                {
     
    193212                                                   mSource.c_str(), rc));
    194213                }
    195                 else
     214            }
     215        }
     216    }
     217    else
     218    {
     219        pFile = mSourceFile;
     220        /* Size + offset are optional. */
     221    }
     222
     223    GuestProcessStartupInfo procInfo;
     224    procInfo.mName    = Utf8StrFmt(GuestSession::tr("Copying file \"%s\" to the guest to \"%s\" (%RU64 bytes)"),
     225                                   mSource.c_str(), mDest.c_str(), mSourceSize);
     226    procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_CAT);
     227    procInfo.mFlags   = ProcessCreateFlag_Hidden;
     228
     229    /* Set arguments.*/
     230    procInfo.mArguments.push_back(Utf8StrFmt("--output=%s", mDest.c_str())); /** @todo Do we need path conversion? */
     231
     232    /* Startup process. */
     233    ComObjPtr<GuestProcess> pProcess;
     234    rc = pSession->processCreateExInteral(procInfo, pProcess);
     235    if (RT_SUCCESS(rc))
     236        rc = pProcess->startProcess();
     237    if (RT_FAILURE(rc))
     238    {
     239        setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     240                            Utf8StrFmt(GuestSession::tr("Unable to start guest process: %Rrc"), rc));
     241    }
     242    else
     243    {
     244        GuestProcessWaitResult waitRes;
     245        BYTE byBuf[_64K];
     246
     247        BOOL fCanceled = FALSE;
     248        uint64_t cbWrittenTotal = 0;
     249        uint64_t cbToRead = mSourceSize;
     250
     251        for (;;)
     252        {
     253            rc = pProcess->waitFor(ProcessWaitForFlag_StdIn,
     254                                   30 * 1000 /* Timeout */, waitRes);
     255            if (   RT_FAILURE(rc)
     256                || waitRes.mResult == ProcessWaitResult_Terminate
     257                || waitRes.mResult == ProcessWaitResult_Error
     258                || waitRes.mResult == ProcessWaitResult_Timeout)
     259            {
     260                break;
     261            }
     262
     263            size_t cbRead = 0;
     264            if (mSourceSize) /* If we have nothing to write, take a shortcut. */
     265            {
     266                /** @todo Not very efficient, but works for now. */
     267                rc = RTFileSeek(*pFile, mSourceOffset + cbWrittenTotal,
     268                                RTFILE_SEEK_BEGIN, NULL /* poffActual */);
     269                if (RT_SUCCESS(rc))
    196270                {
    197                     GuestProcessStartupInfo procInfo;
    198                     procInfo.mName    = Utf8StrFmt(GuestSession::tr("Copying file \"%s\" to the guest to \"%s\" (%RU64 bytes)"),
    199                                                    mSource.c_str(), mDest.c_str(), cbFileSize);
    200                     procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_CAT);
    201                     procInfo.mFlags   = ProcessCreateFlag_Hidden;
    202 
    203                     /* Set arguments.*/
    204                     procInfo.mArguments.push_back(Utf8StrFmt("--output=%s", mDest.c_str())); /** @todo Do we need path conversion? */
    205 
    206                     /* Startup process. */
    207                     ComObjPtr<GuestProcess> pProcess;
    208                     rc = pSession->processCreateExInteral(procInfo, pProcess);
    209                     if (RT_SUCCESS(rc))
    210                         rc = pProcess->startProcess();
     271                    rc = RTFileRead(*pFile, (uint8_t*)byBuf,
     272                                    RT_MIN(cbToRead, sizeof(byBuf)), &cbRead);
     273                    /*
     274                     * Some other error occured? There might be a chance that RTFileRead
     275                     * could not resolve/map the native error code to an IPRT code, so just
     276                     * print a generic error.
     277                     */
    211278                    if (RT_FAILURE(rc))
    212279                    {
    213280                        setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    214                                             Utf8StrFmt(GuestSession::tr("Unable to start guest process: %Rrc"), rc));
     281                                            Utf8StrFmt(GuestSession::tr("Could not read from file \"%s\" (%Rrc)"),
     282                                                       mSource.c_str(), rc));
     283                        break;
    215284                    }
     285                }
     286                else
     287                {
     288                    setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     289                                        Utf8StrFmt(GuestSession::tr("Seeking file \"%s\" offset %RU64 failed: %Rrc"),
     290                                                   mSource.c_str(), cbWrittenTotal, rc));
     291                    break;
     292                }
     293            }
     294
     295            uint32_t fFlags = ProcessInputFlag_None;
     296
     297            /* Did we reach the end of the content we want to transfer (last chunk)? */
     298            if (   (cbRead < sizeof(byBuf))
     299                /* Did we reach the last block which is exactly _64K? */
     300                || (cbToRead - cbRead == 0)
     301                /* ... or does the user want to cancel? */
     302                || (   SUCCEEDED(mProgress->COMGETTER(Canceled(&fCanceled)))
     303                    && fCanceled)
     304               )
     305            {
     306                fFlags |= ProcessInputFlag_EndOfFile;
     307            }
     308
     309            uint32_t cbWritten;
     310            Assert(sizeof(byBuf) >= cbRead);
     311            rc = pProcess->writeData(0 /* StdIn */, fFlags,
     312                                     byBuf, cbRead,
     313                                     30 * 1000 /* Timeout */, &cbWritten);
     314            if (RT_FAILURE(rc))
     315            {
     316                setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     317                                    Utf8StrFmt(GuestSession::tr("Writing to file \"%s\" (offset %RU64) failed: %Rrc"),
     318                                               mSource.c_str(), cbWrittenTotal, rc));
     319                break;
     320            }
     321#ifdef DEBUG
     322            LogFlowThisFunc(("cbWritten=%RU32, cbToRead=%RU64, cbWrittenTotal=%RU64, cbFileSize=%RU64\n",
     323                             cbWritten, cbToRead - cbWritten, cbWrittenTotal + cbWritten, mSourceSize));
     324#endif
     325            /* Only subtract bytes reported written by the guest. */
     326            Assert(cbToRead >= cbWritten);
     327            cbToRead -= cbWritten;
     328
     329            /* Update total bytes written to the guest. */
     330            cbWrittenTotal += cbWritten;
     331            Assert(cbWrittenTotal <= mSourceSize);
     332
     333            /* Did the user cancel the operation above? */
     334            if (fCanceled)
     335                break;
     336
     337            /* Update the progress.
     338             * Watch out for division by zero. */
     339            mSourceSize > 0
     340                ? rc = setProgress((ULONG)(cbWrittenTotal * 100 / mSourceSize))
     341                : rc = setProgress(100);
     342            if (RT_FAILURE(rc))
     343                break;
     344
     345            /* End of file reached? */
     346            if (!cbToRead)
     347                break;
     348        } /* for */
     349
     350        if (   !fCanceled
     351            || RT_SUCCESS(rc))
     352        {
     353            /*
     354             * Even if we succeeded until here make sure to check whether we really transfered
     355             * everything.
     356             */
     357            if (   mSourceSize > 0
     358                && cbWrittenTotal == 0)
     359            {
     360                /* If nothing was transfered but the file size was > 0 then "vbox_cat" wasn't able to write
     361                 * to the destination -> access denied. */
     362                rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     363                                         Utf8StrFmt(GuestSession::tr("Access denied when copying file \"%s\" to \"%s\""),
     364                                                    mSource.c_str(), mDest.c_str()));
     365            }
     366            else if (cbWrittenTotal < mSourceSize)
     367            {
     368                /* If we did not copy all let the user know. */
     369                rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     370                                         Utf8StrFmt(GuestSession::tr("Copying file \"%s\" failed (%RU64/%RU64 bytes transfered)"),
     371                                                    mSource.c_str(), cbWrittenTotal, mSourceSize));
     372            }
     373            else
     374            {
     375                rc = pProcess->waitFor(ProcessWaitForFlag_Terminate,
     376                                       30 * 1000 /* Timeout */, waitRes);
     377                if (   RT_FAILURE(rc)
     378                    || waitRes.mResult != ProcessWaitResult_Terminate)
     379                {
     380                    if (RT_FAILURE(rc))
     381                        rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     382                                                 Utf8StrFmt(GuestSession::tr("Waiting on termination for copying file \"%s\" failed: %Rrc"),
     383                                                            mSource.c_str(), rc));
    216384                    else
     385                        rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     386                                                 Utf8StrFmt(GuestSession::tr("Waiting on termination for copying file \"%s\" failed with wait result %ld"),
     387                                                            mSource.c_str(), waitRes.mResult));
     388                }
     389
     390                if (RT_SUCCESS(rc))
     391                {
     392                    ProcessStatus_T procStatus;
     393                    LONG exitCode;
     394                    if (   (   SUCCEEDED(pProcess->COMGETTER(Status(&procStatus)))
     395                            && procStatus != ProcessStatus_TerminatedNormally)
     396                        || (   SUCCEEDED(pProcess->COMGETTER(ExitCode(&exitCode)))
     397                            && exitCode != 0)
     398                       )
    217399                    {
    218                         GuestProcessWaitResult waitRes;
    219                         BYTE byBuf[_64K];
    220 
    221                         BOOL fCanceled = FALSE;
    222                         uint64_t cbWrittenTotal = 0;
    223                         uint64_t cbToRead = cbFileSize;
    224 
    225                         for (;;)
    226                         {
    227                             rc = pProcess->waitFor(ProcessWaitForFlag_StdIn,
    228                                                    30 * 1000 /* Timeout */, waitRes);
    229                             if (   RT_FAILURE(rc)
    230                                 || waitRes.mResult == ProcessWaitResult_Terminate
    231                                 || waitRes.mResult == ProcessWaitResult_Error
    232                                 || waitRes.mResult == ProcessWaitResult_Timeout)
    233                             {
    234                                 break;
    235                             }
    236 
    237                             size_t cbRead = 0;
    238                             if (cbFileSize) /* If we have nothing to write, take a shortcut. */
    239                             {
    240                                 /** @todo Not very efficient, but works for now. */
    241                                 rc = RTFileSeek(fileSource, cbWrittenTotal,
    242                                                 RTFILE_SEEK_BEGIN, NULL /* poffActual */);
    243                                 if (RT_SUCCESS(rc))
    244                                 {
    245                                     rc = RTFileRead(fileSource, (uint8_t*)byBuf,
    246                                                     RT_MIN(cbToRead, sizeof(byBuf)), &cbRead);
    247                                     /*
    248                                      * Some other error occured? There might be a chance that RTFileRead
    249                                      * could not resolve/map the native error code to an IPRT code, so just
    250                                      * print a generic error.
    251                                      */
    252                                     if (RT_FAILURE(rc))
    253                                     {
    254                                         setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    255                                                             Utf8StrFmt(GuestSession::tr("Could not read from file \"%s\" (%Rrc)"),
    256                                                                        mSource.c_str(), rc));
    257                                         break;
    258                                     }
    259                                 }
    260                                 else
    261                                 {
    262                                     setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    263                                                         Utf8StrFmt(GuestSession::tr("Seeking file \"%s\" offset %RU64 failed: %Rrc"),
    264                                                                    mSource.c_str(), cbWrittenTotal, rc));
    265                                     break;
    266                                 }
    267                             }
    268 
    269                             uint32_t fFlags = ProcessInputFlag_None;
    270 
    271                             /* Did we reach the end of the content we want to transfer (last chunk)? */
    272                             if (   (cbRead < sizeof(byBuf))
    273                                 /* Did we reach the last block which is exactly _64K? */
    274                                 || (cbToRead - cbRead == 0)
    275                                 /* ... or does the user want to cancel? */
    276                                 || (   SUCCEEDED(mProgress->COMGETTER(Canceled(&fCanceled)))
    277                                     && fCanceled)
    278                                )
    279                             {
    280                                 fFlags |= ProcessInputFlag_EndOfFile;
    281                             }
    282 
    283                             uint32_t cbWritten;
    284                             Assert(sizeof(byBuf) >= cbRead);
    285                             rc = pProcess->writeData(0 /* StdIn */, fFlags,
    286                                                      byBuf, cbRead,
    287                                                      30 * 1000 /* Timeout */, &cbWritten);
    288                             if (RT_FAILURE(rc))
    289                             {
    290                                 setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    291                                                     Utf8StrFmt(GuestSession::tr("Writing to file \"%s\" (offset %RU64) failed: %Rrc"),
    292                                                                mSource.c_str(), cbWrittenTotal, rc));
    293                                 break;
    294                             }
    295 #ifdef DEBUG
    296                             LogFlowThisFunc(("cbWritten=%RU32, cbToRead=%RU64, cbWrittenTotal=%RU64, cbFileSize=%RU64\n",
    297                                              cbWritten, cbToRead - cbWritten, cbWrittenTotal + cbWritten, cbFileSize));
    298 #endif
    299                             /* Only subtract bytes reported written by the guest. */
    300                             Assert(cbToRead >= cbWritten);
    301                             cbToRead -= cbWritten;
    302 
    303                             /* Update total bytes written to the guest. */
    304                             cbWrittenTotal += cbWritten;
    305                             Assert(cbWrittenTotal <= cbFileSize);
    306 
    307                             /* Did the user cancel the operation above? */
    308                             if (fCanceled)
    309                                 break;
    310 
    311                             /* Update the progress.
    312                              * Watch out for division by zero. */
    313                             cbFileSize > 0
    314                                 ? rc = setProgress((ULONG)(cbWrittenTotal * 100 / cbFileSize))
    315                                 : rc = setProgress(100);
    316                             if (RT_FAILURE(rc))
    317                                 break;
    318 
    319                             /* End of file reached? */
    320                             if (!cbToRead)
    321                                 break;
    322                         } /* for */
    323 
    324                         if (   !fCanceled
    325                             || RT_SUCCESS(rc))
    326                         {
    327                             /*
    328                              * Even if we succeeded until here make sure to check whether we really transfered
    329                              * everything.
    330                              */
    331                             if (   cbFileSize > 0
    332                                 && cbWrittenTotal == 0)
    333                             {
    334                                 /* If nothing was transfered but the file size was > 0 then "vbox_cat" wasn't able to write
    335                                  * to the destination -> access denied. */
    336                                 rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    337                                                          Utf8StrFmt(GuestSession::tr("Access denied when copying file \"%s\" to \"%s\""),
    338                                                                     mSource.c_str(), mDest.c_str()));
    339                             }
    340                             else if (cbWrittenTotal < cbFileSize)
    341                             {
    342                                 /* If we did not copy all let the user know. */
    343                                 rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    344                                                          Utf8StrFmt(GuestSession::tr("Copying file \"%s\" failed (%RU64/%RU64 bytes transfered)"),
    345                                                                     mSource.c_str(), cbWrittenTotal, cbFileSize));
    346                             }
    347                             else
    348                             {
    349                                 rc = pProcess->waitFor(ProcessWaitForFlag_Terminate,
    350                                                        30 * 1000 /* Timeout */, waitRes);
    351                                 if (   RT_FAILURE(rc)
    352                                     || waitRes.mResult != ProcessWaitResult_Terminate)
    353                                 {
    354                                     if (RT_FAILURE(rc))
    355                                         rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    356                                                                  Utf8StrFmt(GuestSession::tr("Waiting on termination for copying file \"%s\" failed: %Rrc"),
    357                                                                             mSource.c_str(), rc));
    358                                     else
    359                                         rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    360                                                                  Utf8StrFmt(GuestSession::tr("Waiting on termination for copying file \"%s\" failed with wait result %ld"),
    361                                                                             mSource.c_str(), waitRes.mResult));
    362                                 }
    363 
    364                                 if (RT_SUCCESS(rc))
    365                                 {
    366                                     ProcessStatus_T procStatus;
    367                                     LONG exitCode;
    368                                     if (   (   SUCCEEDED(pProcess->COMGETTER(Status(&procStatus)))
    369                                             && procStatus != ProcessStatus_TerminatedNormally)
    370                                         || (   SUCCEEDED(pProcess->COMGETTER(ExitCode(&exitCode)))
    371                                             && exitCode != 0)
    372                                        )
    373                                     {
    374                                         rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    375                                                                  Utf8StrFmt(GuestSession::tr("Copying file \"%s\" failed with status %ld, exit code %ld"),
    376                                                                             mSource.c_str(), procStatus, exitCode)); /**@todo Add stringify methods! */
    377                                     }
    378                                 }
    379 
    380                                 if (RT_SUCCESS(rc))
    381                                     rc = setProgressSuccess();
    382                             }
    383                         }
    384 
    385                         pProcess->close();
    386                     } /* processCreateExInteral */
    387                 } /* RTFileGetSize */
    388 
    389                 RTFileClose(fileSource);
    390 
    391             } /* RTFileOpen */
    392         } /* RTFileExists */
    393     }
    394     catch (int rc2)
    395     {
    396         rc = rc2;
    397     }
     400                        rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     401                                                 Utf8StrFmt(GuestSession::tr("Copying file \"%s\" failed with status %ld, exit code %ld"),
     402                                                            mSource.c_str(), procStatus, exitCode)); /**@todo Add stringify methods! */
     403                    }
     404                }
     405
     406                if (RT_SUCCESS(rc))
     407                    rc = setProgressSuccess();
     408            }
     409        }
     410
     411        pProcess->close();
     412    } /* processCreateExInteral */
     413
     414    if (!mSourceFile) /* Only close locally opened files. */
     415        RTFileClose(*pFile);
    398416
    399417    LogFlowFuncLeaveRC(rc);
     
    450468    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    451469
    452     int rc;
    453 
    454     /** @todo Make use of exceptions (+ finally block) here! */
    455 
    456     try
    457     {
    458         /*
    459          * Note: There will be races between querying file size + reading the guest file's
    460          *       content because we currently *do not* lock down the guest file when doing the
    461          *       actual operations.
    462          ** @todo Implement guest file locking!
    463          */
    464         GuestFsObjData objData;
    465         rc = pSession->fileQueryInfoInternal(Utf8Str(mSource), objData);
     470    /*
     471     * Note: There will be races between querying file size + reading the guest file's
     472     *       content because we currently *do not* lock down the guest file when doing the
     473     *       actual operations.
     474     ** @todo Implement guest file locking!
     475     */
     476    GuestFsObjData objData;
     477    int rc = pSession->fileQueryInfoInternal(Utf8Str(mSource), objData);
     478    if (RT_FAILURE(rc))
     479    {
     480        setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     481                            Utf8StrFmt(GuestSession::tr("Querying guest file information for \"%s\" failed: %Rrc"),
     482                            mSource.c_str(), rc));
     483    }
     484    else if (objData.mType != FsObjType_File) /* Only single files are supported at the moment. */
     485    {
     486        rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     487                                 Utf8StrFmt(GuestSession::tr("Guest file \"%s\" is not a file"), mSource.c_str()));
     488    }
     489
     490    if (RT_SUCCESS(rc))
     491    {
     492        RTFILE fileDest;
     493        rc = RTFileOpen(&fileDest, mDest.c_str(),
     494                        RTFILE_O_WRITE | RTFILE_O_OPEN_CREATE | RTFILE_O_DENY_WRITE); /** @todo Use the correct open modes! */
    466495        if (RT_FAILURE(rc))
    467496        {
    468497            setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    469                                 Utf8StrFmt(GuestSession::tr("Querying guest file information for \"%s\" failed: %Rrc"),
    470                                 mSource.c_str(), rc));
    471         }
    472         else if (objData.mType != FsObjType_File) /* Only single files are supported at the moment. */
    473         {
    474             rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    475                                      Utf8StrFmt(GuestSession::tr("Guest file \"%s\" is not a file"), mSource.c_str()));
    476         }
    477 
    478         if (RT_SUCCESS(rc))
    479         {
    480             RTFILE fileDest;
    481             rc = RTFileOpen(&fileDest, mDest.c_str(),
    482                             RTFILE_O_WRITE | RTFILE_O_OPEN_CREATE | RTFILE_O_DENY_WRITE); /** @todo Use the correct open modes! */
     498                                Utf8StrFmt(GuestSession::tr("Error opening destination file \"%s\": %Rrc"),
     499                                           mDest.c_str(), rc));
     500        }
     501        else
     502        {
     503            GuestProcessStartupInfo procInfo;
     504            procInfo.mName    = Utf8StrFmt(GuestSession::tr("Copying file \"%s\" from guest to the host to \"%s\" (%RI64 bytes)"),
     505                                                            mSource.c_str(), mDest.c_str(), objData.mObjectSize);
     506            procInfo.mCommand   = Utf8Str(VBOXSERVICE_TOOL_CAT);
     507            procInfo.mFlags     = ProcessCreateFlag_Hidden | ProcessCreateFlag_WaitForStdOut;
     508
     509            /* Set arguments.*/
     510            procInfo.mArguments.push_back(mSource); /* Which file to output? */
     511
     512            /* Startup process. */
     513            ComObjPtr<GuestProcess> pProcess;
     514            rc = pSession->processCreateExInteral(procInfo, pProcess);
     515            if (RT_SUCCESS(rc))
     516                rc = pProcess->startProcess();
    483517            if (RT_FAILURE(rc))
    484518            {
    485519                setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    486                                     Utf8StrFmt(GuestSession::tr("Error opening destination file \"%s\": %Rrc"),
    487                                                mDest.c_str(), rc));
     520                                    Utf8StrFmt(GuestSession::tr("Unable to start guest process: %Rrc"), rc));
    488521            }
    489522            else
    490523            {
    491                 GuestProcessStartupInfo procInfo;
    492                 procInfo.mName    = Utf8StrFmt(GuestSession::tr("Copying file \"%s\" from guest to the host to \"%s\" (%RI64 bytes)"),
    493                                                                 mSource.c_str(), mDest.c_str(), objData.mObjectSize);
    494                 procInfo.mCommand   = Utf8Str(VBOXSERVICE_TOOL_CAT);
    495                 procInfo.mFlags     = ProcessCreateFlag_Hidden | ProcessCreateFlag_WaitForStdOut;
    496 
    497                 /* Set arguments.*/
    498                 procInfo.mArguments.push_back(mSource); /* Which file to output? */
    499 
    500                 /* Startup process. */
    501                 ComObjPtr<GuestProcess> pProcess;
    502                 rc = pSession->processCreateExInteral(procInfo, pProcess);
    503                 if (RT_SUCCESS(rc))
    504                     rc = pProcess->startProcess();
    505                 if (RT_FAILURE(rc))
     524                GuestProcessWaitResult waitRes;
     525                BYTE byBuf[_64K];
     526
     527                BOOL fCanceled = FALSE;
     528                uint64_t cbWrittenTotal = 0;
     529                uint64_t cbToRead = objData.mObjectSize;
     530
     531                for (;;)
    506532                {
    507                     setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    508                                         Utf8StrFmt(GuestSession::tr("Unable to start guest process: %Rrc"), rc));
    509                 }
    510                 else
    511                 {
    512                     GuestProcessWaitResult waitRes;
    513                     BYTE byBuf[_64K];
    514 
    515                     BOOL fCanceled = FALSE;
    516                     uint64_t cbWrittenTotal = 0;
    517                     uint64_t cbToRead = objData.mObjectSize;
    518 
    519                     for (;;)
     533                    rc = pProcess->waitFor(ProcessWaitForFlag_StdOut,
     534                                           30 * 1000 /* Timeout */, waitRes);
     535                    if (   RT_FAILURE(rc)
     536                        || waitRes.mResult != ProcessWaitResult_StdOut)
    520537                    {
    521                         rc = pProcess->waitFor(ProcessWaitForFlag_StdOut,
    522                                                30 * 1000 /* Timeout */, waitRes);
    523                         if (   RT_FAILURE(rc)
    524                             || waitRes.mResult != ProcessWaitResult_StdOut)
    525                         {
    526                             break;
    527                         }
    528 
    529                         size_t cbRead;
    530                         rc = pProcess->readData(OUTPUT_HANDLE_ID_STDOUT, sizeof(byBuf),
    531                                                 30 * 1000 /* Timeout */, byBuf, sizeof(byBuf),
    532                                                 &cbRead);
     538                        break;
     539                    }
     540
     541                    size_t cbRead;
     542                    rc = pProcess->readData(OUTPUT_HANDLE_ID_STDOUT, sizeof(byBuf),
     543                                            30 * 1000 /* Timeout */, byBuf, sizeof(byBuf),
     544                                            &cbRead);
     545                    if (RT_FAILURE(rc))
     546                    {
     547                        setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     548                                            Utf8StrFmt(GuestSession::tr("Reading from file \"%s\" (offset %RU64) failed: %Rrc"),
     549                                            mSource.c_str(), cbWrittenTotal, rc));
     550                        break;
     551                    }
     552
     553                    if (cbRead)
     554                    {
     555                        rc = RTFileWrite(fileDest, byBuf, cbRead, NULL /* No partial writes */);
    533556                        if (RT_FAILURE(rc))
    534557                        {
    535558                            setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    536                                                 Utf8StrFmt(GuestSession::tr("Reading from file \"%s\" (offset %RU64) failed: %Rrc"),
    537                                                 mSource.c_str(), cbWrittenTotal, rc));
     559                                                Utf8StrFmt(GuestSession::tr("Error writing to file \"%s\" (%RU64 bytes left): %Rrc"),
     560                                                mDest.c_str(), cbToRead, rc));
    538561                            break;
    539562                        }
    540563
    541                         if (cbRead)
     564                        /* Only subtract bytes reported written by the guest. */
     565                        Assert(cbToRead >= cbRead);
     566                        cbToRead -= cbRead;
     567
     568                        /* Update total bytes written to the guest. */
     569                        cbWrittenTotal += cbRead;
     570                        Assert(cbWrittenTotal <= (uint64_t)objData.mObjectSize);
     571
     572                        /* Did the user cancel the operation above? */
     573                        if (   SUCCEEDED(mProgress->COMGETTER(Canceled(&fCanceled)))
     574                            && fCanceled)
     575                            break;
     576
     577                        rc = setProgress((ULONG)(cbWrittenTotal / ((uint64_t)objData.mObjectSize / 100.0)));
     578                        if (RT_FAILURE(rc))
     579                            break;
     580
     581                        /* End of file reached? */
     582                        if (cbToRead == 0)
     583                            break;
     584                    }
     585                } /* for */
     586
     587                if (   !fCanceled
     588                    || RT_SUCCESS(rc))
     589                {
     590                    /*
     591                     * Even if we succeeded until here make sure to check whether we really transfered
     592                     * everything.
     593                     */
     594                    if (   objData.mObjectSize > 0
     595                        && cbWrittenTotal == 0)
     596                    {
     597                        /* If nothing was transfered but the file size was > 0 then "vbox_cat" wasn't able to write
     598                         * to the destination -> access denied. */
     599                        rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     600                                                 Utf8StrFmt(GuestSession::tr("Access denied when copying file \"%s\" to \"%s\""),
     601                                                 mSource.c_str(), mDest.c_str()));
     602                    }
     603                    else if (cbWrittenTotal < (uint64_t)objData.mObjectSize)
     604                    {
     605                        /* If we did not copy all let the user know. */
     606                        rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     607                                                 Utf8StrFmt(GuestSession::tr("Copying file \"%s\" failed (%RU64/%RU64 bytes transfered)"),
     608                                                 mSource.c_str(), cbWrittenTotal, objData.mObjectSize));
     609                    }
     610                    else
     611                    {
     612                        ProcessStatus_T procStatus;
     613                        LONG exitCode;
     614                        if (   (   SUCCEEDED(pProcess->COMGETTER(Status(&procStatus)))
     615                                && procStatus != ProcessStatus_TerminatedNormally)
     616                            || (   SUCCEEDED(pProcess->COMGETTER(ExitCode(&exitCode)))
     617                                && exitCode != 0)
     618                           )
    542619                        {
    543                             rc = RTFileWrite(fileDest, byBuf, cbRead, NULL /* No partial writes */);
    544                             if (RT_FAILURE(rc))
    545                             {
    546                                 setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    547                                                     Utf8StrFmt(GuestSession::tr("Error writing to file \"%s\" (%RU64 bytes left): %Rrc"),
    548                                                     mDest.c_str(), cbToRead, rc));
    549                                 break;
    550                             }
    551 
    552                             /* Only subtract bytes reported written by the guest. */
    553                             Assert(cbToRead >= cbRead);
    554                             cbToRead -= cbRead;
    555 
    556                             /* Update total bytes written to the guest. */
    557                             cbWrittenTotal += cbRead;
    558                             Assert(cbWrittenTotal <= (uint64_t)objData.mObjectSize);
    559 
    560                             /* Did the user cancel the operation above? */
    561                             if (   SUCCEEDED(mProgress->COMGETTER(Canceled(&fCanceled)))
    562                                 && fCanceled)
    563                                 break;
    564 
    565                             rc = setProgress((ULONG)(cbWrittenTotal / ((uint64_t)objData.mObjectSize / 100.0)));
    566                             if (RT_FAILURE(rc))
    567                                 break;
    568 
    569                             /* End of file reached? */
    570                             if (cbToRead == 0)
    571                                 break;
     620                            rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     621                                                     Utf8StrFmt(GuestSession::tr("Copying file \"%s\" failed with status %ld, exit code %d"),
     622                                                                mSource.c_str(), procStatus, exitCode)); /**@todo Add stringify methods! */
    572623                        }
    573                     } /* for */
    574 
    575                     if (   !fCanceled
    576                         || RT_SUCCESS(rc))
    577                     {
    578                         /*
    579                          * Even if we succeeded until here make sure to check whether we really transfered
    580                          * everything.
    581                          */
    582                         if (   objData.mObjectSize > 0
    583                             && cbWrittenTotal == 0)
    584                         {
    585                             /* If nothing was transfered but the file size was > 0 then "vbox_cat" wasn't able to write
    586                              * to the destination -> access denied. */
    587                             rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    588                                                      Utf8StrFmt(GuestSession::tr("Access denied when copying file \"%s\" to \"%s\""),
    589                                                      mSource.c_str(), mDest.c_str()));
    590                         }
    591                         else if (cbWrittenTotal < (uint64_t)objData.mObjectSize)
    592                         {
    593                             /* If we did not copy all let the user know. */
    594                             rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    595                                                      Utf8StrFmt(GuestSession::tr("Copying file \"%s\" failed (%RU64/%RU64 bytes transfered)"),
    596                                                      mSource.c_str(), cbWrittenTotal, objData.mObjectSize));
    597                         }
    598                         else
    599                         {
    600                             ProcessStatus_T procStatus;
    601                             LONG exitCode;
    602                             if (   (   SUCCEEDED(pProcess->COMGETTER(Status(&procStatus)))
    603                                     && procStatus != ProcessStatus_TerminatedNormally)
    604                                 || (   SUCCEEDED(pProcess->COMGETTER(ExitCode(&exitCode)))
    605                                     && exitCode != 0)
    606                                )
    607                             {
    608                                 rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    609                                                          Utf8StrFmt(GuestSession::tr("Copying file \"%s\" failed with status %ld, exit code %d"),
    610                                                                     mSource.c_str(), procStatus, exitCode)); /**@todo Add stringify methods! */
    611                             }
    612                             else /* Yay, success! */
    613                                 rc = setProgressSuccess();
    614                         }
     624                        else /* Yay, success! */
     625                            rc = setProgressSuccess();
    615626                    }
    616 
    617                     pProcess->close();
    618627                }
    619628
    620                 RTFileClose(fileDest);
     629                pProcess->close();
    621630            }
    622         }
    623     }
    624     catch (int rc2)
    625     {
    626         rc = rc2;
     631
     632            RTFileClose(fileDest);
     633        }
    627634    }
    628635
     
    650657{
    651658    std::auto_ptr<SessionTaskCopyFrom> task(static_cast<SessionTaskCopyFrom*>(pvUser));
     659    AssertReturn(task.get(), VERR_GENERAL_FAILURE);
     660
     661    LogFlowFunc(("pTask=%p\n", task.get()));
     662    return task->Run();
     663}
     664
     665SessionTaskUpdateAdditions::SessionTaskUpdateAdditions(GuestSession *pSession,
     666                                                       const Utf8Str &strSource, uint32_t uFlags)
     667                                                       : GuestSessionTask(pSession)
     668{
     669    mSource = strSource;
     670    mFlags  = uFlags;
     671}
     672
     673SessionTaskUpdateAdditions::~SessionTaskUpdateAdditions(void)
     674{
     675
     676}
     677
     678int SessionTaskUpdateAdditions::Run(void)
     679{
     680    LogFlowThisFuncEnter();
     681
     682    ComObjPtr<GuestSession> pSession = mSession;
     683    Assert(!pSession.isNull());
     684
     685    AutoCaller autoCaller(pSession);
     686    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     687
     688    int rc = setProgress(10);
     689    if (RT_FAILURE(rc))
     690        return rc;
     691
     692    HRESULT hr = S_OK;
     693
     694    LogRel(("Automatic update of Guest Additions started, using \"%s\"\n", mSource.c_str()));
     695
     696    /*
     697     * Determine guest OS type and the required installer image.
     698     * At the moment only Windows guests are supported.
     699     */
     700    Utf8Str strInstallerImage;
     701
     702    ComObjPtr<Guest> pGuest(mSession->getParent());
     703    Bstr osTypeId;
     704    if (   SUCCEEDED(pGuest->COMGETTER(OSTypeId(osTypeId.asOutParam())))
     705        && !osTypeId.isEmpty())
     706    {
     707        Utf8Str osTypeIdUtf8(osTypeId); /* Needed for .contains(). */
     708        if (   osTypeIdUtf8.contains("Microsoft", Utf8Str::CaseInsensitive)
     709            || osTypeIdUtf8.contains("Windows", Utf8Str::CaseInsensitive))
     710        {
     711            if (osTypeIdUtf8.contains("64", Utf8Str::CaseInsensitive))
     712                strInstallerImage = "VBOXWINDOWSADDITIONS_AMD64.EXE";
     713            else
     714                strInstallerImage = "VBOXWINDOWSADDITIONS_X86.EXE";
     715            /* Since the installers are located in the root directory,
     716             * no further path processing needs to be done (yet). */
     717        }
     718        else /* Everything else is not supported (yet). */
     719        {
     720            hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     721                                     Utf8StrFmt(GuestSession::tr("Detected guest OS (%s) does not support automatic Guest Additions updating, please update manually"),
     722                                     osTypeIdUtf8.c_str()));
     723            rc = VERR_GENERAL_FAILURE; /* Fudge. */
     724        }
     725    }
     726    else
     727    {
     728        hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     729                                 Utf8StrFmt(GuestSession::tr("Could not detected guest OS type/version, please update manually")));
     730        rc = VERR_GENERAL_FAILURE; /* Fudge. */
     731    }
     732
     733    RTISOFSFILE iso;
     734    uint32_t cbOffset;
     735    size_t cbSize;
     736
     737    if (RT_SUCCESS(rc))
     738    {
     739        Assert(!strInstallerImage.isEmpty());
     740
     741        /*
     742         * Try to open the .ISO file and locate the specified installer.
     743         */
     744        rc = RTIsoFsOpen(&iso, mSource.c_str());
     745        if (RT_FAILURE(rc))
     746        {
     747            hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     748                                     Utf8StrFmt(GuestSession::tr("Invalid installation medium \"%s\" detected: %Rrc"),
     749                                     mSource.c_str(), rc));
     750        }
     751        else
     752        {
     753            rc = RTIsoFsGetFileInfo(&iso, strInstallerImage.c_str(), &cbOffset, &cbSize);
     754            if (   RT_SUCCESS(rc)
     755                && cbOffset
     756                && cbSize)
     757            {
     758                rc = RTFileSeek(iso.file, cbOffset, RTFILE_SEEK_BEGIN, NULL);
     759                if (RT_FAILURE(rc))
     760                    hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     761                                             Utf8StrFmt(GuestSession::tr("Could not seek to setup file on installation medium \"%s\": %Rrc"),
     762                                             mSource.c_str(), rc));
     763            }
     764            else
     765            {
     766                switch (rc)
     767                {
     768                    case VERR_FILE_NOT_FOUND:
     769                        hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     770                                                 Utf8StrFmt(GuestSession::tr("Setup file was not found on installation medium \"%s\""),
     771                                                 mSource.c_str()));
     772                        break;
     773
     774                    default:
     775                        hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     776                                                 Utf8StrFmt(GuestSession::tr("An unknown error (%Rrc) occured while retrieving information of setup file on installation medium \"%s\""),
     777                                                 rc, mSource.c_str()));
     778                        break;
     779                }
     780            }
     781
     782            /* Specify the ouput path on the guest side. */
     783            /** @todo Add support for non-Windows as well! */
     784            Utf8Str strInstallerDest = "%TEMP%\\VBoxWindowsAdditions.exe";
     785
     786            /* Copy over the Guest Additions installer to the guest. */
     787            if (RT_SUCCESS(rc))
     788            {
     789                LogRel(("Copying Guest Additions installer \"%s\" to \"%s\" on guest ...\n",
     790                        strInstallerImage.c_str(), strInstallerDest.c_str()));
     791
     792                rc = setProgress(15);
     793                if (RT_SUCCESS(rc))
     794                {
     795                    SessionTaskCopyTo *pTask = new SessionTaskCopyTo(pSession /* GuestSession */,
     796                                                                     &iso.file, cbOffset, cbSize,
     797                                                                     strInstallerDest, CopyFileFlag_None);
     798                    AssertPtrReturn(pTask, VERR_NO_MEMORY);
     799
     800                    ComObjPtr<Progress> pProgressCopyTo;
     801                    rc = pSession->startTaskAsync(Utf8StrFmt(GuestSession::tr("Copying Guest Additions installer from \"%s\" to \"%s\" on the guest"),
     802                                                             mSource.c_str(), strInstallerDest.c_str()),
     803                                                  pTask, pProgressCopyTo);
     804                    if (RT_FAILURE(rc))
     805                    {
     806                        hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     807                                                 Utf8StrFmt(GuestSession::tr("Unable to start copying Guest Additions installer \"%s\" to \"%s\": %Rrc"),
     808                                                 mSource.c_str(), strInstallerDest.c_str(), rc));
     809                    }
     810                    else
     811                    {
     812                        BOOL fCanceled = FALSE;
     813                        hr = pProgressCopyTo->WaitForCompletion(-1);
     814                        if (SUCCEEDED(hr))
     815                        {
     816                            rc = setProgress(20);
     817                        }
     818                        else if (   SUCCEEDED(pProgressCopyTo->COMGETTER(Canceled)(&fCanceled))
     819                                 && fCanceled)
     820                        {
     821                            hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     822                                                     Utf8StrFmt(GuestSession::tr("Copying Guest Additions installer \"%s\" to \"%s\" was canceled"),
     823                                                     mSource.c_str(), strInstallerDest.c_str(), hr));
     824                            rc = VERR_GENERAL_FAILURE; /* Fudge. */
     825                        }
     826                        else
     827                        {
     828                            Assert(FAILED(hr));
     829                            hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     830                                                     Utf8StrFmt(GuestSession::tr("Error while copying Guest Additions installer \"%s\" to \"%s\": %Rhrc"),
     831                                                     mSource.c_str(), strInstallerDest.c_str(), hr));
     832                            rc = VERR_GENERAL_FAILURE; /* Fudge. */
     833                        }
     834                    }
     835                }
     836            }
     837
     838            if (RT_SUCCESS(rc))
     839            {
     840                /* Install needed certificates for the WHQL crap. */
     841                /** @todo Copy over VBoxCertUtil? */
     842                rc = setProgress(25);
     843            }
     844
     845            if (RT_SUCCESS(rc))
     846            {
     847                /*
     848                 * Installer was transferred successfully, so let's start it
     849                 * (with system rights).
     850                 */
     851                LogRel(("Starting Guest Additions installer ...\n"));
     852                rc = setProgress(60);
     853            }
     854
     855            if (RT_SUCCESS(rc))
     856            {
     857                GuestProcessStartupInfo procInfo;
     858                procInfo.mName    = Utf8StrFmt(GuestSession::tr("Guest Additions Setup"));
     859                procInfo.mCommand = Utf8Str(strInstallerDest);
     860                procInfo.mFlags   = ProcessCreateFlag_Hidden;
     861                /* If the caller does not want to wait for out guest update process to end,
     862                 * complete the progress object now so that the caller can do other work. */
     863                if (mFlags & AdditionsUpdateFlag_WaitForUpdateStartOnly)
     864                    procInfo.mFlags |= ProcessCreateFlag_WaitForProcessStartOnly;
     865
     866                /* Construct arguments. */
     867                procInfo.mArguments.push_back(Utf8Str("/S")); /* We want to install in silent mode. */
     868                procInfo.mArguments.push_back(Utf8Str("/l")); /* ... and logging enabled. */
     869                /* Don't quit VBoxService during upgrade because it still is used for this
     870                 * piece of code we're in right now (that is, here!) ... */
     871                procInfo.mArguments.push_back(Utf8Str("/no_vboxservice_exit"));
     872                /* Tell the installer to report its current installation status
     873                 * using a running VBoxTray instance via balloon messages in the
     874                 * Windows taskbar. */
     875                procInfo.mArguments.push_back(Utf8Str("/post_installstatus"));
     876
     877                ComObjPtr<GuestProcess> pProcess;
     878                rc = pSession->processCreateExInteral(procInfo, pProcess);
     879                if (RT_SUCCESS(rc))
     880                    rc = pProcess->startProcess();
     881                if (RT_SUCCESS(rc))
     882                    rc = setProgress(65);
     883                if (RT_SUCCESS(rc))
     884                {
     885                    LogRel(("Updating Guest Additions in progress ...\n"));
     886
     887                    GuestProcessWaitResult waitRes;
     888                    rc = pProcess->waitFor(ProcessWaitForFlag_Terminate,
     889                                           10 * 60 * 1000 /* 10 mins Timeout */, waitRes);
     890                    if (waitRes.mResult == ProcessWaitResult_Terminate)
     891                    {
     892                        ProcessStatus_T procStatus;
     893                        LONG exitCode;
     894                        if (   (   SUCCEEDED(pProcess->COMGETTER(Status(&procStatus)))
     895                                && procStatus != ProcessStatus_TerminatedNormally)
     896                            || (   SUCCEEDED(pProcess->COMGETTER(ExitCode(&exitCode)))
     897                                && exitCode != 0)
     898                           )
     899                        {
     900                            rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     901                                                     Utf8StrFmt(GuestSession::tr("Updating Guest Additions failed with status %ld, exit code %d"),
     902                                                                procStatus, exitCode)); /**@todo Add stringify methods! */
     903                        }
     904                        else /* Yay, success! */
     905                            rc = setProgressSuccess();
     906                    }
     907                    else
     908                    {
     909                        if (RT_FAILURE(rc))
     910                            hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     911                                                     Utf8StrFmt(GuestSession::tr("Error while waiting for Guest Additions update: %Rrc"), rc));
     912                        else
     913                            hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     914                                                     Utf8StrFmt(GuestSession::tr("Error installing Guest Additions update: %Rrc"),
     915                                                                waitRes.mRC));
     916                    }
     917                }
     918            }
     919            RTIsoFsClose(&iso);
     920        }
     921    }
     922
     923    LogFlowFuncLeaveRC(rc);
     924    return rc;
     925}
     926
     927int SessionTaskUpdateAdditions::RunAsync(const Utf8Str &strDesc, ComObjPtr<Progress> &pProgress)
     928{
     929    LogFlowThisFunc(("strDesc=%s, strSource=%s, uFlags=%x\n",
     930                     strDesc.c_str(), mSource.c_str(), mFlags));
     931
     932    mDesc = strDesc;
     933    mProgress = pProgress;
     934
     935    int rc = RTThreadCreate(NULL, SessionTaskUpdateAdditions::taskThread, this,
     936                            0, RTTHREADTYPE_MAIN_HEAVY_WORKER, 0,
     937                            "gctlUpGA");
     938    LogFlowFuncLeaveRC(rc);
     939    return rc;
     940}
     941
     942/* static */
     943int SessionTaskUpdateAdditions::taskThread(RTTHREAD Thread, void *pvUser)
     944{
     945    std::auto_ptr<SessionTaskUpdateAdditions> task(static_cast<SessionTaskUpdateAdditions*>(pvUser));
    652946    AssertReturn(task.get(), VERR_GENERAL_FAILURE);
    653947
     
    10641358        return rc;
    10651359
    1066     try
    1067     {
    1068         AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    1069 
    1070         /* Create the directory object. */
    1071         HRESULT hr = pDirectory.createObject();
    1072         if (FAILED(hr)) throw VERR_COM_UNEXPECTED;
    1073 
    1074         /* Note: There will be a race between creating and getting/initing the directory
    1075                  object here. */
    1076         rc = pDirectory->init(this /* Parent */, strPath);
    1077         if (RT_FAILURE(rc)) throw rc;
    1078 
    1079         /* Add the created directory to our vector. */
    1080         mData.mDirectories.push_back(pDirectory);
    1081 
    1082         LogFlowFunc(("Added new directory \"%s\" (Session: %RU32)\n",
    1083                      strPath.c_str(), mData.mId));
    1084     }
    1085     catch (int rc2)
    1086     {
    1087         rc = rc2;
    1088     }
     1360    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     1361
     1362    /* Create the directory object. */
     1363    HRESULT hr = pDirectory.createObject();
     1364    if (FAILED(hr))
     1365        return VERR_COM_UNEXPECTED;
     1366
     1367    /* Note: There will be a race between creating and getting/initing the directory
     1368             object here. */
     1369    rc = pDirectory->init(this /* Parent */, strPath);
     1370    if (RT_FAILURE(rc))
     1371        return rc;
     1372
     1373    /* Add the created directory to our vector. */
     1374    mData.mDirectories.push_back(pDirectory);
     1375
     1376    LogFlowFunc(("Added new directory \"%s\" (Session: %RU32)\n",
     1377                 strPath.c_str(), mData.mId));
    10891378
    10901379    LogFlowFuncLeaveRC(rc);
     
    10971386    LogFlowThisFunc(("strPath=%s, strPath=%s, uFlags=%x\n",
    10981387                     strPath.c_str(), strFilter.c_str(), uFlags));
    1099     int rc;
    1100 
    1101     try
    1102     {
    1103         AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    1104 
    1105         /* Create the directory object. */
    1106         HRESULT hr = pDirectory.createObject();
    1107         if (FAILED(hr)) throw VERR_COM_UNEXPECTED;
    1108 
    1109         rc = pDirectory->init(this /* Parent */,
     1388
     1389    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     1390
     1391    /* Create the directory object. */
     1392    HRESULT hr = pDirectory.createObject();
     1393    if (FAILED(hr))
     1394        return VERR_COM_UNEXPECTED;
     1395
     1396    int rc = pDirectory->init(this /* Parent */,
    11101397                              strPath, strFilter, uFlags);
    1111         if (RT_FAILURE(rc)) throw rc;
    1112 
    1113         /* Add the created directory to our vector. */
    1114         mData.mDirectories.push_back(pDirectory);
    1115 
    1116         LogFlowFunc(("Added new directory \"%s\" (Session: %RU32)\n",
    1117                      strPath.c_str(), mData.mId));
    1118     }
    1119     catch (int rc2)
    1120     {
    1121         rc = rc2;
    1122     }
     1398    if (RT_FAILURE(rc))
     1399        return rc;
     1400
     1401    /* Add the created directory to our vector. */
     1402    mData.mDirectories.push_back(pDirectory);
     1403
     1404    LogFlowFunc(("Added new directory \"%s\" (Session: %RU32)\n",
     1405                 strPath.c_str(), mData.mId));
    11231406
    11241407    LogFlowFuncLeaveRC(rc);
     
    12621545    LogFlowThisFunc(("strPath=%s, strOpenMode=%s, strDisposition=%s, uCreationMode=%x, iOffset=%RI64\n",
    12631546                     strPath.c_str(), strOpenMode.c_str(), strDisposition.c_str(), uCreationMode, iOffset));
    1264     int rc;
    1265 
    1266     try
    1267     {
    1268         /* Create the directory object. */
    1269         HRESULT hr = pFile.createObject();
    1270         if (FAILED(hr)) throw VERR_COM_UNEXPECTED;
    1271 
    1272         /* Note: There will be a race between creating and getting/initing the directory
    1273                  object here. */
    1274         rc = pFile->init(this /* Parent */,
     1547
     1548    /* Create the directory object. */
     1549    HRESULT hr = pFile.createObject();
     1550    if (FAILED(hr))
     1551        return VERR_COM_UNEXPECTED;
     1552
     1553    /* Note: There will be a race between creating and getting/initing the directory
     1554             object here. */
     1555    int rc = pFile->init(this /* Parent */,
    12751556                         strPath, strOpenMode, strDisposition, uCreationMode, iOffset);
    1276         if (RT_FAILURE(rc)) throw rc;
    1277 
    1278         /* Add the created directory to our vector. */
    1279         mData.mFiles.push_back(pFile);
    1280 
    1281         LogFlowFunc(("Added new file \"%s\" (Session: %RU32\n",
    1282                      strPath.c_str(), mData.mId));
    1283     }
    1284     catch (int rc2)
    1285     {
    1286         rc = rc2;
    1287     }
     1557    if (RT_FAILURE(rc))
     1558        return rc;
     1559
     1560    /* Add the created directory to our vector. */
     1561    mData.mFiles.push_back(pFile);
     1562
     1563    LogFlowFunc(("Added new file \"%s\" (Session: %RU32\n",
     1564                 strPath.c_str(), mData.mId));
    12881565
    12891566    LogFlowFuncLeaveRC(rc);
     
    14911768            break; /* Don't try too hard. */
    14921769    }
    1493     if (RT_FAILURE(rc)) return rc;
    1494 
    1495     try
    1496     {
    1497         /* Create the process object. */
    1498         HRESULT hr = pProcess.createObject();
    1499         if (FAILED(hr)) throw VERR_COM_UNEXPECTED;
    1500 
    1501         rc = pProcess->init(mData.mParent->getConsole() /* Console */, this /* Session */,
    1502                             uNewProcessID, procInfo);
    1503         if (RT_FAILURE(rc)) throw rc;
    1504 
    1505         /* Add the created process to our map. */
    1506         mData.mProcesses[uNewProcessID] = pProcess;
    1507 
    1508         LogFlowFunc(("Added new process (Session: %RU32) with process ID=%RU32 (now total %ld processes)\n",
    1509                      mData.mId, uNewProcessID, mData.mProcesses.size()));
    1510     }
    1511     catch (int rc2)
    1512     {
    1513         rc = rc2;
    1514     }
     1770
     1771    if (RT_FAILURE(rc))
     1772        return rc;
     1773
     1774    /* Create the process object. */
     1775    HRESULT hr = pProcess.createObject();
     1776    if (FAILED(hr))
     1777        return VERR_COM_UNEXPECTED;
     1778
     1779    rc = pProcess->init(mData.mParent->getConsole() /* Console */, this /* Session */,
     1780                        uNewProcessID, procInfo);
     1781    if (RT_FAILURE(rc))
     1782        return rc;
     1783
     1784    /* Add the created process to our map. */
     1785    mData.mProcesses[uNewProcessID] = pProcess;
     1786
     1787    LogFlowFunc(("Added new process (Session: %RU32) with process ID=%RU32 (now total %ld processes)\n",
     1788                 mData.mId, uNewProcessID, mData.mProcesses.size()));
    15151789
    15161790    return rc;
     
    15601834    AssertPtrReturn(pTask, VERR_INVALID_POINTER);
    15611835
    1562     int rc;
    1563 
    1564     try
    1565     {
    1566         /* Create the progress object. */
    1567         HRESULT hr = pProgress.createObject();
    1568         if (FAILED(hr)) throw VERR_COM_UNEXPECTED;
    1569 
    1570         hr = pProgress->init(static_cast<IGuestSession*>(this),
    1571                              Bstr(strTaskDesc).raw(),
    1572                              TRUE /* aCancelable */);
    1573         if (FAILED(hr)) throw VERR_COM_UNEXPECTED;
    1574 
    1575         /* Initialize our worker task. */
    1576         std::auto_ptr<GuestSessionTask> task(pTask);
    1577 
    1578         rc = task->RunAsync(strTaskDesc, pProgress);
    1579         if (FAILED(rc)) throw rc;
    1580 
    1581         /* Don't destruct on success. */
    1582         task.release();
    1583     }
    1584     catch (int rc2)
    1585     {
    1586         rc = rc2;
    1587     }
     1836    /* Create the progress object. */
     1837    HRESULT hr = pProgress.createObject();
     1838    if (FAILED(hr))
     1839        return VERR_COM_UNEXPECTED;
     1840
     1841    hr = pProgress->init(static_cast<IGuestSession*>(this),
     1842                         Bstr(strTaskDesc).raw(),
     1843                         TRUE /* aCancelable */);
     1844    if (FAILED(hr))
     1845        return VERR_COM_UNEXPECTED;
     1846
     1847    /* Initialize our worker task. */
     1848    std::auto_ptr<GuestSessionTask> task(pTask);
     1849
     1850    int rc = task->RunAsync(strTaskDesc, pProgress);
     1851    if (RT_FAILURE(rc))
     1852        return rc;
     1853
     1854    /* Don't destruct on success. */
     1855    task.release();
    15881856
    15891857    LogFlowFuncLeaveRC(rc);
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette