VirtualBox

Ignore:
Timestamp:
Aug 21, 2015 4:54:50 PM (9 years ago)
Author:
vboxsync
Message:

DnD: Use a separate context for URI object when transferring, misc cleanups.

File:
1 edited

Legend:

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

    r57469 r57500  
    771771    ASMAtomicWriteBool(&pCtx->mIsActive, false);
    772772
    773 #undef DATA_IS_VALID_BREAK
    774 
    775773    LogFlowFuncLeaveRC(rc);
    776774    return rc;
    777775}
    778776
    779 int GuestDnDTarget::i_sendDirectory(PSENDDATACTX pCtx, GuestDnDMsg *pMsg, DnDURIObject *pObject)
    780 {
    781     AssertPtrReturn(pObject, VERR_INVALID_POINTER);
     777int GuestDnDTarget::i_sendDirectory(PSENDDATACTX pCtx, GuestDnDURIObjCtx *pObjCtx, GuestDnDMsg *pMsg)
     778{
    782779    AssertPtrReturn(pCtx,    VERR_INVALID_POINTER);
    783 
    784     RTCString strPath = pObject->GetDestPath();
     780    AssertPtrReturn(pObjCtx, VERR_INVALID_POINTER);
     781    AssertPtrReturn(pMsg,    VERR_INVALID_POINTER);
     782
     783    DnDURIObject *pObj = pObjCtx->pObjURI;
     784    AssertPtr(pObj);
     785
     786    RTCString strPath = pObj->GetDestPath();
    785787    if (strPath.isEmpty())
    786788        return VERR_INVALID_PARAMETER;
     
    793795    pMsg->setNextString(strPath.c_str());                  /* path */
    794796    pMsg->setNextUInt32((uint32_t)(strPath.length() + 1)); /* path length - note: Maximum is RTPATH_MAX on guest side. */
    795     pMsg->setNextUInt32(pObject->GetMode());             /* mode */
     797    pMsg->setNextUInt32(pObj->GetMode());                  /* mode */
    796798
    797799    return VINF_SUCCESS;
    798800}
    799801
    800 int GuestDnDTarget::i_sendFile(PSENDDATACTX pCtx, GuestDnDMsg *pMsg, DnDURIObject *pObject)
    801 {
    802     AssertPtrReturn(pObject, VERR_INVALID_POINTER);
     802int GuestDnDTarget::i_sendFile(PSENDDATACTX pCtx, GuestDnDURIObjCtx *pObjCtx, GuestDnDMsg *pMsg)
     803{
    803804    AssertPtrReturn(pCtx,    VERR_INVALID_POINTER);
    804 
    805     RTCString strPathSrc = pObject->GetSourcePath();
     805    AssertPtrReturn(pObjCtx, VERR_INVALID_POINTER);
     806    AssertPtrReturn(pMsg,    VERR_INVALID_POINTER);
     807
     808    DnDURIObject *pObj = pObjCtx->pObjURI;
     809    AssertPtr(pObj);
     810
     811    RTCString strPathSrc = pObj->GetSourcePath();
    806812    if (strPathSrc.isEmpty())
    807813        return VERR_INVALID_PARAMETER;
     
    809815    int rc = VINF_SUCCESS;
    810816
    811     LogFlowFunc(("Sending \"%s\" (%RU32 bytes buffer) using protocol v%RU32 ...\n",
    812                  strPathSrc.c_str(), mData.mcbBlockSize, mDataBase.mProtocolVersion));
    813 
    814     bool fOpen = pObject->IsOpen();
    815     if (!fOpen)
    816     {
    817         LogFlowFunc(("Opening \"%s\" ...\n", strPathSrc.c_str()));
    818         rc = pObject->OpenEx(strPathSrc, DnDURIObject::File, DnDURIObject::Source,
     817    LogFlowFunc(("Sending file with %RU32 bytes buffer, using protocol v%RU32 ...\n",
     818                  mData.mcbBlockSize, mDataBase.mProtocolVersion));
     819    LogFlowFunc(("strPathSrc=%s, fIsOpen=%RTbool, cbSize=%RU64\n", strPathSrc.c_str(), pObj->IsOpen(), pObj->GetSize()));
     820
     821    if (!pObj->IsOpen())
     822    {
     823        LogRel2(("DnD: Opening host file for transferring to guest: %s\n", strPathSrc.c_str()));
     824        rc = pObj->OpenEx(strPathSrc, DnDURIObject::File, DnDURIObject::Source,
    819825                          RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE, 0 /* fFlags */);
    820826        if (RT_FAILURE(rc))
    821             LogRel(("DnD: Error opening host file \"%s\", rc=%Rrc\n", strPathSrc.c_str(), rc));
    822     }
    823 
    824     bool fSendFileData = false;
     827            LogRel(("DnD: Error opening host file '%s', rc=%Rrc\n", strPathSrc.c_str(), rc));
     828    }
     829
     830    bool fSendData = false;
    825831    if (RT_SUCCESS(rc))
    826832    {
    827833        if (mDataBase.mProtocolVersion >= 2)
    828834        {
    829             if (!fOpen)
     835            if (!pObjCtx->fHeaderSent)
    830836            {
    831837                /*
     
    835841                 */
    836842                pMsg->setType(DragAndDropSvc::HOST_DND_HG_SND_FILE_HDR);
    837                 pMsg->setNextUInt32(0);                                            /* context ID */
    838                 rc = pMsg->setNextString(pObject->GetDestPath().c_str());             /* pvName */
     843                pMsg->setNextUInt32(0);                                            /* uContextID */
     844                rc = pMsg->setNextString(pObj->GetDestPath().c_str());             /* pvName */
    839845                AssertRC(rc);
    840                 pMsg->setNextUInt32((uint32_t)(pObject->GetDestPath().length() + 1)); /* cbName */
     846                pMsg->setNextUInt32((uint32_t)(pObj->GetDestPath().length() + 1)); /* cbName */
    841847                pMsg->setNextUInt32(0);                                            /* uFlags */
    842                 pMsg->setNextUInt32(pObject->GetMode());                              /* fMode */
    843                 pMsg->setNextUInt64(pObject->GetSize());                              /* uSize */
     848                pMsg->setNextUInt32(pObj->GetMode());                              /* fMode */
     849                pMsg->setNextUInt64(pObj->GetSize());                              /* uSize */
    844850
    845851                LogFlowFunc(("Sending file header ...\n"));
    846852                LogRel2(("DnD: Transferring host file to guest: %s (%RU64 bytes, mode 0x%x)\n",
    847                          strPathSrc.c_str(), pObject->GetSize(), pObject->GetMode()));
     853                         strPathSrc.c_str(), pObj->GetSize(), pObj->GetMode()));
    848854
    849855                /** @todo Set progress object title to current file being transferred? */
     856
     857                pObjCtx->fHeaderSent = true;
    850858            }
    851859            else
    852860            {
    853861                /* File header was sent, so only send the actual file data. */
    854                 fSendFileData = true;
     862                fSendData = true;
    855863            }
    856864        }
     
    858866        {
    859867            /* Always send the file data, every time. */
    860             fSendFileData = true;
     868            fSendData = true;
    861869        }
    862870    }
    863871
    864872    if (   RT_SUCCESS(rc)
    865         && fSendFileData)
    866     {
    867         rc = i_sendFileData(pCtx, pMsg, pObject);
     873        && fSendData)
     874    {
     875        rc = i_sendFileData(pCtx, pObjCtx, pMsg);
    868876    }
    869877
     
    872880}
    873881
    874 int GuestDnDTarget::i_sendFileData(PSENDDATACTX pCtx, GuestDnDMsg *pMsg, DnDURIObject *pObject)
    875 {
    876     AssertPtrReturn(pObject, VERR_INVALID_POINTER);
     882int GuestDnDTarget::i_sendFileData(PSENDDATACTX pCtx, GuestDnDURIObjCtx *pObjCtx, GuestDnDMsg *pMsg)
     883{
    877884    AssertPtrReturn(pCtx,    VERR_INVALID_POINTER);
     885    AssertPtrReturn(pObjCtx, VERR_INVALID_POINTER);
    878886    AssertPtrReturn(pMsg,    VERR_INVALID_POINTER);
     887
     888    DnDURIObject *pObj = pObjCtx->pObjURI;
     889    AssertPtr(pObj);
    879890
    880891    GuestDnDResponse *pResp = pCtx->mpResp;
     
    882893
    883894    /** @todo Don't allow concurrent reads per context! */
    884 
    885     /* Something to transfer? */
    886     if (   pCtx->mURI.lstURI.IsEmpty()
    887         || !pCtx->mIsActive)
    888     {
    889         return VERR_WRONG_ORDER;
    890     }
    891895
    892896    /*
     
    901905    if (mDataBase.mProtocolVersion <= 1)
    902906    {
    903         pMsg->setNextString(pObject->GetDestPath().c_str());                  /* pvName */
    904         pMsg->setNextUInt32((uint32_t)(pObject->GetDestPath().length() + 1)); /* cbName */
     907        pMsg->setNextString(pObj->GetDestPath().c_str());                  /* pvName */
     908        pMsg->setNextUInt32((uint32_t)(pObj->GetDestPath().length() + 1)); /* cbName */
    905909    }
    906910    else
    907911    {
    908912        /* Protocol version 2 also sends the context ID. Currently unused. */
    909         pMsg->setNextUInt32(0);                                              /* context ID */
     913        pMsg->setNextUInt32(0);                                            /* context ID */
    910914    }
    911915
    912916    uint32_t cbRead = 0;
    913917
    914     int rc = pObject->Read(pCtx->mURI.GetBufferMutable(), pCtx->mURI.GetBufferSize(), &cbRead);
     918    int rc = pObj->Read(pCtx->mURI.GetBufferMutable(), pCtx->mURI.GetBufferSize(), &cbRead);
    915919    if (RT_SUCCESS(rc))
    916920    {
    917921        pCtx->mData.cbProcessed += cbRead;
     922        LogFlowFunc(("cbBufSize=%zu, cbRead=%RU32, cbProcessed=%RU64, rc=%Rrc\n",
     923                     pCtx->mURI.GetBufferSize(), cbRead, pCtx->mData.cbProcessed, rc));
    918924
    919925        if (mDataBase.mProtocolVersion <= 1)
    920926        {
    921             pMsg->setNextPointer(pCtx->mURI.GetBufferMutable(), cbRead); /* pvData */
    922             pMsg->setNextUInt32(cbRead);                                 /* cbData */
    923             pMsg->setNextUInt32(pObject->GetMode());                     /* fMode */
     927            pMsg->setNextPointer(pCtx->mURI.GetBufferMutable(), cbRead);   /* pvData */
     928            pMsg->setNextUInt32(cbRead);                                   /* cbData */
     929            pMsg->setNextUInt32(pObj->GetMode());                          /* fMode */
    924930        }
    925931        else
    926932        {
    927             pMsg->setNextPointer(pCtx->mURI.GetBufferMutable(), cbRead); /* pvData */
    928             pMsg->setNextUInt32(cbRead);                                 /* cbData */
    929         }
    930 
    931         if (pObject->IsComplete()) /* Done reading? */
    932         {
    933             LogRel2(("DnD: File transfer to guest complete: %s\n", pObject->GetSourcePath().c_str()));
    934             LogFlowFunc(("File \"%s\" complete\n", pObject->GetSourcePath().c_str()));
    935             rc = VINF_EOF;
     933            pMsg->setNextPointer(pCtx->mURI.GetBufferMutable(), cbRead);   /* pvData */
     934            pMsg->setNextUInt32(cbRead);                                   /* cbData */
     935        }
     936
     937        if (pObj->IsComplete()) /* Done reading? */
     938        {
     939            LogRel2(("DnD: File transfer to guest complete: %s\n", pObj->GetSourcePath().c_str()));
     940            LogFlowFunc(("File '%s' complete\n", pObj->GetSourcePath().c_str()));
     941
     942            /* DnDURIObject::Read() returns VINF_EOF when finished reading the entire fire,
     943             * but we don't want this here -- so just override this with VINF_SUCCESS. */
     944            rc = VINF_SUCCESS;
    936945        }
    937946    }
     
    952961    LogFlowFunc(("pThis=%p, uMsg=%RU32\n", pThis, uMsg));
    953962
    954     int rc = VINF_SUCCESS; /* Will be reported back to guest. */
    955 
    956     int rcCallback = VINF_SUCCESS; /* rc for the callback. */
     963    int rc      = VINF_SUCCESS; /* Will be reported back to guest. */
     964    int rcGuest;                /* Contains error code from guest in case of VERR_GSTDND_GUEST_ERROR. */
    957965    bool fNotify = false;
    958966
     
    971979
    972980                rc = pThis->i_sendURIDataLoop(pCtx, pMsg);
    973                 if (RT_SUCCESS(rc))
     981                if (rc == VINF_EOF) /* Transfer complete? */
     982                {
     983                    LogFlowFunc(("Last URI item processed, bailing out\n"));
     984                }
     985                else if (RT_SUCCESS(rc))
    974986                {
    975987                    rc = pThis->msgQueueAdd(pMsg);
     
    982994                }
    983995
    984                 if (RT_FAILURE(rc))
     996                if (   RT_FAILURE(rc)
     997                    || rc == VINF_EOF) /* Transfer complete? */
     998                {
    985999                    delete pMsg;
     1000                    pMsg = NULL;
     1001                }
    9861002            }
    9871003            catch(std::bad_alloc & /*e*/)
     
    10011017
    10021018            if (RT_SUCCESS(pCBData->rc))
     1019            {
     1020                AssertMsgFailed(("Guest has sent an error event but did not specify an actual error code\n"));
    10031021                pCBData->rc = VERR_GENERAL_FAILURE; /* Make sure some error is set. */
     1022            }
    10041023
    10051024            rc = pCtx->mpResp->setProgress(100, DragAndDropSvc::DND_PROGRESS_ERROR, pCBData->rc,
    10061025                                           GuestDnDTarget::i_guestErrorToString(pCBData->rc));
    10071026            if (RT_SUCCESS(rc))
    1008                 rcCallback = VERR_GSTDND_GUEST_ERROR;
     1027            {
     1028                rc      = VERR_GSTDND_GUEST_ERROR;
     1029                rcGuest = pCBData->rc;
     1030            }
    10091031            break;
    10101032        }
     
    10611083    }
    10621084
    1063     if (   RT_FAILURE(rc)
    1064         || RT_FAILURE(rcCallback))
    1065     {
    1066         fNotify = true;
    1067         if (RT_SUCCESS(rcCallback))
    1068             rcCallback = rc;
     1085    int rcToGuest = VINF_SUCCESS; /* Status which will be sent back to the guest. */
     1086
     1087    /*
     1088     * Resolve errors.
     1089     */
     1090    switch (rc)
     1091    {
     1092        case VINF_SUCCESS:
     1093            break;
     1094
     1095        case VINF_EOF:
     1096        {
     1097            LogRel2(("DnD: Transfer to guest complete\n"));
     1098
     1099            /* Complete operation on host side. */
     1100            fNotify = true;
     1101
     1102            /* The guest expects VERR_NO_DATA if the transfer is complete. */
     1103            rcToGuest = VERR_NO_DATA;
     1104            break;
     1105        }
     1106
     1107        case VERR_GSTDND_GUEST_ERROR:
     1108        {
     1109            LogRel(("DnD: Guest reported error %Rrc, aborting transfer to guest\n", rcGuest));
     1110            break;
     1111        }
     1112
     1113        case VERR_CANCELLED:
     1114        {
     1115            LogRel2(("DnD: Transfer to guest canceled\n"));
     1116            rcToGuest = VERR_CANCELLED; /* Also cancel on guest side. */
     1117            break;
     1118        }
     1119
     1120        default:
     1121        {
     1122            LogRel(("DnD: Host error %Rrc occurred, aborting transfer to guest\n", rc));
     1123            rcToGuest = VERR_CANCELLED; /* Also cancel on guest side. */
     1124            break;
     1125        }
    10691126    }
    10701127
    10711128    if (RT_FAILURE(rc))
    10721129    {
    1073         switch (rc)
    1074         {
    1075             case VERR_NO_DATA:
    1076                 LogRel2(("DnD: Transfer to guest complete\n"));
    1077                 break;
    1078 
    1079             case VERR_CANCELLED:
    1080                 LogRel2(("DnD: Transfer to guest canceled\n"));
    1081                 break;
    1082 
    1083             default:
    1084                 LogRel(("DnD: Error %Rrc occurred, aborting transfer to guest\n", rc));
    1085                 break;
    1086         }
    1087 
    10881130        /* Unregister this callback. */
    10891131        AssertPtr(pCtx->mpResp);
    10901132        int rc2 = pCtx->mpResp->setCallback(uMsg, NULL /* PFNGUESTDNDCALLBACK */);
    10911133        AssertRC(rc2);
    1092     }
    1093 
    1094     LogFlowFunc(("fNotify=%RTbool, rcCallback=%Rrc, rc=%Rrc\n", fNotify, rcCallback, rc));
     1134
     1135        /* Let the waiter(s) know. */
     1136        fNotify = true;
     1137    }
     1138
     1139    LogFlowFunc(("fNotify=%RTbool, rc=%Rrc, rcToGuest=%Rrc\n", fNotify, rc, rcToGuest));
    10951140
    10961141    if (fNotify)
    10971142    {
    1098         int rc2 = pCtx->mCallback.Notify(rcCallback);
     1143        int rc2 = pCtx->mCallback.Notify(rc); /** @todo Also pass guest error back? */
    10991144        AssertRC(rc2);
    11001145    }
    11011146
    11021147    LogFlowFuncLeaveRC(rc);
    1103     return rc; /* Tell the guest. */
     1148    return rcToGuest; /* Tell the guest. */
    11041149}
    11051150
     
    11641209        URI_DATA_IS_VALID_BREAK(!lstURIOrg.isEmpty());
    11651210
    1166         uint32_t fFlags = DNDURILIST_FLAGS_KEEP_OPEN;
    1167 
    1168         rc = lstURI.AppendURIPathsFromList(lstURIOrg, fFlags);
     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);
    11691214        if (RT_SUCCESS(rc))
    11701215            LogFlowFunc(("URI root objects: %zu, total bytes (raw data to transfer): %zu\n",
     
    12671312
    12681313    if (fComplete)
    1269     {
    1270         LogFlowFunc(("Last URI item processed, bailing out\n"));
    1271         return VERR_NO_DATA;
    1272     }
     1314        return VINF_EOF;
    12731315
    12741316    Assert(!lstURI.IsEmpty());
    12751317    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;
    12761325
    12771326    uint32_t fMode = pCurObj->GetMode();
     
    12831332    if (RTFS_IS_DIRECTORY(fMode))
    12841333    {
    1285         rc = i_sendDirectory(pCtx, pMsg, pCurObj);
     1334        rc = i_sendDirectory(pCtx, pObjCtx, pMsg);
    12861335    }
    12871336    else if (RTFS_IS_FILE(fMode))
    12881337    {
    1289         rc = i_sendFile(pCtx, pMsg, pCurObj);
     1338        rc = i_sendFile(pCtx, pObjCtx, pMsg);
    12901339    }
    12911340    else
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