VirtualBox

Ignore:
Timestamp:
Jul 30, 2020 6:55:32 AM (4 years ago)
Author:
vboxsync
Message:

DnD/Main: More fixes and cleanups.

File:
1 edited

Legend:

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

    r85451 r85537  
    6262    int getRC(void) const { return mRC; }
    6363    bool isOk(void) const { return RT_SUCCESS(mRC); }
    64     const ComObjPtr<GuestDnDTarget> &getTarget(void) const { return mTarget; }
    6564
    6665protected:
     
    8786    void handler()
    8887    {
    89         GuestDnDTarget::i_sendDataThreadTask(this);
    90     }
    91 
    92     virtual ~GuestDnDSendDataTask(void)
    93     {
    94         if (mpCtx)
    95         {
    96             delete mpCtx;
    97             mpCtx = NULL;
    98         }
    99     }
    100 
    101 
    102     GuestDnDSendCtx *getCtx(void) { return mpCtx; }
     88        const ComObjPtr<GuestDnDTarget> pThis(mTarget);
     89        Assert(!pThis.isNull());
     90
     91        AutoCaller autoCaller(pThis);
     92        if (FAILED(autoCaller.rc()))
     93            return;
     94
     95        int vrc = pThis->i_sendData(mpCtx, RT_INDEFINITE_WAIT /* msTimeout */);
     96        if (RT_FAILURE(vrc)) /* In case we missed some error handling within i_sendData(). */
     97        {
     98            if (vrc != VERR_CANCELLED)
     99                LogRel(("DnD: Sending data to guest failed with %Rrc\n", vrc));
     100
     101            /* Make sure to fire a cancel request to the guest side in case something went wrong. */
     102            pThis->sendCancel();
     103        }
     104    }
     105
     106    virtual ~GuestDnDSendDataTask(void) { }
    103107
    104108protected:
     
    295299
    296300    LogRel2(("DnD: Offered formats to guest:\n"));
    297     RTCList<RTCString> lstFormats = strFormats.split("\r\n");
     301    RTCList<RTCString> lstFormats = strFormats.split(DND_PATH_SEPARATOR);
    298302    for (size_t i = 0; i < lstFormats.size(); i++)
    299303        LogRel2(("DnD: \t%s\n", lstFormats[i].c_str()));
     
    307311
    308312    /* Adjust the coordinates in a multi-monitor setup. */
    309     int rc = GUESTDNDINST()->adjustScreenCoordinates(aScreenId, &aX, &aY);
     313    int rc = GuestDnDInst()->adjustScreenCoordinates(aScreenId, &aX, &aY);
    310314    if (RT_SUCCESS(rc))
    311315    {
     
    322326        Msg.setNextUInt32(cbFormats);
    323327
    324         rc = GUESTDNDINST()->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms());
     328        rc = GuestDnDInst()->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms());
    325329        if (RT_SUCCESS(rc))
    326330        {
    327             GuestDnDResponse *pResp = GUESTDNDINST()->response();
     331            GuestDnDResponse *pResp = GuestDnDInst()->response();
    328332            if (pResp && RT_SUCCESS(pResp->waitForGuestResponse()))
    329333                resAction = GuestDnD::toMainAction(pResp->getActionDefault());
     
    385389    HRESULT hr = S_OK;
    386390
    387     int rc = GUESTDNDINST()->adjustScreenCoordinates(aScreenId, &aX, &aY);
     391    int rc = GuestDnDInst()->adjustScreenCoordinates(aScreenId, &aX, &aY);
    388392    if (RT_SUCCESS(rc))
    389393    {
     
    400404        Msg.setNextUInt32(cbFormats);
    401405
    402         rc = GUESTDNDINST()->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms());
     406        rc = GuestDnDInst()->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms());
    403407        if (RT_SUCCESS(rc))
    404408        {
    405             GuestDnDResponse *pResp = GUESTDNDINST()->response();
     409            GuestDnDResponse *pResp = GuestDnDInst()->response();
    406410            if (pResp && RT_SUCCESS(pResp->waitForGuestResponse()))
    407411                resAction = GuestDnD::toMainAction(pResp->getActionDefault());
     
    440444        Msg.setNextUInt32(0); /** @todo ContextID not used yet. */
    441445
    442     int rc = GUESTDNDINST()->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms());
     446    int rc = GuestDnDInst()->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms());
    443447    if (RT_SUCCESS(rc))
    444448    {
    445         GuestDnDResponse *pResp = GUESTDNDINST()->response();
     449        GuestDnDResponse *pResp = GuestDnDInst()->response();
    446450        if (pResp)
    447451            pResp->waitForGuestResponse();
     
    479483
    480484    /* Default action is ignoring. */
    481     DnDAction_T resAction    = DnDAction_Ignore;
     485    DnDAction_T resAct = DnDAction_Ignore;
     486    Utf8Str     resFmt;
    482487
    483488    /* Check & convert the drag & drop actions to HGCM codes. */
     
    507512
    508513    /* Adjust the coordinates in a multi-monitor setup. */
    509     HRESULT hr = GUESTDNDINST()->adjustScreenCoordinates(aScreenId, &aX, &aY);
     514    HRESULT hr = GuestDnDInst()->adjustScreenCoordinates(aScreenId, &aX, &aY);
    510515    if (SUCCEEDED(hr))
    511516    {
     
    522527        Msg.setNextUInt32(cbFormats);
    523528
    524         int vrc = GUESTDNDINST()->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms());
     529        int vrc = GuestDnDInst()->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms());
    525530        if (RT_SUCCESS(vrc))
    526531        {
    527             GuestDnDResponse *pResp = GUESTDNDINST()->response();
    528             AssertPtr(pResp);
    529 
    530             vrc = pResp->waitForGuestResponse();
    531             if (RT_SUCCESS(vrc))
     532            GuestDnDResponse *pResp = GuestDnDInst()->response();
     533            if (pResp && RT_SUCCESS(pResp->waitForGuestResponse()))
    532534            {
    533                 resAction = GuestDnD::toMainAction(pResp->getActionDefault());
     535                resAct = GuestDnD::toMainAction(pResp->getActionDefault());
    534536
    535537                GuestDnDMIMEList lstFormats = pResp->formats();
    536538                if (lstFormats.size() == 1) /* Exactly one format to use specified? */
    537539                {
    538                     aFormat = lstFormats.at(0);
    539                     LogFlowFunc(("resFormat=%s, resAction=%RU32\n", aFormat.c_str(), pResp->getActionDefault()));
     540                    resFmt = lstFormats.at(0);
    540541                }
    541542                else
     
    552553        hr = setError(hr, tr("Retrieving drop coordinates failed"));
    553554
     555    LogFlowFunc(("resFmt=%s, resAct=%RU32, vrc=%Rhrc\n", resFmt.c_str(), resAct, hr));
     556
    554557    if (SUCCEEDED(hr))
    555558    {
     559        aFormat = resFmt;
    556560        if (aResultAction)
    557             *aResultAction = resAction;
    558     }
    559 
    560     LogFlowFunc(("Returning hr=%Rhrc\n", hr));
     561            *aResultAction = resAct;
     562    }
     563
    561564    return hr;
    562565#endif /* VBOX_WITH_DRAG_AND_DROP */
    563 }
    564 
    565 /**
    566  * Thread handler function for sending data to the guest.
    567  *
    568  * @param   pTask               Thread task this handler is associated with.
    569  */
    570 /* static */
    571 void GuestDnDTarget::i_sendDataThreadTask(GuestDnDSendDataTask *pTask)
    572 {
    573     LogFlowFunc(("pTask=%p\n", pTask));
    574     AssertPtrReturnVoid(pTask);
    575 
    576     const ComObjPtr<GuestDnDTarget> pThis(pTask->getTarget());
    577     Assert(!pThis.isNull());
    578 
    579     AutoCaller autoCaller(pThis);
    580     if (FAILED(autoCaller.rc()))
    581         return;
    582 
    583     int vrc = pThis->i_sendData(pTask->getCtx(), RT_INDEFINITE_WAIT /* msTimeout */);
    584     if (RT_FAILURE(vrc)) /* In case we missed some error handling within i_sendData(). */
    585     {
    586         AssertFailed();
    587         LogRel(("DnD: Sending data to guest failed with %Rrc\n", vrc));
    588     }
    589 
    590     AutoWriteLock alock(pThis COMMA_LOCKVAL_SRC_POS);
    591 
    592     Assert(pThis->m_DataBase.cTransfersPending);
    593     if (pThis->m_DataBase.cTransfersPending)
    594         pThis->m_DataBase.cTransfersPending--;
    595 
    596     LogFlowFunc(("pTarget=%p, vrc=%Rrc (ignored)\n", (GuestDnDTarget *)pThis, vrc));
    597566}
    598567
     
    626595    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    627596
     597    /* Check if this object still is in a pending state and bail out if so. */
     598    if (m_fIsPending)
     599        return setError(E_FAIL, tr("Current drop operation to guest still in progress"));
     600
     601    /* Reset our internal state. */
     602    i_reset();
     603
    628604    /* At the moment we only support one transfer at a time. */
    629     if (m_DataBase.cTransfersPending)
    630         return setError(E_INVALIDARG, tr("Another drop operation already is in progress"));
    631 
    632     /* Ditto. */
    633     GuestDnDResponse *pResp = GUESTDNDINST()->response();
     605    if (GuestDnDInst()->getTargetCount())
     606        return setError(E_INVALIDARG, tr("Another drag and drop operation to the guest already is in progress"));
     607
     608    /* Reset progress object. */
     609    GuestDnDResponse *pResp = GuestDnDInst()->response();
    634610    AssertPtr(pResp);
    635 
    636611    HRESULT hr = pResp->resetProgress(m_pGuest);
    637612    if (FAILED(hr))
    638613        return hr;
    639614
    640     GuestDnDSendDataTask *pTask    = NULL;
    641     GuestDnDSendCtx      *pSendCtx = NULL;
     615    GuestDnDSendDataTask *pTask = NULL;
    642616
    643617    try
    644618    {
    645         /* pSendCtx is passed into SendDataTask where one is deleted in destructor. */
    646         pSendCtx = new GuestDnDSendCtx();
    647         pSendCtx->pTarget   = this;
    648         pSendCtx->pResp     = pResp;
    649         pSendCtx->uScreenID = aScreenId;
    650 
    651         pSendCtx->Meta.strFmt = aFormat;
    652         pSendCtx->Meta.add(aData);
    653 
    654         /* pTask is responsible for deletion of pSendCtx after creating */
    655         pTask = new GuestDnDSendDataTask(this, pSendCtx);
     619        mData.mSendCtx.reset();
     620
     621        mData.mSendCtx.pTarget   = this;
     622        mData.mSendCtx.pResp     = pResp;
     623        mData.mSendCtx.uScreenID = aScreenId;
     624
     625        mData.mSendCtx.Meta.strFmt = aFormat;
     626        mData.mSendCtx.Meta.add(aData);
     627
     628        pTask = new GuestDnDSendDataTask(this, &mData.mSendCtx);
    656629        if (!pTask->isOk())
    657630        {
     
    660633            throw hr = E_FAIL;
    661634        }
    662 
    663         /* Drop write lock before creating thread. */
    664         alock.release();
    665635
    666636        /* This function delete pTask in case of exceptions,
     
    681651    if (SUCCEEDED(hr))
    682652    {
    683         /* Re-acquire write lock. */
    684         alock.acquire();
    685 
    686         m_DataBase.cTransfersPending++;
    687 
     653        /* Register ourselves at the DnD manager. */
     654        GuestDnDInst()->registerTarget(this);
     655
     656        /* Return progress to caller. */
    688657        hr = pResp->queryProgressTo(aProgress.asOutParam());
    689658        ComAssertComRC(hr);
    690659    }
    691660    else
    692         hr = setError(hr, tr("Starting thread for GuestDnDTarget::i_sendDataThread (%Rhrc)"), hr);
     661        hr = setError(hr, tr("Starting thread for GuestDnDTarget failed (%Rhrc)"), hr);
    693662
    694663    LogFlowFunc(("Returning hr=%Rhrc\n", hr));
     
    767736
    768737    return strError;
     738}
     739
     740void GuestDnDTarget::i_reset(void)
     741{
     742    LogFlowThisFunc(("\n"));
     743
     744    mData.mSendCtx.reset();
     745
     746    m_fIsPending = false;
     747
     748    /* Unregister ourselves from the DnD manager. */
     749    GuestDnDInst()->unregisterTarget(this);
    769750}
    770751
     
    780761    AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
    781762
    782     /* Is this context already in sending state? */
    783     if (ASMAtomicReadBool(&pCtx->fIsActive))
    784         return VERR_WRONG_ORDER;
    785     ASMAtomicWriteBool(&pCtx->fIsActive, true);
     763    /* Don't allow receiving the actual data until our current transfer is complete. */
     764    if (m_fIsPending)
     765        return setError(E_FAIL, tr("Current drop operation to guest still in progress"));
    786766
    787767    /* Clear all remaining outgoing messages. */
     
    810790    }
    811791
    812     ASMAtomicWriteBool(&pCtx->fIsActive, false);
     792    if (RT_FAILURE(rc))
     793        LogRel(("DnD: Sending data to guest failed with %Rrc\n", rc));
     794
     795    /* Reset state. */
     796    i_reset();
    813797
    814798    LogFlowFuncLeaveRC(rc);
     
    839823
    840824#ifdef DEBUG
    841     RTCList<RTCString> lstFilesURI = RTCString((char *)pvData, cbData).split("\r\n");
     825    RTCList<RTCString> lstFilesURI = RTCString((char *)pvData, cbData).split(DND_PATH_SEPARATOR);
    842826    LogFlowFunc(("lstFilesURI=%zu\n", lstFilesURI.size()));
    843827    for (size_t i = 0; i < lstFilesURI.size(); i++)
     
    871855        }
    872856
    873         rc = GUESTDNDINST()->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms());
     857        rc = GuestDnDInst()->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms());
    874858        if (RT_FAILURE(rc))
    875859            break;
     
    907891
    908892    LogRel2(("DnD: Sending meta data header to guest (%RU64 bytes total data, %RU32 bytes meta data, %RU64 objects)\n",
    909              pCtx->getTotal(), pCtx->Meta.cbData, pCtx->Transfer.cObjToProcess));
     893             pCtx->getTotalAnnounced(), pCtx->Meta.cbData, pCtx->Transfer.cObjToProcess));
    910894
    911895    Msg.setNextUInt32(0);                                                /** @todo uContext; not used yet. */
    912896    Msg.setNextUInt32(0);                                                /** @todo uFlags; not used yet. */
    913897    Msg.setNextUInt32(pCtx->uScreenID);                                  /* uScreen */
    914     Msg.setNextUInt64(pCtx->getTotal());                                 /* cbTotal */
     898    Msg.setNextUInt64(pCtx->getTotalAnnounced());                        /* cbTotal */
    915899    Msg.setNextUInt32((uint32_t)pCtx->Meta.cbData);                      /* cbMeta*/
    916900    Msg.setNextPointer(unconst(pCtx->Meta.strFmt.c_str()), (uint32_t)pCtx->Meta.strFmt.length() + 1); /* pvMetaFmt */
     
    922906    Msg.setNextUInt32(0);                                                /** @todo cbChecksum; not used yet. */
    923907
    924     int rc = GUESTDNDINST()->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms());
     908    int rc = GuestDnDInst()->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms());
    925909
    926910    LogFlowFuncLeaveRC(rc);
     
    13981382         * Update internal state to reflect everything we need to work with it.
    13991383         */
    1400         pCtx->cbExtra               = DnDTransferListObjTotalBytes(&pCtx->Transfer.List);
     1384        pCtx->cbExtra                = DnDTransferListObjTotalBytes(&pCtx->Transfer.List);
    14011385        /* cbExtra can be 0, if all files are of 0 bytes size. */
    14021386        pCtx->Transfer.cObjToProcess = DnDTransferListObjCount(&pCtx->Transfer.List);
     
    14311415            pCtx->Meta.cbData      = cbData;
    14321416            pCtx->Meta.cbAllocated = cbData;
     1417            pCtx->Meta.cbAnnounced = cbData;
    14331418        }
    14341419
     
    15301515    AssertRCReturn(rc, rc);
    15311516
    1532     if (pCtx->isComplete())
    1533     {
    1534         Assert(pCtx->Transfer.isComplete());
     1517    PDNDTRANSFEROBJECT pObj = DnDTransferListObjGetFirst(pList);
     1518    if (!pObj) /* Transfer complete? */
    15351519        return VINF_EOF;
    1536     }
    1537 
    1538     PDNDTRANSFEROBJECT pObj = DnDTransferListObjGetFirst(pList);
    1539     AssertPtrReturn(pObj, VERR_WRONG_ORDER);
    15401520
    15411521    switch (DnDTransferObjectGetType(pObj))
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