VirtualBox

Changeset 55549 in vbox for trunk/src/VBox/Main/src-client


Ignore:
Timestamp:
Apr 30, 2015 12:28:26 PM (10 years ago)
Author:
vboxsync
Message:

DnD: Update.

Location:
trunk/src/VBox/Main/src-client
Files:
3 edited

Legend:

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

    r55539 r55549  
    261261{
    262262    m_progress.setNull();
    263     HRESULT rc = m_progress.createObject();
    264     if (SUCCEEDED(rc))
    265     {
    266         rc = m_progress->init(static_cast<IGuest *>(pParent),
     263
     264    HRESULT hr = m_progress.createObject();
     265    if (SUCCEEDED(hr))
     266    {
     267        hr = m_progress->init(static_cast<IGuest *>(pParent),
    267268                              Bstr(pParent->tr("Dropping data")).raw(),
    268269                              TRUE /* aCancelable */);
    269270    }
    270     return rc;
     271
     272    return hr;
    271273}
    272274
     
    734736GuestDnDBase::GuestDnDBase(void)
    735737{
     738    mDataBase.mfTransferIsPending = false;
     739
     740    /*
     741     * Initialize public attributes.
     742     */
    736743    m_strFormats = GuestDnDInst()->defaultFormats();
    737744}
  • trunk/src/VBox/Main/src-client/GuestDnDSourceImpl.cpp

    r55539 r55549  
    101101     *       how to do something, so try to negogiate a sensible value here later. */
    102102    mData.mcbBlockSize    = _64K; /** @todo Make this configurable. */
    103     mData.mfDropIsPending = false;
    104103
    105104    LogFlowThisFunc(("\n"));
     
    293292#else /* VBOX_WITH_DRAG_AND_DROP */
    294293
     294    AutoCaller autoCaller(this);
     295    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     296
    295297    /* Input validation. */
    296298    if (RT_UNLIKELY((aFormat.c_str()) == NULL || *(aFormat.c_str()) == '\0'))
    297299        return setError(E_INVALIDARG, tr("No drop format specified"));
    298300
    299     AutoCaller autoCaller(this);
    300     if (FAILED(autoCaller.rc())) return autoCaller.rc();
    301 
    302301    uint32_t uAction = GuestDnD::toHGCMAction(aAction);
    303     /* If there is no usable action, ignore this request. */
    304     if (isDnDIgnoreAction(uAction))
     302    if (isDnDIgnoreAction(uAction)) /* If there is no usable action, ignore this request. */
    305303        return S_OK;
    306304
    307305    /* Note: At the moment we only support one transfer at a time. */
    308     if (ASMAtomicReadBool(&mData.mfDropIsPending))
     306    if (ASMAtomicReadBool(&mDataBase.mfTransferIsPending))
    309307        return setError(E_INVALIDARG, tr("Another drop operation already is in progress"));
    310308
    311     ASMAtomicWriteBool(&mData.mfDropIsPending, true);
     309    ASMAtomicWriteBool(&mDataBase.mfTransferIsPending, true);
    312310
    313311    /* Dito. */
     
    329327        AssertReturn(pTask->isOk(), pTask->getRC());
    330328
    331         RTTHREAD recvThread;
    332         int rc = RTThreadCreate(&recvThread, GuestDnDSource::i_receiveDataThread,
     329        int rc = RTThreadCreate(NULL, GuestDnDSource::i_receiveDataThread,
    333330                                (void *)pTask, 0, RTTHREADTYPE_MAIN_WORKER, 0, "dndSrcRcvData");
    334331        if (RT_SUCCESS(rc))
     
    347344    }
    348345
    349     /* Note: mData.mfDropIsPending will be set to false again by i_receiveDataThread. */
     346    /* Note: mDataBase.mfTransferIsPending will be set to false again by i_receiveDataThread. */
    350347
    351348    LogFlowFunc(("Returning hr=%Rhrc\n", hr));
     
    365362    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    366363
    367     if (ASMAtomicReadBool(&mData.mfDropIsPending))
    368         return setError(E_INVALIDARG, tr("Current drop operation still running"));
     364    /* Don't allow receiving the actual data until our transfer
     365     * actually is complete. */
     366    if (ASMAtomicReadBool(&mDataBase.mfTransferIsPending))
     367        return setError(E_INVALIDARG, tr("Current drop operation still in progress"));
    369368
    370369    PRECVDATACTX pCtx = &mData.mRecvCtx;
     
    507506        {
    508507            /*
    509              * BUG: Protocol v1 does *not* send root directory names in URI format,
    510              *      however, if this is a root URI directory (which came with the initial
    511              *      GUEST_DND_GH_SND_DATA message(s)) the total data announced was for
    512              *      root directory names which came in URI format, as an URI list.
     508             * Protocols v1/v2 do *not* send root element names (files/directories)
     509             * in URI format. The initial GUEST_DND_GH_SND_DATA message(s) however
     510             * did take those element names into account, but *with* URI decoration
     511             * when it comes to communicating the total bytes being sent.
    513512             *
    514              *      So construct an URI path locally to keep the accounting right.
     513             * So translate the path into a valid URI path and add the resulting
     514             * length (+ "\r\n" and termination) to the total bytes received
     515             * to keep the accounting right.
    515516             */
    516517            char *pszPathURI = RTUriCreate("file" /* pszScheme */, "/" /* pszAuthority */,
     
    593594        {
    594595            /** @todo Unescpae path before printing. */
    595             LogRel2(("DnD: Transferring file to host: %s\n", pCtx->mURI.objURI.GetDestPath().c_str()));
     596            LogRel2(("DnD: Transferring guest file to host: %s\n", pCtx->mURI.objURI.GetDestPath().c_str()));
    596597
    597598            /* Note: Protocol v1 does not send any file sizes, so always 0. */
     
    604605        else
    605606        {
    606             LogRel2(("DnD: Error opening/creating guest file \"%s\" on host, rc=%Rrc\n",
     607            LogRel2(("DnD: Error opening/creating guest file '%s' on host, rc=%Rrc\n",
    607608                     pCtx->mURI.objURI.GetDestPath().c_str(), rc));
    608609            break;
     610        }
     611
     612        if (mDataBase.mProtocolVersion <= 2)
     613        {
     614            /*
     615             * Protocols v1/v2 do *not* send root element names (files/directories)
     616             * in URI format. The initial GUEST_DND_GH_SND_DATA message(s) however
     617             * did take those element names into account, but *with* URI decoration
     618             * when it comes to communicating the total bytes being sent.
     619             *
     620             * So translate the path into a valid URI path and add the resulting
     621             * length (+ "\r\n" and termination) to the total bytes received
     622             * to keep the accounting right.
     623             */
     624            char *pszPathURI = RTUriCreate("file" /* pszScheme */, "/" /* pszAuthority */,
     625                                           pszPath /* pszPath */,
     626                                           NULL /* pszQuery */, NULL /* pszFragment */);
     627            if (pszPathURI)
     628            {
     629                bool fHasPath = RTPathHasPath(pszPath); /* Use original data received. */
     630                if (!fHasPath) /* Root path? */
     631                {
     632                    cbPath  = strlen(pszPathURI);
     633                    cbPath += 3;                  /* Include "\r" + "\n" + termination -- see above. */
     634
     635                    rc = i_updateProcess(pCtx, cbPath);
     636                }
     637
     638                LogFlowFunc(("URI pszPathURI=%s, fHasPath=%RTbool, cbPath=%RU32\n", pszPathURI, fHasPath, cbPath));
     639                RTStrFree(pszPathURI);
     640            }
     641            else
     642            {
     643                rc = VERR_NO_MEMORY;
     644                break;
     645            }
    609646        }
    610647
     
    667704        }
    668705        else
    669             LogRel(("DnD: Error: Can't write guest file to host to \"%s\": %Rrc\n", pCtx->mURI.objURI.GetDestPath().c_str(), rc));
     706            LogRel(("DnD: Error writing guest file to host to \"%s\": %Rrc\n", pCtx->mURI.objURI.GetDestPath().c_str(), rc));
    670707
    671708    } while (0);
     
    749786        rc = VERR_COM_INVALID_OBJECT_STATE;
    750787
     788    ASMAtomicWriteBool(&pSource->mDataBase.mfTransferIsPending, false);
     789
    751790    LogFlowFunc(("pSource=%p returning rc=%Rrc\n", (GuestDnDSource *)pSource, rc));
    752791
    753792    if (pTask)
    754793        delete pTask;
    755 
    756     ASMAtomicWriteBool(&pSource->mData.mfDropIsPending, false);
    757 
    758794    return rc;
    759795}
     
    939975
    940976    int rc = VINF_SUCCESS;
    941     bool fNotify = false;
    942977
    943978    switch (uMsg)
     
    9741009
    9751010    if (RT_FAILURE(rc))
    976         fNotify = true;
    977 
    978     if (fNotify)
    9791011    {
    9801012        int rc2 = pCtx->mCallback.Notify(rc);
  • trunk/src/VBox/Main/src-client/GuestDnDTargetImpl.cpp

    r55539 r55549  
    496496    else
    497497        rc = VERR_COM_INVALID_OBJECT_STATE;
     498
     499    ASMAtomicWriteBool(&pTarget->mDataBase.mfTransferIsPending, false);
    498500
    499501    LogFlowFunc(("pTarget=%p returning rc=%Rrc\n", (GuestDnDTarget *)pTarget, rc));
     
    521523#else /* VBOX_WITH_DRAG_AND_DROP */
    522524
    523     /** @todo Add input validation. */
    524     /** @todo Check if another sendData() call currently is being processed. */
    525 
    526525    AutoCaller autoCaller(this);
    527526    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    528527
    529     /* Note: At the moment we only support one response at a time. */
     528    /* Input validation. */
     529    if (RT_UNLIKELY((aFormat.c_str()) == NULL || *(aFormat.c_str()) == '\0'))
     530        return setError(E_INVALIDARG, tr("No data format specified"));
     531    if (RT_UNLIKELY(!aData.size()))
     532        return setError(E_INVALIDARG, tr("No data to send specified"));
     533
     534    /* Note: At the moment we only support one transfer at a time. */
     535    if (ASMAtomicReadBool(&mDataBase.mfTransferIsPending))
     536        return setError(E_INVALIDARG, tr("Another send operation already is in progress"));
     537
     538    ASMAtomicWriteBool(&mDataBase.mfTransferIsPending, true);
     539
     540    /* Dito. */
    530541    GuestDnDResponse *pResp = GuestDnDInst()->response();
    531542    AssertPtr(pResp);
     
    549560        AssertReturn(pTask->isOk(), pTask->getRC());
    550561
    551         RTTHREAD sendThread;
    552         int rc = RTThreadCreate(&sendThread, GuestDnDTarget::i_sendDataThread,
     562        int rc = RTThreadCreate(NULL, GuestDnDTarget::i_sendDataThread,
    553563                                (void *)pTask, 0, RTTHREADTYPE_MAIN_WORKER, 0, "dndTgtSndData");
    554564        if (RT_SUCCESS(rc))
     
    569579        hr = setError(E_OUTOFMEMORY);
    570580    }
     581
     582    /* Note: mDataBase.mfTransferIsPending will be set to false again by i_sendDataThread. */
    571583
    572584    LogFlowFunc(("Returning hr=%Rhrc\n", hr));
     
    608620
    609621    ASMAtomicWriteBool(&pCtx->mIsActive, true);
     622
     623    /* Clear all remaining outgoing messages. */
     624    mDataBase.mListOutgoing.clear();
    610625
    611626    do
     
    694709        rc = aFile.OpenEx(strPathSrc, DnDURIObject::File, DnDURIObject::Source,
    695710                          RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE, 0 /* fFlags */);
     711        if (RT_FAILURE(rc))
     712            LogRel2(("DnD: Error opening host file \"%s\", rc=%Rrc\n", strPathSrc.c_str(), rc));
    696713    }
    697714
     
    718735
    719736                LogFlowFunc(("Sending file header ...\n"));
     737                LogRel2(("DnD: Transferring host file to guest: %s (%RU64 bytes, mode 0x%x)\n",
     738                         strPathSrc.c_str(), aFile.GetSize(), aFile.GetMode()));
    720739            }
    721740            else
     
    800819        if (aFile.IsComplete()) /* Done reading? */
    801820        {
     821            LogRel2(("DnD: File transfer to guest complete: %s\n", aFile.GetSourcePath().c_str()));
    802822            LogFlowFunc(("File \"%s\" complete\n", aFile.GetSourcePath().c_str()));
    803823            rc = VINF_EOF;
     
    821841
    822842    int rc = VINF_SUCCESS;
    823     bool fNotify = false;
    824843
    825844    switch (uMsg)
     
    849868
    850869                if (RT_FAILURE(rc))
    851                 {
    852                     if (rc == VERR_NO_DATA) /* All URI objects processed? */
    853                     {
    854                         /* Unregister this callback. */
    855                         AssertPtr(pCtx->mpResp);
    856                         int rc2 = pCtx->mpResp->setCallback(uMsg, NULL /* PFNGUESTDNDCALLBACK */);
    857                         if (RT_FAILURE(rc2))
    858                             LogFlowFunc(("Error: Unable to unregister callback for message %RU32, rc=%Rrc\n", uMsg, rc2));
    859                     }
    860 
    861870                    delete pMsg;
    862                 }
    863871            }
    864872            catch(std::bad_alloc & /*e*/)
     
    866874                rc = VERR_NO_MEMORY;
    867875            }
     876            break;
     877        }
     878        case DragAndDropSvc::GUEST_DND_GH_EVT_ERROR:
     879        {
     880            DragAndDropSvc::PVBOXDNDCBEVTERRORDATA pCBData = reinterpret_cast<DragAndDropSvc::PVBOXDNDCBEVTERRORDATA>(pvParms);
     881            AssertPtr(pCBData);
     882            AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBEVTERRORDATA) == cbParms, VERR_INVALID_PARAMETER);
     883            AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_EVT_ERROR == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
     884
     885            pCtx->mpResp->reset();
     886            rc = pCtx->mpResp->setProgress(100, DragAndDropSvc::DND_PROGRESS_ERROR, pCBData->rc);
     887            if (RT_SUCCESS(rc))
     888                rc = pCBData->rc;
    868889            break;
    869890        }
     
    917938    }
    918939
    919     if (fNotify)
    920     {
    921         int rc2 = pCtx->mCallback.Notify(rc);
     940    if (RT_FAILURE(rc))
     941    {
     942        switch (rc)
     943        {
     944            case VERR_NO_DATA:
     945                LogRel2(("DnD: Transfer complete\n"));
     946                break;
     947
     948            case VERR_CANCELLED:
     949                LogRel2(("DnD: Transfer canceled\n"));
     950                break;
     951
     952            default:
     953                LogRel(("DnD: Error %Rrc occurred, aborting transfer\n", rc));
     954                break;
     955        }
     956
     957        /* Unregister this callback. */
     958        AssertPtr(pCtx->mpResp);
     959        int rc2 = pCtx->mpResp->setCallback(uMsg, NULL /* PFNGUESTDNDCALLBACK */);
     960        AssertRC(rc2);
     961
     962        /* Notify waiters. */
     963        rc2 = pCtx->mCallback.Notify(rc);
    922964        AssertRC(rc2);
    923965    }
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