Changeset 85371 in vbox for trunk/src/VBox/Additions/common
- Timestamp:
- Jul 17, 2020 10:02:58 AM (5 years ago)
- svn:sync-xref-src-repo-rev:
- 139382
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibDragAndDrop.cpp
r85029 r85371 349 349 * @param pDroppedFiles Dropped files object to use for maintaining the file creation / locking. 350 350 */ 351 static int vbglR3DnDHGRecvURIData(PVBGLR3GUESTDNDCMDCTX pCtx, PVBOXDNDSNDDATAHDR pDataHdr, DnDDroppedFiles *pDroppedFiles)351 static int vbglR3DnDHGRecvURIData(PVBGLR3GUESTDNDCMDCTX pCtx, PVBOXDNDSNDDATAHDR pDataHdr, PDNDDROPPEDFILES pDroppedFiles) 352 352 { 353 353 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); … … 384 384 * Create and query the (unique) drop target directory in the user's temporary directory. 385 385 */ 386 int rc = pDroppedFiles->OpenTemp(0 /* fFlags */);386 int rc = DnDDroppedFilesOpenTemp(pDroppedFiles, 0 /* fFlags */); 387 387 if (RT_FAILURE(rc)) 388 388 { … … 391 391 } 392 392 393 const char *pszDropDir = pDroppedFiles->GetDirAbs();393 const char *pszDropDir = DnDDroppedFilesGetDirAbs(pDroppedFiles); 394 394 AssertPtr(pszDropDir); 395 395 … … 397 397 * Enter the main loop of retieving files + directories. 398 398 */ 399 DnDURIObject objFile; 399 DNDTRANSFEROBJECT objCur; 400 RT_ZERO(objCur); 400 401 401 402 char szPathName[RTPATH_MAX] = { 0 }; … … 424 425 &cbPathName, 425 426 &fMode); 426 LogFlowFunc(("HOST_DND_HG_SND_DIR pszPathName=%s, cbPathName=%RU32, fMode=0x%x, rc=%Rrc\n", 427 LogFlowFunc(("HOST_DND_HG_SND_DIR: " 428 "pszPathName=%s, cbPathName=%RU32, fMode=0x%x, rc=%Rrc\n", 427 429 szPathName, cbPathName, fMode, rc)); 428 430 … … 437 439 rc = RTDirCreate(pszPathAbs, fCreationMode, 0); 438 440 if (RT_SUCCESS(rc)) 439 rc = pDroppedFiles->AddDir(pszPathAbs);441 rc = DnDDroppedFilesAddDir(pDroppedFiles, pszPathAbs); 440 442 441 443 if (RT_SUCCESS(rc)) … … 452 454 } 453 455 case HOST_DND_HG_SND_FILE_HDR: 456 RT_FALL_THROUGH(); 454 457 case HOST_DND_HG_SND_FILE_DATA: 455 458 { … … 489 492 490 493 /* Is there already a file open, e.g. in transfer? */ 491 if (! objFile.IsOpen())494 if (!DnDTransferObjectIsOpen(&objCur)) 492 495 { 493 RTCString strPathAbs(pszPathAbs);494 496 #ifdef RT_OS_WINDOWS 495 497 uint32_t fCreationMode = (fMode & RTFS_DOS_MASK) | RTFS_DOS_NT_NORMAL; … … 497 499 uint32_t fCreationMode = (fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR; 498 500 #endif 499 rc = objFile.Init(DnDURIObject::Type_File, strPathAbs); 501 rc = DnDTransferObjectInit(&objCur, DNDTRANSFEROBJTYPE_FILE, 502 pszDropDir /* Source (base) path */, szPathName /* Destination path */); 500 503 if (RT_SUCCESS(rc)) 501 504 { 502 rc = objFile.Open(fOpen, fCreationMode);505 rc = DnDTransferObjectOpen(&objCur, fOpen, fCreationMode, DNDTRANSFEROBJECT_FLAGS_NONE); 503 506 if (RT_SUCCESS(rc)) 504 507 { 505 rc = pDroppedFiles->AddFile(strPathAbs.c_str());508 rc = DnDDroppedFilesAddFile(pDroppedFiles, pszPathAbs); 506 509 if (RT_SUCCESS(rc)) 507 510 { 508 511 cbFileWritten = 0; 509 objFile.SetSize(cbFileSize);512 DnDTransferObjectSetSize(&objCur, cbFileSize); 510 513 } 511 514 } … … 514 517 else 515 518 { 516 AssertMsgFailed(("ObjType=%RU32\n", objFile.GetType()));519 AssertMsgFailed(("ObjType=%RU32\n", DnDTransferObjectGetType(&objCur))); 517 520 rc = VERR_WRONG_ORDER; 518 521 } … … 529 532 { 530 533 uint32_t cbChunkWritten; 531 rc = objFile.Write(pvChunk, cbChunkRead, &cbChunkWritten);534 rc = DnDTransferObjectWrite(&objCur, pvChunk, cbChunkRead, &cbChunkWritten); 532 535 if (RT_SUCCESS(rc)) 533 536 { 534 LogFlowFunc(("HOST_DND_HG_SND_FILE_DATA "537 LogFlowFunc(("HOST_DND_HG_SND_FILE_DATA: " 535 538 "cbChunkRead=%RU32, cbChunkWritten=%RU32, cbFileWritten=%RU64 cbFileSize=%RU64\n", 536 539 cbChunkRead, cbChunkWritten, cbFileWritten + cbChunkWritten, cbFileSize)); … … 544 547 545 548 /* Data transfer complete? Close the file. */ 546 bool fClose = objFile.IsComplete();549 bool fClose = DnDTransferObjectIsComplete(&objCur); 547 550 if (fClose) 548 551 { … … 557 560 { 558 561 LogFlowFunc(("Closing file\n")); 559 objFile.Close();562 DnDTransferObjectDestroy(&objCur); 560 563 } 561 564 … … 604 607 if (RT_FAILURE(rc)) 605 608 { 606 objFile.Close();607 pDroppedFiles->Rollback();609 DnDTransferObjectDestroy(&objCur); 610 DnDDroppedFilesRollback(pDroppedFiles); 608 611 } 609 612 else 610 613 { 611 /** @todo Compare the URIlist with the dirs/files we really transferred. */614 /** @todo Compare the transfer list with the dirs/files we really transferred. */ 612 615 /** @todo Implement checksum verification, if any. */ 613 616 } … … 618 621 * by the client's drag'n drop operation lateron. 619 622 */ 620 int rc2 = pDroppedFiles->Reset(false /* fRemoveDropDir */);623 int rc2 = DnDDroppedFilesReset(pDroppedFiles, false /* fRemoveDropDir */); 621 624 if (RT_FAILURE(rc2)) /* Not fatal, don't report back to host. */ 622 625 LogFlowFunc(("Closing dropped files directory failed with %Rrc\n", rc2)); … … 805 808 /** 806 809 * Host -> Guest 807 * Main function for receiving the actual DnD data from the host, extended version. 808 * 809 * @returns IPRT status code. 810 * @param pCtx DnD context to use. 811 * @param pEnmType Where to store the meta data type. Optional. 812 * @param ppvData Returns the received meta data. Needs to be free'd by the caller. Optional. 813 * @param pcbData Where to store the size (in bytes) of the received meta data. Optional. 814 */ 815 static int vbglR3DnDHGRecvDataMainEx(PVBGLR3GUESTDNDCMDCTX pCtx, 816 VBGLR3GUESTDNDMETADATATYPE *pEnmType, 817 void **ppvData, 818 uint32_t *pcbData) 810 * Main function for receiving the actual DnD data from the host. 811 * 812 * @returns IPRT status code. 813 * @param pCtx DnD context to use. 814 * @param pMeta Where to store the actual meta data received from the host. 815 */ 816 static int vbglR3DnDHGRecvDataMain(PVBGLR3GUESTDNDCMDCTX pCtx, 817 PVBGLR3GUESTDNDMETADATA pMeta) 819 818 { 820 819 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 821 /* The rest is optional. */820 AssertPtrReturn(pMeta, VERR_INVALID_POINTER); 822 821 823 822 VBOXDNDDATAHDR dataHdr; … … 831 830 return VERR_NO_MEMORY; 832 831 833 DnDURIList lstURI; 834 DnDDroppedFiles droppedFiles; 832 DNDDROPPEDFILES droppedFiles; 835 833 836 834 void *pvData = NULL; … … 855 853 Assert(cbData); 856 854 857 rc = lstURI.SetFromURIData(pvData, cbData, 0 /* fFlags */); 855 /* Use the dropped files directory as the root directory for the current transfer. */ 856 rc = DnDTransferListInit(&pMeta->u.URI.Transfer, DnDDroppedFilesGetDirAbs(&droppedFiles)); 858 857 if (RT_SUCCESS(rc)) 859 rc = vbglR3DnDHGRecvURIData(pCtx, &dataHdr, &droppedFiles);860 861 if (RT_SUCCESS(rc)) /** @todo Remove this block as soon as we hand in DnDURIList. */862 858 { 863 if (pvData) 864 { 865 /* Reuse data buffer to fill in the transformed URI file list. */ 866 RTMemFree(pvData); 867 pvData = NULL; 868 } 869 870 RTCString strData = lstURI.GetRootEntries(droppedFiles.GetDirAbs()); 871 Assert(!strData.isEmpty()); 872 873 cbData = strData.length() + 1; 874 LogFlowFunc(("URI list has %zu bytes\n", cbData)); 875 876 pvData = RTMemAlloc(cbData); 877 if (pvData) 878 { 879 memcpy(pvData, strData.c_str(), cbData); 880 881 if (pEnmType) 882 *pEnmType = VBGLR3GUESTDNDMETADATATYPE_URI_LIST; 883 } 884 else 885 rc = VERR_NO_MEMORY; 859 rc = DnDTransferListAppendPathsFromBuffer(&pMeta->u.URI.Transfer, DNDTRANSFERLISTFMT_URI, (const char *)pvData, cbData, 860 DND_PATH_SEPARATOR, 0 /* fFlags */); 861 if (RT_SUCCESS(rc)) 862 rc = vbglR3DnDHGRecvURIData(pCtx, &dataHdr, &droppedFiles); 886 863 } 887 864 } 888 865 else /* Raw data. */ 889 866 { 890 if (pEnmType) 891 *pEnmType = VBGLR3GUESTDNDMETADATATYPE_RAW; 867 pMeta->enmType = VBGLR3GUESTDNDMETADATATYPE_RAW; 892 868 } 893 869 } … … 898 874 if (RT_SUCCESS(rc)) 899 875 { 900 if ( pvData 901 && cbData) 902 { 903 if (pcbData) 904 *pcbData = cbData; 905 if (ppvData) 906 *ppvData = pvData; 907 else 908 RTMemFree(pvData); 909 } 876 910 877 } 911 878 else if ( RT_FAILURE(rc) … … 921 888 922 889 LogFlowFuncLeaveRC(rc); 923 return rc;924 }925 926 /**927 * Host -> Guest928 * Main function for receiving the actual DnD data from the host.929 *930 * @returns IPRT status code.931 * @param pCtx DnD context to use.932 * @param pMeta Where to store the actual meta data received from the host.933 */934 static int vbglR3DnDHGRecvDataMain(PVBGLR3GUESTDNDCMDCTX pCtx,935 PVBGLR3GUESTDNDMETADATA pMeta)936 {937 AssertPtrReturn(pMeta, VERR_INVALID_POINTER);938 939 int rc = vbglR3DnDHGRecvDataMainEx(pCtx,940 &pMeta->enmType,941 &pMeta->pvMeta,942 &pMeta->cbMeta);943 890 return rc; 944 891 } … … 1300 1247 { 1301 1248 PVBGLR3GUESTDNDMETADATA pMeta = &pEvent->u.HG_Received.Meta; 1302 if (pMeta->pvMeta)1249 switch (pMeta->enmType) 1303 1250 { 1304 Assert(pMeta->cbMeta); 1305 RTMemFree(pMeta->pvMeta); 1306 pMeta->cbMeta = 0; 1251 case VBGLR3GUESTDNDMETADATATYPE_RAW: 1252 { 1253 if (pMeta->u.Raw.pvMeta) 1254 { 1255 Assert(pMeta->u.Raw.cbMeta); 1256 RTMemFree(pMeta->u.Raw.pvMeta); 1257 pMeta->u.Raw.cbMeta = 0; 1258 } 1259 break; 1260 } 1261 1262 case VBGLR3GUESTDNDMETADATATYPE_URI_LIST: 1263 { 1264 DnDTransferListDestroy(&pMeta->u.URI.Transfer); 1265 break; 1266 } 1267 1268 default: 1269 break; 1307 1270 } 1308 1271 break; … … 1503 1466 * @returns IPRT status code. 1504 1467 * @param pCtx DnD context to use. 1505 * @param pObj URIobject containing the directory to send.1506 */ 1507 static int vbglR3DnDGHSendDir(PVBGLR3GUESTDNDCMDCTX pCtx, D nDURIObject*pObj)1468 * @param pObj transfer object containing the directory to send. 1469 */ 1470 static int vbglR3DnDGHSendDir(PVBGLR3GUESTDNDCMDCTX pCtx, DNDTRANSFEROBJECT *pObj) 1508 1471 { 1509 1472 AssertPtrReturn(pObj, VERR_INVALID_POINTER); 1510 1473 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 1511 AssertReturn(pObj->GetType() == DnDURIObject::Type_Directory, VERR_INVALID_PARAMETER); 1512 1513 RTCString strPath = pObj->GetPath(); 1514 LogFlowFunc(("strDir=%s (%zu), fMode=0x%x\n", 1515 strPath.c_str(), strPath.length(), pObj->GetMode())); 1516 1517 if (strPath.length() > RTPATH_MAX) 1474 AssertReturn(DnDTransferObjectGetType(pObj) == DNDTRANSFEROBJTYPE_DIRECTORY, VERR_INVALID_PARAMETER); 1475 1476 const char *pcszPath = DnDTransferObjectGetDestPath(pObj); 1477 const size_t cchPath = RTStrNLen(pcszPath, RTPATH_MAX); 1478 const RTFMODE fMode = DnDTransferObjectGetMode(pObj); 1479 1480 LogFlowFunc(("strDir=%s (%zu), fMode=0x%x\n", pcszPath, cchPath, fMode)); 1481 1482 if (cchPath > RTPATH_MAX) /* Can't happen, but check anyway. */ 1518 1483 return VERR_INVALID_PARAMETER; 1519 1520 const uint32_t cbPath = (uint32_t)strPath.length() + 1; /* Include termination. */1521 1484 1522 1485 HGCMMsgGHSendDir Msg; … … 1524 1487 /** @todo Context ID not used yet. */ 1525 1488 Msg.u.v3.uContext.SetUInt32(0); 1526 Msg.u.v3.pvName.SetPtr((void *) strPath.c_str(), (uint32_t)cbPath);1527 Msg.u.v3.cbName.SetUInt32((uint32_t)c bPath);1528 Msg.u.v3.fMode.SetUInt32( pObj->GetMode());1489 Msg.u.v3.pvName.SetPtr((void *)pcszPath, (uint32_t)cchPath); 1490 Msg.u.v3.cbName.SetUInt32((uint32_t)cchPath + 1); /* Include termination. */ 1491 Msg.u.v3.fMode.SetUInt32(fMode); 1529 1492 1530 1493 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg)); … … 1537 1500 * @returns IPRT status code. 1538 1501 * @param pCtx DnD context to use. 1539 * @param pObj URIobject containing the file to send.1540 */ 1541 static int vbglR3DnDGHSendFile(PVBGLR3GUESTDNDCMDCTX pCtx, DnDURIObject *pObj)1502 * @param pObj Transfer object containing the file to send. 1503 */ 1504 static int vbglR3DnDGHSendFile(PVBGLR3GUESTDNDCMDCTX pCtx, PDNDTRANSFEROBJECT pObj) 1542 1505 { 1543 1506 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 1544 1507 AssertPtrReturn(pObj, VERR_INVALID_POINTER); 1545 AssertReturn( pObj->GetType() == DnDURIObject::Type_File, VERR_INVALID_PARAMETER);1546 AssertReturn( pObj->IsOpen(),VERR_INVALID_STATE);1508 AssertReturn(DnDTransferObjectGetType(pObj) == DNDTRANSFEROBJTYPE_FILE, VERR_INVALID_PARAMETER); 1509 AssertReturn(DnDTransferObjectIsOpen(pObj), VERR_INVALID_STATE); 1547 1510 1548 1511 uint32_t cbBuf = _64K; /** @todo Make this configurable? */ … … 1551 1514 return VERR_NO_MEMORY; 1552 1515 1553 RTCString strPath = pObj->GetPath(); 1554 1555 LogFlowFunc(("strFile=%s (%zu), cbSize=%RU64, fMode=0x%x\n", strPath.c_str(), strPath.length(), 1556 pObj->GetSize(), pObj->GetMode())); 1516 const char *pcszPath = DnDTransferObjectGetDestPath(pObj); 1517 const size_t cchPath = RTStrNLen(pcszPath, RTPATH_MAX); 1518 const uint64_t cbSize = DnDTransferObjectGetSize(pObj); 1519 const RTFMODE fMode = DnDTransferObjectGetMode(pObj); 1520 1521 LogFlowFunc(("strFile=%s (%zu), cbSize=%RU64, fMode=0x%x\n", pcszPath, cchPath, cbSize, fMode)); 1557 1522 1558 1523 HGCMMsgGHSendFileHdr MsgHdr; 1559 1524 VBGL_HGCM_HDR_INIT(&MsgHdr.hdr, pCtx->uClientID, GUEST_DND_GH_SND_FILE_HDR, 6); 1560 1525 MsgHdr.uContext.SetUInt32(0); /* Context ID; unused at the moment. */ 1561 MsgHdr.pvName.SetPtr((void *) strPath.c_str(), (uint32_t)(strPath.length() + 1));1562 MsgHdr.cbName.SetUInt32((uint32_t)( strPath.length() + 1));1526 MsgHdr.pvName.SetPtr((void *)pcszPath, (uint32_t)(cchPath + 1)); /* Include termination. */ 1527 MsgHdr.cbName.SetUInt32((uint32_t)(cchPath + 1)); /* Ditto. */ 1563 1528 MsgHdr.uFlags.SetUInt32(0); /* Flags; unused at the moment. */ 1564 MsgHdr.fMode.SetUInt32( pObj->GetMode());/* File mode */1565 MsgHdr.cbTotal.SetUInt64( pObj->GetSize());/* File size (in bytes). */1529 MsgHdr.fMode.SetUInt32(fMode); /* File mode */ 1530 MsgHdr.cbTotal.SetUInt64(cbSize); /* File size (in bytes). */ 1566 1531 1567 1532 int rc = VbglR3HGCMCall(&MsgHdr.hdr, sizeof(MsgHdr)); … … 1580 1545 Msg.u.v3.cbChecksum.SetUInt32(0); 1581 1546 1582 uint64_t cbToReadTotal = pObj->GetSize();1547 uint64_t cbToReadTotal = cbSize; 1583 1548 uint64_t cbWrittenTotal = 0; 1584 1549 while (cbToReadTotal) … … 1587 1552 uint32_t cbRead = 0; 1588 1553 if (cbToRead) 1589 rc = pObj->Read(pvBuf, cbToRead, &cbRead);1554 rc = DnDTransferObjectRead(pObj, pvBuf, cbToRead, &cbRead); 1590 1555 1591 1556 LogFlowFunc(("cbToReadTotal=%RU64, cbToRead=%RU32, cbRead=%RU32, rc=%Rrc\n", … … 1612 1577 cbWrittenTotal += cbRead; 1613 1578 1614 LogFlowFunc(("%RU64/%RU64 -- %RU8%%\n", cbWrittenTotal, pObj->GetSize(), cbWrittenTotal * 100 / pObj->GetSize()));1579 LogFlowFunc(("%RU64/%RU64 -- %RU8%%\n", cbWrittenTotal, cbSize, cbWrittenTotal * 100 / cbSize)); 1615 1580 }; 1616 1581 } … … 1624 1589 /** 1625 1590 * Guest -> Host 1626 * Utility function to send a n URIobject from guest to the host.1627 * 1628 * @returns IPRT status code. 1629 * @param pCtx DnD context to use. 1630 * @param pObj URIobject to send from guest to the host.1631 */ 1632 static int vbglR3DnDGHSendURIObject(PVBGLR3GUESTDNDCMDCTX pCtx, DnDURIObject *pObj)1591 * Utility function to send a transfer object from guest to the host. 1592 * 1593 * @returns IPRT status code. 1594 * @param pCtx DnD context to use. 1595 * @param pObj Transfer object to send from guest to the host. 1596 */ 1597 static int vbglR3DnDGHSendURIObject(PVBGLR3GUESTDNDCMDCTX pCtx, PDNDTRANSFEROBJECT pObj) 1633 1598 { 1634 1599 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); … … 1637 1602 int rc; 1638 1603 1639 switch (pObj->GetType()) 1640 { 1641 case DnDURIObject::Type_Directory: 1604 const DNDTRANSFEROBJTYPE enmType = DnDTransferObjectGetType(pObj); 1605 1606 switch (enmType) 1607 { 1608 case DNDTRANSFEROBJTYPE_DIRECTORY: 1642 1609 rc = vbglR3DnDGHSendDir(pCtx, pObj); 1643 1610 break; 1644 1611 1645 case D nDURIObject::Type_File:1612 case DNDTRANSFEROBJTYPE_FILE: 1646 1613 rc = vbglR3DnDGHSendFile(pCtx, pObj); 1647 1614 break; 1648 1615 1649 1616 default: 1650 AssertMsgFailed(("Object type %ld not implemented\n", pObj->GetType()));1617 AssertMsgFailed(("Object type %ld not implemented\n", enmType)); 1651 1618 rc = VERR_NOT_IMPLEMENTED; 1652 1619 break; … … 1682 1649 /** 1683 1650 * Guest -> Host 1684 * Utility function to send URI data from guest to the host. 1685 * 1686 * @returns IPRT status code. 1687 * @param pCtx DnD context to use. 1688 * @param pvData Block to URI data to send. 1689 * @param cbData Size (in bytes) of URI data to send. 1690 */ 1691 static int vbglR3DnDGHSendURIData(PVBGLR3GUESTDNDCMDCTX pCtx, const void *pvData, size_t cbData) 1692 { 1693 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 1694 AssertPtrReturn(pvData, VERR_INVALID_POINTER); 1695 AssertReturn(cbData, VERR_INVALID_PARAMETER); 1696 1697 RTCList<RTCString> lstPaths = 1698 RTCString((const char *)pvData, cbData).split("\r\n"); 1699 1700 /** @todo Add symlink support (DNDURILIST_FLAGS_RESOLVE_SYMLINKS) here. */ 1701 /** @todo Add lazy loading (DNDURILIST_FLAGS_LAZY) here. */ 1702 uint32_t fFlags = DNDURILIST_FLAGS_KEEP_OPEN; 1703 1704 DnDURIList lstURI; 1705 int rc = lstURI.AppendURIPathsFromList(lstPaths, fFlags); 1651 * Utility function to send transfer data from guest to the host. 1652 * 1653 * @returns IPRT status code. 1654 * @param pCtx DnD context to use. 1655 * @param pTransferList Dnd transfer list to send. 1656 */ 1657 static int vbglR3DnDGHSendTransferData(PVBGLR3GUESTDNDCMDCTX pCtx, PDNDTRANSFERLIST pTransferList) 1658 { 1659 AssertPtrReturn(pCtx,VERR_INVALID_POINTER); 1660 AssertPtrReturn(pTransferList, VERR_INVALID_POINTER); 1661 1662 /* 1663 * Send the (meta) data; in case of URIs it's the root entries of a 1664 * transfer list the host needs to know upfront to set up the drag'n drop operation. 1665 */ 1666 char *pszList = NULL; 1667 size_t cbList; 1668 int rc = DnDTransferListGetRoots(pTransferList, DNDTRANSFERLISTFMT_URI, &pszList, &cbList); 1669 if (RT_FAILURE(rc)) 1670 return rc; 1671 1672 void *pvURIList = (void *)pszList; 1673 uint32_t cbURLIist = (uint32_t)cbList; 1674 1675 /* The total size also contains the size of the meta data. */ 1676 uint64_t cbTotal = cbURLIist; 1677 cbTotal += DnDTransferListObjTotalBytes(pTransferList); 1678 1679 /* We're going to send a transfer list in text format. */ 1680 const char szMetaFmt[] = "text/uri-list"; 1681 const uint32_t cbMetaFmt = (uint32_t)strlen(szMetaFmt) + 1; /* Include termination. */ 1682 1683 VBOXDNDDATAHDR dataHdr; 1684 dataHdr.uFlags = 0; /* Flags not used yet. */ 1685 dataHdr.cbTotal = cbTotal; 1686 dataHdr.cbMeta = cbURLIist; 1687 dataHdr.pvMetaFmt = (void *)szMetaFmt; 1688 dataHdr.cbMetaFmt = cbMetaFmt; 1689 dataHdr.cObjects = DnDTransferListObjCount(pTransferList); 1690 1691 rc = vbglR3DnDGHSendDataInternal(pCtx, pvURIList, cbURLIist, &dataHdr); 1692 1706 1693 if (RT_SUCCESS(rc)) 1707 1694 { 1708 /* 1709 * Send the (meta) data; in case of URIs it's the (non-recursive) file/directory 1710 * URI list the host needs to know upfront to set up the drag'n drop operation. 1711 */ 1712 RTCString strRootDest = lstURI.GetRootEntries(); 1713 if (strRootDest.isNotEmpty()) 1695 while (DnDTransferListObjCount(pTransferList)) 1714 1696 { 1715 void *pvURIList = (void *)strRootDest.c_str(); /* URI root list. */ 1716 uint32_t cbURLIist = (uint32_t)strRootDest.length() + 1; /* Include string termination. */ 1717 1718 /* The total size also contains the size of the meta data. */ 1719 uint64_t cbTotal = cbURLIist; 1720 cbTotal += lstURI.GetTotalBytes(); 1721 1722 /* We're going to send an URI list in text format. */ 1723 const char szMetaFmt[] = "text/uri-list"; 1724 const uint32_t cbMetaFmt = (uint32_t)strlen(szMetaFmt) + 1; /* Include termination. */ 1725 1726 VBOXDNDDATAHDR dataHdr; 1727 dataHdr.uFlags = 0; /* Flags not used yet. */ 1728 dataHdr.cbTotal = cbTotal; 1729 dataHdr.cbMeta = cbURLIist; 1730 dataHdr.pvMetaFmt = (void *)szMetaFmt; 1731 dataHdr.cbMetaFmt = cbMetaFmt; 1732 dataHdr.cObjects = lstURI.GetTotalCount(); 1733 1734 rc = vbglR3DnDGHSendDataInternal(pCtx, 1735 pvURIList, cbURLIist, &dataHdr); 1736 } 1737 else 1738 rc = VERR_INVALID_PARAMETER; 1739 } 1740 1741 if (RT_SUCCESS(rc)) 1742 { 1743 while (!lstURI.IsEmpty()) 1744 { 1745 DnDURIObject *pNextObj = lstURI.First(); 1746 1747 rc = vbglR3DnDGHSendURIObject(pCtx, pNextObj); 1697 PDNDTRANSFEROBJECT pObj = DnDTransferListObjGetFirst(pTransferList); 1698 1699 rc = vbglR3DnDGHSendURIObject(pCtx, pObj); 1748 1700 if (RT_FAILURE(rc)) 1749 1701 break; 1750 1702 1751 lstURI.RemoveFirst();1703 DnDTransferListObjRemoveFirst(pTransferList); 1752 1704 } 1705 1706 Assert(DnDTransferListObjCount(pTransferList) == 0); 1753 1707 } 1754 1708 … … 1779 1733 if (DnDMIMEHasFileURLs(pszFormat, strlen(pszFormat))) 1780 1734 { 1781 /* Send file data. */ 1782 rc = vbglR3DnDGHSendURIData(pCtx, pvData, cbData); 1735 DNDTRANSFERLIST lstTransfer; 1736 rc = DnDTransferListInit(&lstTransfer, NULL /* pcszRootPathAbs */); 1737 if (RT_SUCCESS(rc)) 1738 { 1739 /** @todo Add symlink support (DNDTRANSFERLIST_FLAGS_RESOLVE_SYMLINKS) here. */ 1740 /** @todo Add lazy loading (DNDTRANSFERLIST_FLAGS_LAZY) here. */ 1741 const DNDTRANSFERLISTFLAGS fFlags = DNDTRANSFERLIST_FLAGS_KEEP_OPEN; 1742 1743 rc = DnDTransferListAppendPathsFromBuffer(&lstTransfer, DNDTRANSFERLISTFMT_NATIVE, (const char *)pvData, cbData, 1744 DND_PATH_SEPARATOR, fFlags); 1745 if (RT_SUCCESS(rc)) 1746 rc = vbglR3DnDGHSendTransferData(pCtx, &lstTransfer); 1747 DnDTransferListDestroy(&lstTransfer); 1748 } 1783 1749 } 1784 1750 else
Note:
See TracChangeset
for help on using the changeset viewer.