VirtualBox

Changeset 42693 in vbox for trunk/src/VBox


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

Guest Control 2.0: Update.

Location:
trunk/src/VBox
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp

    r42668 r42693  
    16591659    {
    16601660#ifndef VBOX_WITH_GUEST_CONTROL2
     1661        Assert(!fFlags);
    16611662        rc = pContext->pGuest->CopyToGuest(Bstr(pszFileSource).raw(), Bstr(pszFileDest).raw(),
    16621663                                           Bstr(pContext->strUsername).raw(), Bstr(pContext->strPassword).raw(),
    16631664                                           fFlags, pProgress.asOutParam());
    16641665#else
    1665         Assert(!fFlags);
    16661666        SafeArray<CopyFileFlag_T> copyFlags;
    16671667        rc = pContext->pGuestSession->CopyTo(Bstr(pszFileSource).raw(), Bstr(pszFileDest).raw(),
     
    16741674    {
    16751675#ifndef VBOX_WITH_GUEST_CONTROL2
     1676        Assert(!fFlags);
    16761677        rc = pContext->pGuest->CopyFromGuest(Bstr(pszFileSource).raw(), Bstr(pszFileDest).raw(),
    16771678                                             Bstr(pContext->strUsername).raw(), Bstr(pContext->strPassword).raw(),
    16781679                                             fFlags, pProgress.asOutParam());
    16791680#else
    1680         Assert(!fFlags);
    16811681        SafeArray<CopyFileFlag_T> copyFlags;
    16821682        rc = pContext->pGuestSession->CopyFrom(Bstr(pszFileSource).raw(), Bstr(pszFileDest).raw(),
     
    28092809        HRESULT rc = S_OK;
    28102810        ComPtr<IProgress> pProgress;
     2811
     2812        SafeArray<AdditionsUpdateFlag_T> updateFlags;
    28112813        CHECK_ERROR(guest, UpdateGuestAdditions(Bstr(strSource).raw(),
    28122814                                                /* Wait for whole update process to complete. */
    2813                                                 AdditionsUpdateFlag_None,
     2815                                                ComSafeArrayAsInParam(updateFlags),
    28142816                                                pProgress.asOutParam()));
    28152817        if (FAILED(rc))
  • trunk/src/VBox/Main/idl/VirtualBox.xidl

    r42673 r42693  
    1066810668  <interface
    1066910669    name="IGuest" extends="$unknown"
    10670     uuid="9e0b07b1-490f-4413-8955-0a16515aac12"
     10670    uuid="19c32350-0618-4ede-b0c3-2b4311bf0d9b"
    1067110671    wsmap="managed"
    1067210672    >
     
    1159011590        </desc>
    1159111591      </param>
    11592       <param name="flags" type="unsigned long" dir="in">
     11592      <param name="flags" type="AdditionsUpdateFlag" dir="in" safearray="yes">
    1159311593        <desc>
    1159411594          <link to="AdditionsUpdateFlag"/> flags.
  • trunk/src/VBox/Main/include/GuestCtrlImplPrivate.h

    r42673 r42693  
    172172struct GuestProcessWaitResult
    173173{
     174    GuestProcessWaitResult(void)
     175        : mResult(ProcessWaitResult_None),
     176          mRC(VINF_SUCCESS) { }
     177
    174178    /** The wait result when returning from the wait call. */
    175179    ProcessWaitResult_T         mResult;
     180    /** Optional rc to this result. */
    176181    int                         mRC;
    177182};
  • trunk/src/VBox/Main/include/GuestImpl.h

    r42461 r42693  
    132132                                     ULONG *aMemTotal, ULONG *aMemFree, ULONG *aMemBalloon, ULONG *aMemShared, ULONG *aMemCache,
    133133                                     ULONG *aPageTotal, ULONG *aMemAllocTotal, ULONG *aMemFreeTotal, ULONG *aMemBalloonTotal, ULONG *aMemSharedTotal);
    134     STDMETHOD(UpdateGuestAdditions)(IN_BSTR aSource, ULONG aFlags, IProgress **aProgress);
     134    STDMETHOD(UpdateGuestAdditions)(IN_BSTR aSource, ComSafeArrayIn(AdditionsUpdateFlag_T, aFlags), IProgress **aProgress);
    135135    STDMETHOD(CreateSession)(IN_BSTR aUser, IN_BSTR aPassword, IN_BSTR aDomain, IN_BSTR aSessionName, IGuestSession **aGuestSession);
    136136    STDMETHOD(FindSession)(IN_BSTR aSessionName, ComSafeArrayOut(IGuestSession *, aSessions));
     
    210210    Console    *getConsole(void) { return mParent; }
    211211    int         sessionClose(ComObjPtr<GuestSession> pSession);
    212     int         sessionCreate(const Utf8Str &strUser, const Utf8Str &aPassword, const Utf8Str &aDomain,
    213                               const Utf8Str &aSessionName, ComObjPtr<GuestSession> &pGuestSession);
     212    int         sessionCreate(const Utf8Str &strUser, const Utf8Str &strPassword, const Utf8Str &strDomain,
     213                              const Utf8Str &strSessionName, ComObjPtr<GuestSession> &pGuestSession);
    214214    inline bool sessionExists(uint32_t uSessionID);
    215215    /** @}  */
  • trunk/src/VBox/Main/include/GuestSessionImpl.h

    r42691 r42693  
    4949    int setProgress(ULONG uPercent);
    5050    int setProgressSuccess(void);
    51     int setProgressErrorMsg(HRESULT hr, const Utf8Str &strMsg);
     51    HRESULT setProgressErrorMsg(HRESULT hr, const Utf8Str &strMsg);
    5252
    5353protected:
     
    7070                      const Utf8Str &strSource, const Utf8Str &strDest, uint32_t uFlags);
    7171
     72    SessionTaskCopyTo(GuestSession *pSession,
     73                      PRTFILE pSourceFile, size_t cbSourceOffset, size_t cbSourceSize,
     74                      const Utf8Str &strDest, uint32_t uFlags);
     75
    7276    virtual ~SessionTaskCopyTo(void);
    7377
     
    8185
    8286    Utf8Str  mSource;
     87    PRTFILE  mSourceFile;
     88    size_t   mSourceOffset;
     89    size_t   mSourceSize;
    8390    Utf8Str  mDest;
    8491    uint32_t mCopyFileFlags;
     
    107114    Utf8Str  mSource;
    108115    Utf8Str  mDest;
     116    uint32_t mFlags;
     117};
     118
     119/**
     120 * Task for automatically updating the Guest Additions on the guest.
     121 */
     122class SessionTaskUpdateAdditions : public GuestSessionTask
     123{
     124public:
     125
     126    SessionTaskUpdateAdditions(GuestSession *pSession,
     127                               const Utf8Str &strSource, uint32_t uFlags);
     128
     129    virtual ~SessionTaskUpdateAdditions(void);
     130
     131public:
     132
     133    int Run(void);
     134    int RunAsync(const Utf8Str &strDesc, ComObjPtr<Progress> &pProgress);
     135    static int taskThread(RTTHREAD Thread, void *pvUser);
     136
     137protected:
     138
     139    /** The (optionally) specified Guest Additions .ISO on the host
     140     *  which will be used for the updating process. */
     141    Utf8Str  mSource;
     142    /** Update flags. */
    109143    uint32_t mFlags;
    110144};
     
    216250    const GuestEnvironment &getEnvironment(void);
    217251    Utf8Str                 getName(void);
     252    Guest                  *getParent(void) { return mData.mParent; }
    218253    uint32_t                getProtocolVersion(void) { return mData.mProtocolVersion; }
    219254    int                     processClose(ComObjPtr<GuestProcess> pProcess);
  • trunk/src/VBox/Main/src-client/GuestCtrlImpl.cpp

    r42673 r42693  
    26492649}
    26502650
    2651 STDMETHODIMP Guest::UpdateGuestAdditions(IN_BSTR aSource, ULONG aFlags, IProgress **aProgress)
     2651STDMETHODIMP Guest::UpdateGuestAdditions(IN_BSTR aSource, ComSafeArrayIn(AdditionsUpdateFlag_T, aFlags), IProgress **aProgress)
    26522652{
    26532653#ifndef VBOX_WITH_GUEST_CONTROL
     
    26612661
    26622662    /* Validate flags. */
     2663    uint32_t fFlags = AdditionsUpdateFlag_None;
    26632664    if (aFlags)
    26642665    {
    2665         if (!(aFlags & AdditionsUpdateFlag_WaitForUpdateStartOnly))
     2666        com::SafeArray<CopyFileFlag_T> flags(ComSafeArrayInArg(aFlags));
     2667        for (size_t i = 0; i < flags.size(); i++)
     2668            fFlags |= flags[i];
     2669    }
     2670
     2671    if (fFlags)
     2672    {
     2673        if (!(fFlags & AdditionsUpdateFlag_WaitForUpdateStartOnly))
    26662674            return setError(E_INVALIDARG, tr("Unknown flags (%#x)"), aFlags);
    26672675    }
     
    26692677    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    26702678
    2671     HRESULT rc = S_OK;
    2672 
     2679    HRESULT hr = S_OK;
     2680#if 1
     2681    /* Create an anonymous session. This is required to run the Guest Additions
     2682     * update process with administrative rights. */
     2683    ComObjPtr<GuestSession> pSession;
     2684    int rc = sessionCreate("" /* User */, "" /* Password */, "" /* Domain */,
     2685                           "Updating Guest Additions" /* Name */, pSession);
     2686    if (RT_FAILURE(rc))
     2687    {
     2688        switch (rc)
     2689        {
     2690            case VERR_MAX_PROCS_REACHED:
     2691                hr = setError(VBOX_E_IPRT_ERROR, tr("Maximum number of guest sessions (%ld) reached"),
     2692                              VBOX_GUESTCTRL_MAX_SESSIONS);
     2693                break;
     2694
     2695            /** @todo Add more errors here. */
     2696
     2697           default:
     2698                hr = setError(VBOX_E_IPRT_ERROR, tr("Could not create guest session: %Rrc"), rc);
     2699                break;
     2700        }
     2701    }
     2702    else
     2703    {
     2704        AssertPtr(!pSession.isNull());
     2705        rc = pSession->queryInfo();
     2706        if (RT_FAILURE(rc))
     2707        {
     2708            hr = setError(VBOX_E_IPRT_ERROR, tr("Could not query guest session information: %Rrc"), rc);
     2709        }
     2710        else
     2711        {
     2712            ComObjPtr<Progress> pProgress;
     2713            SessionTaskUpdateAdditions *pTask = new SessionTaskUpdateAdditions(pSession /* GuestSession */,
     2714                                                                               Utf8Str(aSource), fFlags);
     2715            AssertPtrReturn(pTask, VERR_NO_MEMORY);
     2716            rc = pSession->startTaskAsync(tr("Updating Guest Additions"), pTask, pProgress);
     2717            if (RT_SUCCESS(rc))
     2718            {
     2719                /* Return progress to the caller. */
     2720                hr = pProgress.queryInterfaceTo(aProgress);
     2721            }
     2722            else
     2723                hr = setError(VBOX_E_IPRT_ERROR,
     2724                              tr("Starting task for updating Guest Additions on the guest failed: %Rrc"), rc);
     2725        }
     2726    }
     2727#else /* Legacy, can be removed later. */
    26732728    ComObjPtr<Progress> progress;
    26742729    try
     
    27092764    }
    27102765    return rc;
     2766#endif
    27112767#endif /* VBOX_WITH_GUEST_CONTROL */
    27122768}
  • trunk/src/VBox/Main/src-client/GuestDirectoryImpl.cpp

    r42674 r42693  
    165165    LogFlowThisFunc(("cbStream=%RU32\n", mData.mStream.GetSize()));
    166166
     167    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     168
    167169    int rc;
    168170    do
     
    209211    Assert(!pProcess.isNull());
    210212
    211     HRESULT hr = S_OK;
    212 
    213     int rc;
    214213    GuestProcessStreamBlock streamBlock;
    215 
    216     /** @todo Make use of exceptions! */
    217 
    218     try
    219     {
    220         GuestFsObjData objData;
    221 
    222         AutoWriteLock rlock(this COMMA_LOCKVAL_SRC_POS);
    223 
    224         rc = parseData(streamBlock);
    225         if (   RT_FAILURE(rc)
    226             || streamBlock.IsEmpty()) /* More data needed. */
    227         {
    228             rlock.release();
    229 
    230             rc = pProcess->waitForStart(30 * 1000 /* Timeout */);
     214    GuestFsObjData objData;
     215
     216    int rc = parseData(streamBlock);
     217    if (   RT_FAILURE(rc)
     218        || streamBlock.IsEmpty()) /* More data needed. */
     219    {
     220        rc = pProcess->waitForStart(30 * 1000 /* 30s timeout */);
     221    }
     222
     223    if (RT_SUCCESS(rc))
     224    {
     225        BYTE byBuf[_64K];
     226        size_t cbRead = 0;
     227
     228        /** @todo Merge with GuestSession::queryFileInfoInternal. */
     229        for (;RT_SUCCESS(rc);)
     230        {
     231            GuestProcessWaitResult waitRes;
     232            rc = pProcess->waitFor(  ProcessWaitForFlag_Terminate
     233                                   | ProcessWaitForFlag_StdOut,
     234                                   30 * 1000 /* Timeout */, waitRes);
     235            if (   RT_FAILURE(rc)
     236                || waitRes.mResult == ProcessWaitResult_Terminate
     237                || waitRes.mResult == ProcessWaitResult_Error
     238                || waitRes.mResult == ProcessWaitResult_Timeout)
     239            {
     240                rc = waitRes.mRC;
     241                break;
     242            }
     243
     244            rc = pProcess->readData(OUTPUT_HANDLE_ID_STDOUT, sizeof(byBuf),
     245                                    30 * 1000 /* Timeout */, byBuf, sizeof(byBuf),
     246                                    &cbRead);
    231247            if (RT_FAILURE(rc))
    232                 return setError(VBOX_E_IPRT_ERROR,
    233                                 tr("Could not start reading directory \"%s\": %Rrc"),
    234                                 mData.mName.c_str(), rc);
    235             BYTE byBuf[_64K];
    236             size_t cbRead = 0;
    237 
    238             /** @todo Merge with GuestSession::queryFileInfoInternal. */
    239             for (;;)
     248                break;
     249
     250            if (cbRead)
    240251            {
    241                 GuestProcessWaitResult waitRes;
    242                 rc = pProcess->waitFor(  ProcessWaitForFlag_Terminate
    243                                        | ProcessWaitForFlag_StdOut,
    244                                        30 * 1000 /* Timeout */, waitRes);
    245                 if (   RT_FAILURE(rc)
    246                     || waitRes.mResult == ProcessWaitResult_Terminate
    247                     || waitRes.mResult == ProcessWaitResult_Error
    248                     || waitRes.mResult == ProcessWaitResult_Timeout)
     252                AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     253
     254                rc = mData.mStream.AddData(byBuf, cbRead);
     255                if (RT_FAILURE(rc))
     256                    break;
     257
     258                LogFlowThisFunc(("rc=%Rrc, cbRead=%RU64, cbStreamOut=%RU32\n",
     259                                 rc, cbRead, mData.mStream.GetSize()));
     260
     261                rc = parseData(streamBlock);
     262                if (RT_SUCCESS(rc))
    249263                {
     264                    /* Parsing the current stream block succeeded so
     265                     * we don't need more at the moment. */
    250266                    break;
    251267                }
    252 
    253                 rc = pProcess->readData(OUTPUT_HANDLE_ID_STDOUT, sizeof(byBuf),
    254                                         30 * 1000 /* Timeout */, byBuf, sizeof(byBuf),
    255                                         &cbRead);
    256                 if (RT_FAILURE(rc))
    257                     break;
    258 
    259                 if (cbRead)
     268            }
     269        }
     270
     271        LogFlowThisFunc(("Reading done with rc=%Rrc, cbRead=%RU64, cbStream=%RU32\n",
     272                         rc, cbRead, mData.mStream.GetSize()));
     273
     274        if (RT_SUCCESS(rc))
     275        {
     276            rc = parseData(streamBlock);
     277            if (rc == VERR_NO_DATA) /* Since this is the last parsing call, this is ok. */
     278                rc = VINF_SUCCESS;
     279        }
     280
     281        /*
     282         * Note: The guest process can still be around to serve the next
     283         *       upcoming stream block next time.
     284         */
     285        if (RT_SUCCESS(rc))
     286        {
     287            /** @todo Move into common function. */
     288            ProcessStatus_T procStatus = ProcessStatus_Undefined;
     289            LONG exitCode = 0;
     290
     291            HRESULT hr2 = pProcess->COMGETTER(Status(&procStatus));
     292            ComAssertComRC(hr2);
     293            hr2 = pProcess->COMGETTER(ExitCode(&exitCode));
     294            ComAssertComRC(hr2);
     295
     296            if (   (   procStatus != ProcessStatus_Started
     297                    && procStatus != ProcessStatus_Paused
     298                    && procStatus != ProcessStatus_Terminating
     299                   )
     300                && exitCode != 0)
     301            {
     302                rc = VERR_ACCESS_DENIED;
     303            }
     304        }
     305    }
     306
     307    if (RT_SUCCESS(rc))
     308    {
     309        if (streamBlock.GetCount()) /* Did we get content? */
     310        {
     311            rc = objData.FromLs(streamBlock);
     312            if (RT_FAILURE(rc))
     313                rc = VERR_PATH_NOT_FOUND;
     314
     315            if (RT_SUCCESS(rc))
     316            {
     317                /* Create the object. */
     318                ComObjPtr<GuestFsObjInfo> pFsObjInfo;
     319                HRESULT hr2 = pFsObjInfo.createObject();
     320                if (FAILED(hr2))
     321                    rc = VERR_COM_UNEXPECTED;
     322
     323                if (RT_SUCCESS(rc))
     324                    rc = pFsObjInfo->init(objData);
     325
     326                if (RT_SUCCESS(rc))
    260327                {
    261                     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    262 
    263                     rc = mData.mStream.AddData(byBuf, cbRead);
    264                     if (RT_FAILURE(rc))
    265                         break;
    266 
    267                     LogFlowThisFunc(("rc=%Rrc, cbRead=%RU64, cbStreamOut=%RU32\n",
    268                                      rc, cbRead, mData.mStream.GetSize()));
    269 
    270                     rc = parseData(streamBlock);
    271                     if (RT_SUCCESS(rc))
    272                     {
    273                         /* Parsing the current stream block succeeded so
    274                          * we don't need more at the moment. */
    275                         break;
    276                     }
     328                    /* Return info object to the caller. */
     329                    hr2 = pFsObjInfo.queryInterfaceTo(aInfo);
     330                    if (FAILED(hr2))
     331                        rc = VERR_COM_UNEXPECTED;
    277332                }
    278333            }
    279 
    280             LogFlowThisFunc(("Reading done with rc=%Rrc, cbRead=%RU64, cbStream=%RU32\n",
    281                              rc, cbRead, mData.mStream.GetSize()));
    282 
    283             if (RT_SUCCESS(rc))
    284             {
    285                 rc = parseData(streamBlock);
    286                 if (rc == VERR_NO_DATA) /* Since this is the last parsing call, this is ok. */
    287                     rc = VINF_SUCCESS;
    288             }
    289 
    290             /*
    291              * Note: The guest process can still be around to serve the next
    292              *       upcoming stream block next time.
    293              */
    294             if (RT_SUCCESS(rc))
    295             {
    296                 /** @todo Move into common function. */
    297                 ProcessStatus_T procStatus = ProcessStatus_Undefined;
    298                 LONG exitCode = 0;
    299 
    300                 HRESULT hr = pProcess->COMGETTER(Status(&procStatus));
    301                 ComAssertComRC(hr);
    302                 hr = pProcess->COMGETTER(ExitCode(&exitCode));
    303                 ComAssertComRC(hr);
    304 
    305                 if (   (   procStatus != ProcessStatus_Started
    306                         && procStatus != ProcessStatus_Paused
    307                         && procStatus != ProcessStatus_Terminating
    308                        )
    309                     && exitCode != 0)
    310                 {
    311                     return setError(VBOX_E_IPRT_ERROR,
    312                                     tr("Reading directory \"%s\" failed: Unable to read / access denied"),
    313                                     mData.mName.c_str(), exitCode); /**@todo Add stringify methods! */
    314                 }
    315             }
    316         }
    317 
    318         if (RT_SUCCESS(rc))
    319         {
    320             if (streamBlock.GetCount()) /* Did we get content? */
    321             {
    322                 rc = objData.FromLs(streamBlock);
    323                 if (RT_FAILURE(rc))
    324                     return setError(VBOX_E_IPRT_ERROR,
    325                                     tr("Reading directory \"%s\" failed: Path not found"),
    326                                     mData.mName.c_str());
    327 
    328                 /* Create the object. */
    329                 ComObjPtr<GuestFsObjInfo> pFsObjInfo;
    330                 hr = pFsObjInfo.createObject();
    331                 if (FAILED(hr)) throw VERR_COM_UNEXPECTED;
    332 
    333                 rc = pFsObjInfo->init(objData);
    334                 if (RT_FAILURE(rc)) throw rc;
    335 
    336                 /* Return info object to the caller. */
    337                 hr = pFsObjInfo.queryInterfaceTo(aInfo);
    338                 if (FAILED(hr)) throw VERR_COM_UNEXPECTED;
    339             }
    340             else
    341             {
    342                 /* Nothing to read anymore. Tell the caller. */
     334        }
     335        else
     336        {
     337            /* Nothing to read anymore. Tell the caller. */
     338            rc = VERR_NO_MORE_FILES;
     339        }
     340    }
     341
     342    HRESULT hr = S_OK;
     343
     344    if (RT_FAILURE(rc)) /** @todo Add more errors here. */
     345    {
     346        switch (rc)
     347        {
     348            case VERR_ACCESS_DENIED:
     349                hr = setError(VBOX_E_IPRT_ERROR, tr("Reading directory \"%s\" failed: Unable to read / access denied"),
     350                              mData.mName.c_str());
     351                break;
     352
     353            case VERR_PATH_NOT_FOUND:
     354                hr = setError(VBOX_E_IPRT_ERROR, tr("Reading directory \"%s\" failed: Path not found"),
     355                              mData.mName.c_str());
     356                break;
     357
     358            case VERR_NO_MORE_FILES:
    343359                hr = setError(VBOX_E_OBJECT_NOT_FOUND, tr("No more entries for directory \"%s\""),
    344360                              mData.mName.c_str());
    345             }
    346         }
    347     }
    348     catch (int rc2)
    349     {
    350         rc = rc2;
    351     }
    352 
    353     if (RT_FAILURE(rc)) /** @todo Add more errors here. */
    354         hr = setError(VBOX_E_IPRT_ERROR, tr("Error while reading directory \"%s\": %Rrc\n"),
    355                       mData.mName.c_str(), rc);
     361                break;
     362
     363            default:
     364                hr = setError(VBOX_E_IPRT_ERROR, tr("Error while reading directory \"%s\": %Rrc\n"),
     365                              mData.mName.c_str(), rc);
     366                break;
     367        }
     368    }
    356369
    357370    LogFlowFuncLeaveRC(rc);
  • 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