VirtualBox

Ignore:
Timestamp:
Oct 13, 2015 11:49:33 AM (9 years ago)
Author:
vboxsync
Message:

DnD: Updates.

  • Introduced protocol changelog in DragAndDropSvc.h.
  • Implemented protocol v3 with HOST_DND_HG_SND_DATA_HDR message for doing proper object accounting, among other parameters like checksumming and compression flags.
  • Encapsulated a lot of functionality in class hierarchies.
  • Renamed a lot of functions to make the usage more clear.
  • Various other bugfixes.
File:
1 edited

Legend:

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

    r57505 r58212  
    262262
    263263    /* Determine guest DnD protocol to use. */
    264     GuestDnDBase::getProtocolVersion(&mDataBase.mProtocolVersion);
     264    GuestDnDBase::getProtocolVersion(&mDataBase.m_uProtocolVersion);
    265265
    266266    /* Default action is ignoring. */
     
    302302    {
    303303        GuestDnDMsg Msg;
    304         Msg.setType(DragAndDropSvc::HOST_DND_HG_EVT_ENTER);
     304        Msg.setType(HOST_DND_HG_EVT_ENTER);
    305305        Msg.setNextUInt32(aScreenId);
    306306        Msg.setNextUInt32(aX);
     
    376376    {
    377377        GuestDnDMsg Msg;
    378         Msg.setType(DragAndDropSvc::HOST_DND_HG_EVT_MOVE);
     378        Msg.setType(HOST_DND_HG_EVT_MOVE);
    379379        Msg.setNextUInt32(aScreenId);
    380380        Msg.setNextUInt32(aX);
     
    418418
    419419    HRESULT hr = S_OK;
    420     int rc = GuestDnDInst()->hostCall(DragAndDropSvc::HOST_DND_HG_EVT_LEAVE,
     420    int rc = GuestDnDInst()->hostCall(HOST_DND_HG_EVT_LEAVE,
    421421                                      0 /* cParms */, NULL /* paParms */);
    422422    if (RT_SUCCESS(rc))
     
    488488    {
    489489        GuestDnDMsg Msg;
    490         Msg.setType(DragAndDropSvc::HOST_DND_HG_EVT_DROPPED);
     490        Msg.setType(HOST_DND_HG_EVT_DROPPED);
    491491        Msg.setNextUInt32(aScreenId);
    492492        Msg.setNextUInt32(aX);
     
    545545    AssertPtrReturn(pTask, VERR_INVALID_POINTER);
    546546
    547     const ComObjPtr<GuestDnDTarget> pTarget(pTask->getTarget());
    548     Assert(!pTarget.isNull());
    549 
    550     int rc;
    551 
    552     AutoCaller autoCaller(pTarget);
    553     if (SUCCEEDED(autoCaller.rc()))
    554     {
    555         rc = pTarget->i_sendData(pTask->getCtx(), RT_INDEFINITE_WAIT /* msTimeout */);
    556         /* Nothing to do here anymore. */
    557     }
    558     else
    559         rc = VERR_COM_INVALID_OBJECT_STATE;
    560 
    561     ASMAtomicWriteBool(&pTarget->mDataBase.mfTransferIsPending, false);
     547    const ComObjPtr<GuestDnDTarget> pThis(pTask->getTarget());
     548    Assert(!pThis.isNull());
     549
     550    AutoCaller autoCaller(pThis);
     551    if (FAILED(autoCaller.rc())) return VERR_COM_INVALID_OBJECT_STATE;
     552
     553    int rc = RTThreadUserSignal(Thread);
     554    AssertRC(rc);
     555
     556    rc = pThis->i_sendData(pTask->getCtx(), RT_INDEFINITE_WAIT /* msTimeout */);
    562557
    563558    if (pTask)
    564559        delete pTask;
    565560
    566     LogFlowFunc(("pTarget=%p returning rc=%Rrc\n", (GuestDnDTarget *)pTarget, rc));
     561    AutoWriteLock alock(pThis COMMA_LOCKVAL_SRC_POS);
     562
     563    Assert(pThis->mDataBase.m_cTransfersPending);
     564    pThis->mDataBase.m_cTransfersPending--;
     565
     566    LogFlowFunc(("pTarget=%p returning rc=%Rrc\n", (GuestDnDTarget *)pThis, rc));
    567567    return rc;
    568568}
     
    594594        return setError(E_INVALIDARG, tr("No data to send specified"));
    595595
    596     /* Note: At the moment we only support one transfer at a time. */
    597     if (ASMAtomicReadBool(&mDataBase.mfTransferIsPending))
    598         return setError(E_INVALIDARG, tr("Another send operation already is in progress"));
    599 
    600     ASMAtomicWriteBool(&mDataBase.mfTransferIsPending, true);
     596    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     597
     598    /* At the moment we only support one transfer at a time. */
     599    if (mDataBase.m_cTransfersPending)
     600        return setError(E_INVALIDARG, tr("Another drop operation already is in progress"));
    601601
    602602    /* Dito. */
     
    617617        pSendCtx->mScreenID     = aScreenId;
    618618        pSendCtx->mFmtReq       = aFormat;
    619         pSendCtx->mData.vecData = aData;
     619
     620        pSendCtx->mData.getMeta().add(aData);
    620621
    621622        SendDataTask *pTask = new SendDataTask(this, pSendCtx);
     
    624625        LogFlowFunc(("Starting thread ...\n"));
    625626
    626         int rc = RTThreadCreate(NULL, GuestDnDTarget::i_sendDataThread,
     627        RTTHREAD threadSnd;
     628        int rc = RTThreadCreate(&threadSnd, GuestDnDTarget::i_sendDataThread,
    627629                                (void *)pTask, 0, RTTHREADTYPE_MAIN_WORKER, 0, "dndTgtSndData");
    628630        if (RT_SUCCESS(rc))
    629631        {
    630             hr = pResp->queryProgressTo(aProgress.asOutParam());
    631             ComAssertComRC(hr);
    632 
    633             /* Note: pTask is now owned by the worker thread. */
     632            rc = RTThreadUserWait(threadSnd, 30 * 1000 /* 30s timeout */);
     633            if (RT_SUCCESS(rc))
     634            {
     635                mDataBase.m_cTransfersPending++;
     636
     637                hr = pResp->queryProgressTo(aProgress.asOutParam());
     638                ComAssertComRC(hr);
     639
     640                /* Note: pTask is now owned by the worker thread. */
     641            }
     642            else
     643                hr = setError(VBOX_E_IPRT_ERROR, tr("Waiting for sending thread failed (%Rrc)"), rc);
    634644        }
    635645        else
    636646            hr = setError(VBOX_E_IPRT_ERROR, tr("Starting thread failed (%Rrc)"), rc);
    637647
    638         if (RT_FAILURE(rc))
     648        if (FAILED(hr))
    639649            delete pSendCtx;
    640650    }
     
    643653        hr = setError(E_OUTOFMEMORY);
    644654    }
    645 
    646     /* Note: mDataBase.mfTransferIsPending will be set to false again by i_sendDataThread. */
    647655
    648656    LogFlowFunc(("Returning hr=%Rhrc\n", hr));
     
    662670
    663671    LogFlowFunc(("Cancelling operation, telling guest ...\n"));
    664     return GuestDnDInst()->hostCall(DragAndDropSvc::HOST_DND_HG_EVT_CANCEL, 0 /* cParms */, NULL /*paParms*/);
     672    return GuestDnDInst()->hostCall(HOST_DND_HG_EVT_CANCEL, 0 /* cParms */, NULL /*paParms*/);
    665673}
    666674
     
    746754
    747755    /* Clear all remaining outgoing messages. */
    748     mDataBase.mListOutgoing.clear();
     756    mDataBase.m_lstMsgOut.clear();
    749757
    750758    /**
     
    775783}
    776784
     785int GuestDnDTarget::i_sendDataBody(PSENDDATACTX pCtx, GuestDnDData *pData)
     786{
     787    AssertPtrReturn(pCtx,  VERR_INVALID_POINTER);
     788    AssertPtrReturn(pData, VERR_INVALID_POINTER);
     789
     790    /** @todo Add support for multiple HOST_DND_HG_SND_DATA messages in case of more than 64K data! */
     791    if (pData->getMeta().getSize() > _64K)
     792        return VERR_NOT_IMPLEMENTED;
     793
     794    GuestDnDMsg Msg;
     795
     796    LogFlowFunc(("cbFmt=%RU32, cbMeta=%RU32, cbChksum=%RU32\n",
     797                 pData->getFmtSize(), pData->getMeta().getSize(), pData->getChkSumSize()));
     798
     799    Msg.setType(HOST_DND_HG_SND_DATA);
     800    if (mDataBase.m_uProtocolVersion < 3)
     801    {
     802        Msg.setNextUInt32(pCtx->mScreenID);                                                /* uScreenId */
     803        Msg.setNextPointer(pData->getFmtMutable(), pData->getFmtSize());                   /* pvFormat */
     804        Msg.setNextUInt32(pData->getFmtSize());                                            /* cbFormat */
     805        Msg.setNextPointer(pData->getMeta().getDataMutable(), pData->getMeta().getSize()); /* pvData */
     806        /* Note1: Fill in the total data to send.
     807         * Note2: Only supports uint32_t. */
     808        Msg.setNextUInt32((uint32_t)pData->getTotal());                                    /* cbData */
     809    }
     810    else
     811    {
     812        Msg.setNextUInt32(0);                                                              /** @todo uContext; not used yet. */
     813        Msg.setNextPointer(pData->getMeta().getDataMutable(), pData->getMeta().getSize()); /* pvData */
     814        Msg.setNextUInt32(pData->getMeta().getSize());                                     /* cbData */
     815        Msg.setNextPointer(pData->getChkSumMutable(), pData->getChkSumSize());             /** @todo pvChecksum; not used yet. */
     816        Msg.setNextUInt32(pData->getChkSumSize());                                         /** @todo cbChecksum; not used yet. */
     817    }
     818
     819    int rc = GuestDnDInst()->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms());
     820    if (RT_SUCCESS(rc))
     821        rc = updateProgress(pData, pCtx->mpResp, pData->getMeta().getSize());
     822
     823    LogFlowFuncLeaveRC(rc);
     824    return rc;
     825}
     826
     827int GuestDnDTarget::i_sendDataHeader(PSENDDATACTX pCtx, GuestDnDData *pData, GuestDnDURIData *pURIData /* = NULL */)
     828{
     829    AssertPtrReturn(pCtx,  VERR_INVALID_POINTER);
     830    AssertPtrReturn(pData, VERR_INVALID_POINTER);
     831    /* pURIData is optional. */
     832
     833    GuestDnDMsg Msg;
     834
     835    Msg.setType(HOST_DND_HG_SND_DATA_HDR);
     836
     837    Msg.setNextUInt32(0);                                                /** @todo uContext; not used yet. */
     838    Msg.setNextUInt32(0);                                                /** @todo uFlags; not used yet. */
     839    Msg.setNextUInt32(pCtx->mScreenID);                                  /* uScreen */
     840    Msg.setNextUInt64(pData->getTotal());                                /* cbTotal */
     841    Msg.setNextUInt32(pData->getMeta().getSize());                       /* cbMeta*/
     842    Msg.setNextPointer(pData->getFmtMutable(), pData->getFmtSize());     /* pvMetaFmt */
     843    Msg.setNextUInt32(pData->getFmtSize());                              /* cbMetaFmt */
     844    Msg.setNextUInt64(pURIData ? pURIData->getObjToProcess() : 0);       /* cObjects */
     845    Msg.setNextUInt32(0);                                                /** @todo enmCompression; not used yet. */
     846    Msg.setNextUInt32(0);                                                /** @todo enmChecksumType; not used yet. */
     847    Msg.setNextPointer(NULL, 0);                                         /** @todo pvChecksum; not used yet. */
     848    Msg.setNextUInt32(0);                                                /** @todo cbChecksum; not used yet. */
     849
     850    int rc = GuestDnDInst()->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms());
     851
     852    LogFlowFuncLeaveRC(rc);
     853    return rc;
     854}
     855
    777856int GuestDnDTarget::i_sendDirectory(PSENDDATACTX pCtx, GuestDnDURIObjCtx *pObjCtx, GuestDnDMsg *pMsg)
    778857{
     
    790869        return VERR_BUFFER_OVERFLOW;
    791870
    792     LogFlowFunc(("Sending directory \"%s\" using protocol v%RU32 ...\n", strPath.c_str(), mDataBase.mProtocolVersion));
    793 
    794     pMsg->setType(DragAndDropSvc::HOST_DND_HG_SND_DIR);
     871    LogRel2(("DnD: Transferring host directory to guest: %s\n", strPath.c_str()));
     872
     873    pMsg->setType(HOST_DND_HG_SND_DIR);
    795874    pMsg->setNextString(strPath.c_str());                  /* path */
    796     pMsg->setNextUInt32((uint32_t)(strPath.length() + 1)); /* path length - note: Maximum is RTPATH_MAX on guest side. */
     875    pMsg->setNextUInt32((uint32_t)(strPath.length() + 1)); /* path length (maximum is RTPATH_MAX on guest side). */
    797876    pMsg->setNextUInt32(pObj->GetMode());                  /* mode */
    798877
     
    816895
    817896    LogFlowFunc(("Sending file with %RU32 bytes buffer, using protocol v%RU32 ...\n",
    818                   mData.mcbBlockSize, mDataBase.mProtocolVersion));
     897                  mData.mcbBlockSize, mDataBase.m_uProtocolVersion));
    819898    LogFlowFunc(("strPathSrc=%s, fIsOpen=%RTbool, cbSize=%RU64\n", strPathSrc.c_str(), pObj->IsOpen(), pObj->GetSize()));
    820899
     
    831910    if (RT_SUCCESS(rc))
    832911    {
    833         if (mDataBase.mProtocolVersion >= 2)
     912        if (mDataBase.m_uProtocolVersion >= 2)
    834913        {
    835914            if (!pObjCtx->fHeaderSent)
     
    840919                 * The just registered callback will be called by the guest afterwards.
    841920                 */
    842                 pMsg->setType(DragAndDropSvc::HOST_DND_HG_SND_FILE_HDR);
     921                pMsg->setType(HOST_DND_HG_SND_FILE_HDR);
    843922                pMsg->setNextUInt32(0);                                            /* uContextID */
    844923                rc = pMsg->setNextString(pObj->GetDestPath().c_str());             /* pvName */
     
    899978
    900979    /* Set the message type. */
    901     pMsg->setType(DragAndDropSvc::HOST_DND_HG_SND_FILE_DATA);
     980    pMsg->setType(HOST_DND_HG_SND_FILE_DATA);
    902981
    903982    /* Protocol version 1 sends the file path *every* time with a new file chunk.
    904983     * In protocol version 2 we only do this once with HOST_DND_HG_SND_FILE_HDR. */
    905     if (mDataBase.mProtocolVersion <= 1)
     984    if (mDataBase.m_uProtocolVersion <= 1)
    906985    {
    907986        pMsg->setNextString(pObj->GetDestPath().c_str());                  /* pvName */
    908987        pMsg->setNextUInt32((uint32_t)(pObj->GetDestPath().length() + 1)); /* cbName */
    909988    }
    910     else
    911     {
    912         /* Protocol version 2 also sends the context ID. Currently unused. */
    913         pMsg->setNextUInt32(0);                                            /* context ID */
     989    else if (mDataBase.m_uProtocolVersion >= 2)
     990    {
     991        /* Since protocol v2 we also send the context ID. Currently unused. */
     992        pMsg->setNextUInt32(0);                                            /* uContext */
    914993    }
    915994
    916995    uint32_t cbRead = 0;
    917996
    918     int rc = pObj->Read(pCtx->mURI.GetBufferMutable(), pCtx->mURI.GetBufferSize(), &cbRead);
     997    int rc = pObj->Read(pCtx->mURI.getBufferMutable(), pCtx->mURI.getBufferSize(), &cbRead);
    919998    if (RT_SUCCESS(rc))
    920999    {
    921         pCtx->mData.cbProcessed += cbRead;
    922         LogFlowFunc(("cbBufSize=%zu, cbRead=%RU32, cbProcessed=%RU64, rc=%Rrc\n",
    923                      pCtx->mURI.GetBufferSize(), cbRead, pCtx->mData.cbProcessed, rc));
    924 
    925         if (mDataBase.mProtocolVersion <= 1)
    926         {
    927             pMsg->setNextPointer(pCtx->mURI.GetBufferMutable(), cbRead);   /* pvData */
    928             pMsg->setNextUInt32(cbRead);                                   /* cbData */
    929             pMsg->setNextUInt32(pObj->GetMode());                          /* fMode */
    930         }
    931         else
    932         {
    933             pMsg->setNextPointer(pCtx->mURI.GetBufferMutable(), cbRead);   /* pvData */
    934             pMsg->setNextUInt32(cbRead);                                   /* cbData */
     1000        pCtx->mData.addProcessed(cbRead);
     1001        LogFlowFunc(("cbBufSize=%zu, cbRead=%RU32\n", pCtx->mURI.getBufferSize(), cbRead));
     1002
     1003        if (mDataBase.m_uProtocolVersion <= 1)
     1004        {
     1005            pMsg->setNextPointer(pCtx->mURI.getBufferMutable(), cbRead);    /* pvData */
     1006            pMsg->setNextUInt32(cbRead);                                    /* cbData */
     1007            pMsg->setNextUInt32(pObj->GetMode());                           /* fMode */
     1008        }
     1009        else /* Protocol v2 and up. */
     1010        {
     1011            pMsg->setNextPointer(pCtx->mURI.getBufferMutable(), cbRead);    /* pvData */
     1012            pMsg->setNextUInt32(cbRead);                                    /* cbData */
     1013
     1014            if (mDataBase.m_uProtocolVersion >= 3)
     1015            {
     1016                /** @todo Calculate checksum. */
     1017                pMsg->setNextPointer(NULL, 0);                              /* pvChecksum */
     1018                pMsg->setNextUInt32(0);                                     /* cbChecksum */
     1019            }
    9351020        }
    9361021
     
    9611046    LogFlowFunc(("pThis=%p, uMsg=%RU32\n", pThis, uMsg));
    9621047
    963     int rc      = VINF_SUCCESS; /* Will be reported back to guest. */
    964     int rcGuest = VINF_SUCCESS; /* Contains error code from guest in case of VERR_GSTDND_GUEST_ERROR. */
     1048    int  rc      = VINF_SUCCESS;
     1049    int  rcGuest = VINF_SUCCESS; /* Contains error code from guest in case of VERR_GSTDND_GUEST_ERROR. */
    9651050    bool fNotify = false;
    9661051
    9671052    switch (uMsg)
    9681053    {
    969         case DragAndDropSvc::GUEST_DND_GET_NEXT_HOST_MSG:
    970         {
    971             DragAndDropSvc::PVBOXDNDCBHGGETNEXTHOSTMSG pCBData = reinterpret_cast<DragAndDropSvc::PVBOXDNDCBHGGETNEXTHOSTMSG>(pvParms);
     1054        case GUEST_DND_GET_NEXT_HOST_MSG:
     1055        {
     1056            PVBOXDNDCBHGGETNEXTHOSTMSG pCBData = reinterpret_cast<PVBOXDNDCBHGGETNEXTHOSTMSG>(pvParms);
    9721057            AssertPtr(pCBData);
    973             AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBHGGETNEXTHOSTMSG) == cbParms, VERR_INVALID_PARAMETER);
    974             AssertReturn(DragAndDropSvc::CB_MAGIC_DND_HG_GET_NEXT_HOST_MSG == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
     1058            AssertReturn(sizeof(VBOXDNDCBHGGETNEXTHOSTMSG) == cbParms, VERR_INVALID_PARAMETER);
     1059            AssertReturn(CB_MAGIC_DND_HG_GET_NEXT_HOST_MSG == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
    9751060
    9761061            try
     
    10071092            break;
    10081093        }
    1009         case DragAndDropSvc::GUEST_DND_GH_EVT_ERROR:
    1010         {
    1011             DragAndDropSvc::PVBOXDNDCBEVTERRORDATA pCBData = reinterpret_cast<DragAndDropSvc::PVBOXDNDCBEVTERRORDATA>(pvParms);
     1094        case GUEST_DND_GH_EVT_ERROR:
     1095        {
     1096            PVBOXDNDCBEVTERRORDATA pCBData = reinterpret_cast<PVBOXDNDCBEVTERRORDATA>(pvParms);
    10121097            AssertPtr(pCBData);
    1013             AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBEVTERRORDATA) == cbParms, VERR_INVALID_PARAMETER);
    1014             AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_EVT_ERROR == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
     1098            AssertReturn(sizeof(VBOXDNDCBEVTERRORDATA) == cbParms, VERR_INVALID_PARAMETER);
     1099            AssertReturn(CB_MAGIC_DND_GH_EVT_ERROR == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
    10151100
    10161101            pCtx->mpResp->reset();
     
    10221107            }
    10231108
    1024             rc = pCtx->mpResp->setProgress(100, DragAndDropSvc::DND_PROGRESS_ERROR, pCBData->rc,
     1109            rc = pCtx->mpResp->setProgress(100, DND_PROGRESS_ERROR, pCBData->rc,
    10251110                                           GuestDnDTarget::i_guestErrorToString(pCBData->rc));
    10261111            if (RT_SUCCESS(rc))
     
    10311116            break;
    10321117        }
    1033         case DragAndDropSvc::HOST_DND_HG_SND_DIR:
    1034         case DragAndDropSvc::HOST_DND_HG_SND_FILE_HDR:
    1035         case DragAndDropSvc::HOST_DND_HG_SND_FILE_DATA:
    1036         {
    1037             DragAndDropSvc::PVBOXDNDCBHGGETNEXTHOSTMSGDATA pCBData
    1038                 = reinterpret_cast<DragAndDropSvc::PVBOXDNDCBHGGETNEXTHOSTMSGDATA>(pvParms);
     1118        case HOST_DND_HG_SND_DIR:
     1119        case HOST_DND_HG_SND_FILE_HDR:
     1120        case HOST_DND_HG_SND_FILE_DATA:
     1121        {
     1122            PVBOXDNDCBHGGETNEXTHOSTMSGDATA pCBData
     1123                = reinterpret_cast<PVBOXDNDCBHGGETNEXTHOSTMSGDATA>(pvParms);
    10391124            AssertPtr(pCBData);
    1040             AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBHGGETNEXTHOSTMSGDATA) == cbParms, VERR_INVALID_PARAMETER);
    1041             AssertReturn(DragAndDropSvc::CB_MAGIC_DND_HG_GET_NEXT_HOST_MSG_DATA == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
     1125            AssertReturn(sizeof(VBOXDNDCBHGGETNEXTHOSTMSGDATA) == cbParms, VERR_INVALID_PARAMETER);
     1126            AssertReturn(CB_MAGIC_DND_HG_GET_NEXT_HOST_MSG_DATA == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
    10421127
    10431128            LogFlowFunc(("pCBData->uMsg=%RU32, paParms=%p, cParms=%RU32\n", pCBData->uMsg, pCBData->paParms, pCBData->cParms));
     
    10531138                    || pCBData->cParms  != pMsg->getCount())
    10541139                {
     1140                    LogFlowFunc(("Current message does not match:\n"));
     1141                    LogFlowFunc(("\tCallback: uMsg=%RU32, cParms=%RU32, paParms=%p\n",
     1142                                 pCBData->uMsg, pCBData->cParms, pCBData->paParms));
     1143                    LogFlowFunc(("\t    Next: uMsg=%RU32, cParms=%RU32\n", pMsg->getType(), pMsg->getCount()));
     1144
    10551145                    /* Start over. */
    10561146                    pThis->msgQueueClear();
     
    11411231    if (fNotify)
    11421232    {
    1143         int rc2 = pCtx->mCallback.Notify(rc); /** @todo Also pass guest error back? */
     1233        int rc2 = pCtx->mCBEvent.Notify(rc); /** @todo Also pass guest error back? */
    11441234        AssertRC(rc2);
    11451235    }
     
    11731263    }
    11741264
    1175     int rc = pCtx->mURI.Init(mData.mcbBlockSize);
     1265    int rc = pCtx->mURI.init(mData.mcbBlockSize);
    11761266    if (RT_FAILURE(rc))
    11771267        return rc;
    11781268
    1179     rc = pCtx->mCallback.Reset();
     1269    rc = pCtx->mCBEvent.Reset();
    11801270    if (RT_FAILURE(rc))
    11811271        return rc;
     
    11851275     */
    11861276    /* Guest callbacks. */
    1187     REGISTER_CALLBACK(DragAndDropSvc::GUEST_DND_GET_NEXT_HOST_MSG);
    1188     REGISTER_CALLBACK(DragAndDropSvc::GUEST_DND_GH_EVT_ERROR);
     1277    REGISTER_CALLBACK(GUEST_DND_GET_NEXT_HOST_MSG);
     1278    REGISTER_CALLBACK(GUEST_DND_GH_EVT_ERROR);
    11891279    /* Host callbacks. */
    1190     REGISTER_CALLBACK(DragAndDropSvc::HOST_DND_HG_SND_DIR);
    1191     if (mDataBase.mProtocolVersion >= 2)
    1192         REGISTER_CALLBACK(DragAndDropSvc::HOST_DND_HG_SND_FILE_HDR);
    1193     REGISTER_CALLBACK(DragAndDropSvc::HOST_DND_HG_SND_FILE_DATA);
     1280    REGISTER_CALLBACK(HOST_DND_HG_SND_DIR);
     1281    if (mDataBase.m_uProtocolVersion >= 2)
     1282        REGISTER_CALLBACK(HOST_DND_HG_SND_FILE_HDR);
     1283    REGISTER_CALLBACK(HOST_DND_HG_SND_FILE_DATA);
    11941284
    11951285    do
    11961286    {
    11971287        /*
    1198          * Extract URI list from byte data.
     1288         * Extract URI list from current meta data.
    11991289         */
    1200         DnDURIList &lstURI = pCtx->mURI.lstURI; /* Use the URI list from the context. */
    1201 
    1202         const char *pszList = (const char *)&pCtx->mData.vecData.front();
    1203         URI_DATA_IS_VALID_BREAK(pszList);
    1204 
    1205         uint32_t cbList = pCtx->mData.vecData.size();
    1206         URI_DATA_IS_VALID_BREAK(cbList);
    1207 
    1208         RTCList<RTCString> lstURIOrg = RTCString(pszList, cbList).split("\r\n");
    1209         URI_DATA_IS_VALID_BREAK(!lstURIOrg.isEmpty());
    1210 
    1211         /* Note: All files to be transferred will be kept open during the entire DnD
    1212          *       operation, also to keep the accounting right. */
    1213         rc = lstURI.AppendURIPathsFromList(lstURIOrg, DNDURILIST_FLAGS_KEEP_OPEN);
     1290        GuestDnDData    *pData = &pCtx->mData;
     1291        GuestDnDURIData *pURI  = &pCtx->mURI;
     1292
     1293        rc = pURI->fromMetaData(pData->getMeta());
     1294        if (RT_FAILURE(rc))
     1295            break;
     1296
     1297        LogFlowFunc(("URI root objects: %zu, total bytes (raw data to transfer): %zu\n",
     1298                     pURI->getURIList().RootCount(), pURI->getURIList().TotalBytes()));
     1299
     1300        /*
     1301         * Set the new meta data with the URI list in it.
     1302         */
     1303        rc = pData->getMeta().fromURIList(pURI->getURIList());
     1304        if (RT_FAILURE(rc))
     1305            break;
     1306
     1307        /*
     1308         * Set the additional size we are going to send after the meta data header + meta data.
     1309         * This additional data will contain the actual file data we want to transfer.
     1310         */
     1311        pData->setAdditionalSize(pURI->getURIList().TotalBytes());
     1312
     1313        void    *pvFmt = (void *)pCtx->mFmtReq.c_str();
     1314        uint32_t cbFmt = pCtx->mFmtReq.length() + 1;        /* Include terminating zero. */
     1315
     1316        pData->setFmt(pvFmt, cbFmt);
     1317
     1318        /*
     1319         * The first message always is the data header. The meta data itself then follows
     1320         * and *only* contains the root elements of an URI list.
     1321         *
     1322         * After the meta data we generate the messages required to send the
     1323         * file/directory data itself.
     1324         *
     1325         * Note: Protocol < v3 use the first data message to tell what's being sent.
     1326         */
     1327        GuestDnDMsg Msg;
     1328
     1329        /*
     1330         * Send the data header first.
     1331         */
     1332        if (mDataBase.m_uProtocolVersion >= 3)
     1333            rc = i_sendDataHeader(pCtx, pData, &pCtx->mURI);
     1334
     1335        /*
     1336         * Send the (meta) data body.
     1337         */
    12141338        if (RT_SUCCESS(rc))
    1215             LogFlowFunc(("URI root objects: %zu, total bytes (raw data to transfer): %zu\n",
    1216                          lstURI.RootCount(), lstURI.TotalBytes()));
    1217         else
    1218             break;
    1219 
    1220         pCtx->mData.cbProcessed = 0;
    1221         pCtx->mData.cbToProcess = lstURI.TotalBytes();
    1222 
    1223         /*
    1224          * The first message always is the meta info for the data. The meta
    1225          * info *only* contains the root elements of an URI list.
    1226          *
    1227          * After the meta data we generate the messages required to send the data itself.
    1228          */
    1229         Assert(!lstURI.IsEmpty());
    1230         RTCString strData = lstURI.RootToString().c_str();
    1231         size_t    cbData  = strData.length() + 1; /* Include terminating zero. */
    1232 
    1233         GuestDnDMsg MsgSndData;
    1234         MsgSndData.setType(DragAndDropSvc::HOST_DND_HG_SND_DATA);
    1235         MsgSndData.setNextUInt32(pCtx->mScreenID);
    1236         MsgSndData.setNextPointer((void *)pCtx->mFmtReq.c_str(), (uint32_t)pCtx->mFmtReq.length() + 1);
    1237         MsgSndData.setNextUInt32((uint32_t)pCtx->mFmtReq.length() + 1);
    1238         MsgSndData.setNextPointer((void*)strData.c_str(), (uint32_t)cbData);
    1239         MsgSndData.setNextUInt32((uint32_t)cbData);
    1240 
    1241         rc = GuestDnDInst()->hostCall(MsgSndData.getType(), MsgSndData.getCount(), MsgSndData.getParms());
     1339            rc = i_sendDataBody(pCtx, pData);
     1340
    12421341        if (RT_SUCCESS(rc))
    12431342        {
    1244             rc = waitForEvent(msTimeout, pCtx->mCallback, pCtx->mpResp);
     1343            rc = waitForEvent(&pCtx->mCBEvent, pCtx->mpResp, msTimeout);
    12451344            if (RT_FAILURE(rc))
    12461345            {
    12471346                if (rc == VERR_CANCELLED)
    1248                     rc = pCtx->mpResp->setProgress(100, DragAndDropSvc::DND_PROGRESS_CANCELLED, VINF_SUCCESS);
     1347                    rc = pCtx->mpResp->setProgress(100, DND_PROGRESS_CANCELLED, VINF_SUCCESS);
    12491348                else if (rc != VERR_GSTDND_GUEST_ERROR) /* Guest-side error are already handled in the callback. */
    1250                     rc = pCtx->mpResp->setProgress(100, DragAndDropSvc::DND_PROGRESS_ERROR, rc,
     1349                    rc = pCtx->mpResp->setProgress(100, DND_PROGRESS_ERROR, rc,
    12511350                                                   GuestDnDTarget::i_hostErrorToString(rc));
    12521351            }
    12531352            else
    1254                 rc = pCtx->mpResp->setProgress(100, DragAndDropSvc::DND_PROGRESS_COMPLETE, VINF_SUCCESS);
     1353                rc = pCtx->mpResp->setProgress(100, DND_PROGRESS_COMPLETE, VINF_SUCCESS);
    12551354        }
    12561355
     
    12611360     */
    12621361    /* Guest callbacks. */
    1263     UNREGISTER_CALLBACK(DragAndDropSvc::GUEST_DND_GET_NEXT_HOST_MSG);
    1264     UNREGISTER_CALLBACK(DragAndDropSvc::GUEST_DND_GH_EVT_ERROR);
     1362    UNREGISTER_CALLBACK(GUEST_DND_GET_NEXT_HOST_MSG);
     1363    UNREGISTER_CALLBACK(GUEST_DND_GH_EVT_ERROR);
    12651364    /* Host callbacks. */
    1266     UNREGISTER_CALLBACK(DragAndDropSvc::HOST_DND_HG_SND_DIR);
    1267     if (mDataBase.mProtocolVersion >= 2)
    1268         UNREGISTER_CALLBACK(DragAndDropSvc::HOST_DND_HG_SND_FILE_HDR);
    1269     UNREGISTER_CALLBACK(DragAndDropSvc::HOST_DND_HG_SND_FILE_DATA);
     1365    UNREGISTER_CALLBACK(HOST_DND_HG_SND_DIR);
     1366    if (mDataBase.m_uProtocolVersion >= 2)
     1367        UNREGISTER_CALLBACK(HOST_DND_HG_SND_FILE_HDR);
     1368    UNREGISTER_CALLBACK(HOST_DND_HG_SND_FILE_DATA);
    12701369
    12711370#undef REGISTER_CALLBACK
     
    12921391{
    12931392    AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
    1294 
    1295     DnDURIList &lstURI = pCtx->mURI.lstURI;
    1296 
    1297     uint64_t cbTotal = pCtx->mData.cbToProcess;
    1298     uint8_t uPercent = pCtx->mData.cbProcessed * 100 / (cbTotal ? cbTotal : 1);
    1299 
    1300     LogFlowFunc(("%RU64 / %RU64 -- %RU8%%\n", pCtx->mData.cbProcessed, cbTotal, uPercent));
    1301 
    1302     bool fComplete = (uPercent >= 100) || lstURI.IsEmpty();
    1303 
    1304     if (pCtx->mpResp)
    1305     {
    1306         int rc2 = pCtx->mpResp->setProgress(uPercent,
    1307                                               fComplete
    1308                                             ? DragAndDropSvc::DND_PROGRESS_COMPLETE
    1309                                             : DragAndDropSvc::DND_PROGRESS_RUNNING);
    1310         AssertRC(rc2);
    1311     }
    1312 
    1313     if (fComplete)
     1393    AssertPtrReturn(pMsg, VERR_INVALID_POINTER);
     1394
     1395    int rc = updateProgress(&pCtx->mData, pCtx->mpResp);
     1396    AssertRC(rc);
     1397
     1398    if (   pCtx->mData.isComplete()
     1399        && pCtx->mURI.isComplete())
     1400    {
    13141401        return VINF_EOF;
    1315 
    1316     Assert(!lstURI.IsEmpty());
    1317     DnDURIObject *pCurObj = lstURI.First();
    1318 
    1319     /* As we transfer all objects one after another at a time at the moment,
    1320      * we only need one object context at the moment. */
    1321     GuestDnDURIObjCtx *pObjCtx = &pCtx->mURI.objCtx;
    1322 
    1323     /* Assign the pointer of the current object to our context. */
    1324     pObjCtx->pObjURI = pCurObj;
     1402    }
     1403
     1404    GuestDnDURIObjCtx &objCtx = pCtx->mURI.getObjCurrent();
     1405    if (!objCtx.isValid())
     1406        return VERR_WRONG_ORDER;
     1407
     1408    DnDURIObject *pCurObj = objCtx.pObjURI;
     1409    AssertPtr(pCurObj);
    13251410
    13261411    uint32_t fMode = pCurObj->GetMode();
    1327     LogFlowFunc(("Processing srcPath=%s, dstPath=%s, fMode=0x%x, cbSize=%RU32, fIsDir=%RTbool, fIsFile=%RTbool\n",
    1328                  pCurObj->GetSourcePath().c_str(), pCurObj->GetDestPath().c_str(),
    1329                  fMode, pCurObj->GetSize(),
    1330                  RTFS_IS_DIRECTORY(fMode), RTFS_IS_FILE(fMode)));
    1331     int rc;
     1412    LogRel3(("DnD: Processing: srcPath=%s, dstPath=%s, fMode=0x%x, cbSize=%RU32, fIsDir=%RTbool, fIsFile=%RTbool\n",
     1413             pCurObj->GetSourcePath().c_str(), pCurObj->GetDestPath().c_str(),
     1414             fMode, pCurObj->GetSize(),
     1415             RTFS_IS_DIRECTORY(fMode), RTFS_IS_FILE(fMode)));
     1416
    13321417    if (RTFS_IS_DIRECTORY(fMode))
    13331418    {
    1334         rc = i_sendDirectory(pCtx, pObjCtx, pMsg);
     1419        rc = i_sendDirectory(pCtx, &objCtx, pMsg);
    13351420    }
    13361421    else if (RTFS_IS_FILE(fMode))
    13371422    {
    1338         rc = i_sendFile(pCtx, pObjCtx, pMsg);
     1423        rc = i_sendFile(pCtx, &objCtx, pMsg);
    13391424    }
    13401425    else
     
    13551440    {
    13561441        LogFlowFunc(("Removing \"%s\" from list, rc=%Rrc\n", pCurObj->GetSourcePath().c_str(), rc));
    1357         lstURI.RemoveFirst();
     1442        pCtx->mURI.removeObjCurrent();
    13581443    }
    13591444
     
    13701455    AssertPtr(pInst);
    13711456
    1372     /** @todo At the moment we only allow sending up to 64K raw data. Fix this by
    1373      *        using HOST_DND_HG_SND_MORE_DATA. */
    1374     size_t cbDataTotal = pCtx->mData.vecData.size();
    1375     if (   !cbDataTotal
    1376         || cbDataTotal > _64K)
    1377     {
    1378         return VERR_INVALID_PARAMETER;
    1379     }
    1380 
    1381     /* Just copy over the raw data. */
    1382     GuestDnDMsg Msg;
    1383     Msg.setType(DragAndDropSvc::HOST_DND_HG_SND_DATA);
    1384     Msg.setNextUInt32(pCtx->mScreenID);
    1385     Msg.setNextPointer((void *)pCtx->mFmtReq.c_str(), (uint32_t)pCtx->mFmtReq.length() + 1);
    1386     Msg.setNextUInt32((uint32_t)pCtx->mFmtReq.length() + 1);
    1387     Msg.setNextPointer((void*)&pCtx->mData.vecData.front(), (uint32_t)cbDataTotal);
    1388     Msg.setNextUInt32(cbDataTotal);
    1389 
    1390     LogFlowFunc(("Transferring %zu total bytes of raw data ('%s')\n", cbDataTotal, pCtx->mFmtReq.c_str()));
     1457    GuestDnDData *pData = &pCtx->mData;
     1458
     1459    /** @todo At the moment we only allow sending up to 64K raw data.
     1460     *        For protocol v1+v2: Fix this by using HOST_DND_HG_SND_MORE_DATA.
     1461     *        For protocol v3   : Send another HOST_DND_HG_SND_DATA message. */
     1462    if (!pData->getMeta().getSize())
     1463        return VINF_SUCCESS;
     1464
     1465    int rc = VINF_SUCCESS;
     1466
     1467    /*
     1468     * Send the data header first.
     1469     */
     1470    if (mDataBase.m_uProtocolVersion >= 3)
     1471        rc = i_sendDataHeader(pCtx, pData, NULL /* URI list */);
     1472
     1473    /*
     1474     * Send the (meta) data body.
     1475     */
     1476    if (RT_SUCCESS(rc))
     1477        rc = i_sendDataBody(pCtx, pData);
    13911478
    13921479    int rc2;
    1393 
    1394     int rc = pInst->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms());
    13951480    if (RT_FAILURE(rc))
    1396         rc2 = pCtx->mpResp->setProgress(100, DragAndDropSvc::DND_PROGRESS_ERROR, rc,
     1481        rc2 = pCtx->mpResp->setProgress(100, DND_PROGRESS_ERROR, rc,
    13971482                                        GuestDnDTarget::i_hostErrorToString(rc));
    13981483    else
    1399         rc2 = pCtx->mpResp->setProgress(100, DragAndDropSvc::DND_PROGRESS_COMPLETE, rc);
     1484        rc2 = pCtx->mpResp->setProgress(100, DND_PROGRESS_COMPLETE, rc);
    14001485    AssertRC(rc2);
    14011486
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