Changeset 85371 in vbox for trunk/src/VBox/Main/src-client/GuestDnDTargetImpl.cpp
- Timestamp:
- Jul 17, 2020 10:02:58 AM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-client/GuestDnDTargetImpl.cpp
r85020 r85371 563 563 } 564 564 565 /** 566 * Thread handler function for sending data to the guest. 567 * 568 * @param pTask Thread task this handler is associated with. 569 */ 565 570 /* static */ 566 571 void GuestDnDTarget::i_sendDataThreadTask(GuestDnDSendDataTask *pTask) … … 593 598 594 599 /** 595 * Initiates a data transfer from the host to the guest. The source is the host whereas the target is the 596 * guest in this case. 600 * Initiates a data transfer from the host to the guest. 601 * 602 * The source is the host, whereas the target is the guest. 597 603 * 598 604 * @return HRESULT 599 * @param aScreenId 600 * @param aFormat 601 * @param aData 602 * @param aProgress 605 * @param aScreenId Screen ID where this data transfer was initiated from. 606 * @param aFormat Format of data to send. MIME-style. 607 * @param aData Actual data to send. 608 * @param aProgress Where to return the progress object on success. 603 609 */ 604 610 HRESULT GuestDnDTarget::sendData(ULONG aScreenId, const com::Utf8Str &aFormat, const std::vector<BYTE> &aData, … … 632 638 return hr; 633 639 634 GuestDnDSendDataTask *pTask = NULL;635 GuestDnDSendCtx *pSendCtx = NULL;640 GuestDnDSendDataTask *pTask = NULL; 641 GuestDnDSendCtx *pSendCtx = NULL; 636 642 637 643 try 638 644 { 639 / /pSendCtx is passed into SendDataTask where one is deleted in destructor645 /* pSendCtx is passed into SendDataTask where one is deleted in destructor. */ 640 646 pSendCtx = new GuestDnDSendCtx(); 641 pSendCtx->mpTarget = this; 642 pSendCtx->mpResp = pResp; 643 pSendCtx->mScreenID = aScreenId; 644 pSendCtx->mFmtReq = aFormat; 645 pSendCtx->mData.getMeta().add(aData); 647 pSendCtx->mpTarget = this; 648 pSendCtx->mpResp = pResp; 649 pSendCtx->mScreenID = aScreenId; 650 pSendCtx->mFmtReq = aFormat; 651 652 pSendCtx->Meta.add(aData); 646 653 647 654 /* pTask is responsible for deletion of pSendCtx after creating */ … … 757 764 758 765 /** 759 * @returns VBox status code that the caller ignores. Not sure if that's 760 * intentional or not. 766 * Main function for sending DnD host data to the guest. 767 * 768 * @returns VBox status code. 769 * @param pCtx Send context to use. 770 * @param msTimeout Timeout (in ms) to wait for getting the data sent. 761 771 */ 762 772 int GuestDnDTarget::i_sendData(GuestDnDSendCtx *pCtx, RTMSINTERVAL msTimeout) … … 776 786 * Note: The decision whether we need to build up a file tree and sending 777 787 * actual file data only depends on the actual formats offered by this target. 778 * If the guest does not want a n URIlist ("text/uri-list") but text ("TEXT" and788 * If the guest does not want a transfer list ("text/uri-list") but text ("TEXT" and 779 789 * friends) instead, still send the data over to the guest -- the file as such still 780 790 * is needed on the guest in this case, as the guest then just wants a simple path 781 * instead of a n URIlist (pointing to a file on the guest itself).791 * instead of a transfer list (pointing to a file on the guest itself). 782 792 * 783 793 ** @todo Support more than one format; add a format<->function handler concept. Later. */ … … 787 797 if (fHasURIList) 788 798 { 789 rc = i_send URIData(pCtx, msTimeout);799 rc = i_sendTransferData(pCtx, msTimeout); 790 800 } 791 801 else … … 800 810 } 801 811 802 int GuestDnDTarget::i_sendDataBody(GuestDnDSendCtx *pCtx, GuestDnDData *pData) 803 { 804 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 805 AssertPtrReturn(pData, VERR_INVALID_POINTER); 812 /** 813 * Sends the common meta data body to the guest. 814 * 815 * @returns VBox status code. 816 * @param pCtx Send context to use. 817 */ 818 int GuestDnDTarget::i_sendMetaDataBody(GuestDnDSendCtx *pCtx) 819 { 820 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 806 821 807 822 /** @todo Add support for multiple HOST_DND_HG_SND_DATA messages in case of more than 64K data! */ 808 if (p Data->getMeta().getSize()> _64K)823 if (pCtx->Meta.cbData > _64K) 809 824 return VERR_NOT_IMPLEMENTED; 810 825 826 const uint32_t cbFmt = (uint32_t)pCtx->Meta.strFmt.length() + 1; /* Include terminator. */ 827 828 LogFlowFunc(("cbFmt=%RU32, cbMeta=%RU32\n", cbFmt, pCtx->Meta.cbData)); 829 811 830 GuestDnDMsg Msg; 812 813 LogFlowFunc(("cbFmt=%RU32, cbMeta=%RU32, cbChksum=%RU32\n",814 pData->getFmtSize(), pData->getMeta().getSize(), pData->getChkSumSize()));815 816 831 Msg.setType(HOST_DND_HG_SND_DATA); 817 832 if (mDataBase.m_uProtocolVersion < 3) 818 833 { 819 Msg.setNextUInt32(pCtx->mScreenID); 820 Msg.setNextPointer(p Data->getFmtMutable(), pData->getFmtSize());/* pvFormat */821 Msg.setNextUInt32( pData->getFmtSize());/* cbFormat */822 Msg.setNextPointer(p Data->getMeta().getDataMutable(), pData->getMeta().getSize()); /* pvData */834 Msg.setNextUInt32(pCtx->mScreenID); /* uScreenId */ 835 Msg.setNextPointer(pCtx->Meta.strFmt.mutableRaw(), cbFmt); /* pvFormat */ 836 Msg.setNextUInt32(cbFmt); /* cbFormat */ 837 Msg.setNextPointer(pCtx->Meta.pvData, (uint32_t)pCtx->Meta.cbData); /* pvData */ 823 838 /* Fill in the current data block size to send. 824 839 * Note: Only supports uint32_t. */ 825 Msg.setNextUInt32((uint32_t)p Data->getMeta().getSize());/* cbData */840 Msg.setNextUInt32((uint32_t)pCtx->Meta.cbData); /* cbData */ 826 841 } 827 842 else 828 843 { 829 844 Msg.setNextUInt32(0); /** @todo ContextID not used yet. */ 830 Msg.setNextPointer(p Data->getMeta().getDataMutable(), pData->getMeta().getSize()); /* pvData */831 Msg.setNextUInt32( pData->getMeta().getSize());/* cbData */832 Msg.setNextPointer( pData->getChkSumMutable(), pData->getChkSumSize());/** @todo pvChecksum; not used yet. */833 Msg.setNextUInt32( pData->getChkSumSize());/** @todo cbChecksum; not used yet. */845 Msg.setNextPointer(pCtx->Meta.pvData, (uint32_t)pCtx->Meta.cbData); /* pvData */ 846 Msg.setNextUInt32((uint32_t)pCtx->Meta.cbData); /* cbData */ 847 Msg.setNextPointer(NULL, 0); /** @todo pvChecksum; not used yet. */ 848 Msg.setNextUInt32(0); /** @todo cbChecksum; not used yet. */ 834 849 } 835 850 836 851 int rc = GUESTDNDINST()->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms()); 837 852 if (RT_SUCCESS(rc)) 838 rc = updateProgress(pData, pCtx->mpResp, pData->getMeta().getSize()); 853 { 854 rc = updateProgress(pCtx, pCtx->mpResp, pCtx->Meta.cbData); 855 AssertRC(rc); 856 } 839 857 840 858 LogFlowFuncLeaveRC(rc); … … 842 860 } 843 861 844 int GuestDnDTarget::i_sendDataHeader(GuestDnDSendCtx *pCtx, GuestDnDData *pData, GuestDnDURIData *pURIData /* = NULL */) 845 { 846 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 847 AssertPtrReturn(pData, VERR_INVALID_POINTER); 848 /* pURIData is optional. */ 862 /** 863 * Sends the common meta data header to the guest. 864 * 865 * @returns VBox status code. 866 * @param pCtx Send context to use. 867 */ 868 int GuestDnDTarget::i_sendMetaDataHeader(GuestDnDSendCtx *pCtx) 869 { 870 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 871 872 if (mDataBase.m_uProtocolVersion < 3) /* Protocol < v3 did not support this, skip. */ 873 return VINF_SUCCESS; 849 874 850 875 GuestDnDMsg Msg; … … 855 880 Msg.setNextUInt32(0); /** @todo uFlags; not used yet. */ 856 881 Msg.setNextUInt32(pCtx->mScreenID); /* uScreen */ 857 Msg.setNextUInt64(p Data->getTotal());/* cbTotal */858 Msg.setNextUInt32(p Data->getMeta().getSize());/* cbMeta*/859 Msg.setNextPointer( pData->getFmtMutable(), pData->getFmtSize());/* pvMetaFmt */860 Msg.setNextUInt32( pData->getFmtSize());/* cbMetaFmt */861 Msg.setNextUInt64(p URIData ? pURIData->getObjToProcess() : 0);/* cObjects */882 Msg.setNextUInt64(pCtx->getTotal()); /* cbTotal */ 883 Msg.setNextUInt32(pCtx->Meta.cbData); /* cbMeta*/ 884 Msg.setNextPointer(unconst(pCtx->Meta.strFmt.c_str()), (uint32_t)pCtx->Meta.strFmt.length() + 1); /* pvMetaFmt */ 885 Msg.setNextUInt32((uint32_t)pCtx->Meta.strFmt.length() + 1); /* cbMetaFmt */ 886 Msg.setNextUInt64(pCtx->mTransfer.cObjToProcess ); /* cObjects */ 862 887 Msg.setNextUInt32(0); /** @todo enmCompression; not used yet. */ 863 888 Msg.setNextUInt32(0); /** @todo enmChecksumType; not used yet. */ … … 871 896 } 872 897 873 int GuestDnDTarget::i_sendDirectory(GuestDnDSendCtx *pCtx, GuestDnDURIObjCtx *pObjCtx, GuestDnDMsg *pMsg) 874 { 875 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 876 AssertPtrReturn(pObjCtx, VERR_INVALID_POINTER); 877 AssertPtrReturn(pMsg, VERR_INVALID_POINTER); 878 879 DnDURIObject *pObj = pObjCtx->getObj(); 880 AssertPtr(pObj); 881 882 RTCString strPath = pObj->GetPath(); 883 if (strPath.isEmpty()) 884 return VERR_INVALID_PARAMETER; 885 if (strPath.length() >= RTPATH_MAX) /* Note: Maximum is RTPATH_MAX on guest side. */ 886 return VERR_BUFFER_OVERFLOW; 887 888 LogRel2(("DnD: Transferring host directory '%s' to guest\n", strPath.c_str())); 898 int GuestDnDTarget::i_sendDirectory(GuestDnDSendCtx *pCtx, PDNDTRANSFEROBJECT pObj, GuestDnDMsg *pMsg) 899 { 900 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 901 AssertPtrReturn(pMsg, VERR_INVALID_POINTER); 902 903 const char *pcszDstPath = DnDTransferObjectGetDestPath(pObj); 904 AssertPtrReturn(pcszDstPath, VERR_INVALID_POINTER); 905 const size_t cchPath = RTStrNLen(pcszDstPath, RTPATH_MAX); /* Note: Maximum is RTPATH_MAX on guest side. */ 906 AssertReturn(cchPath, VERR_INVALID_PARAMETER); 907 908 LogRel2(("DnD: Transferring host directory '%s' to guest\n", DnDTransferObjectGetSourcePath(pObj))); 889 909 890 910 pMsg->setType(HOST_DND_HG_SND_DIR); 891 911 if (mDataBase.m_uProtocolVersion >= 3) 892 912 pMsg->setNextUInt32(0); /** @todo ContextID not used yet. */ 893 pMsg->setNextString( strPath.c_str());/* path */894 pMsg->setNextUInt32((uint32_t)( strPath.length() + 1)); /* path length (maximum is RTPATH_MAX on guest side). */895 pMsg->setNextUInt32( pObj->GetMode());/* mode */913 pMsg->setNextString(pcszDstPath); /* path */ 914 pMsg->setNextUInt32((uint32_t)(cchPath + 1)); /* path length, including terminator. */ 915 pMsg->setNextUInt32(DnDTransferObjectGetMode(pObj)); /* mode */ 896 916 897 917 return VINF_SUCCESS; 898 918 } 899 919 900 int GuestDnDTarget::i_sendFile(GuestDnDSendCtx *pCtx, GuestDnDURIObjCtx *pObjCtx, GuestDnDMsg *pMsg) 901 { 902 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 903 AssertPtrReturn(pObjCtx, VERR_INVALID_POINTER); 904 AssertPtrReturn(pMsg, VERR_INVALID_POINTER); 905 906 DnDURIObject *pObj = pObjCtx->getObj(); 907 AssertPtr(pObj); 908 909 RTCString strPathSrc = pObj->GetPath(); 910 if (strPathSrc.isEmpty()) 911 return VERR_INVALID_PARAMETER; 920 /** 921 * Sends a transfer file to the guest. 922 * 923 * @returns VBox status code. 924 * @param pCtx 925 * @param pObj 926 * @param pMsg 927 */ 928 int GuestDnDTarget::i_sendFile(GuestDnDSendCtx *pCtx, 929 PDNDTRANSFEROBJECT pObj, GuestDnDMsg *pMsg) 930 { 931 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 932 AssertPtrReturn(pObj, VERR_INVALID_POINTER); 933 AssertPtrReturn(pMsg, VERR_INVALID_POINTER); 934 935 const char *pcszSrcPath = DnDTransferObjectGetSourcePath(pObj); 936 AssertPtrReturn(pcszSrcPath, VERR_INVALID_POINTER); 937 const char *pcszDstPath = DnDTransferObjectGetDestPath(pObj); 938 AssertPtrReturn(pcszDstPath, VERR_INVALID_POINTER); 912 939 913 940 int rc = VINF_SUCCESS; 914 941 915 LogFlowFunc(("Sending file with %RU32 bytes buffer, using protocol v%RU32 ...\n", 916 mData.mcbBlockSize, mDataBase.m_uProtocolVersion)); 917 LogFlowFunc(("strPathSrc=%s, fIsOpen=%RTbool, cbSize=%RU64\n", strPathSrc.c_str(), pObj->IsOpen(), pObj->GetSize())); 918 919 if (!pObj->IsOpen()) 920 { 921 LogRel2(("DnD: Opening host file '%s' for transferring to guest\n", strPathSrc.c_str())); 922 rc = pObj->Init(DnDURIObject::Type_File, strPathSrc); 923 if (RT_SUCCESS(rc)) 924 rc = pObj->Open(RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE); 925 942 if (!DnDTransferObjectIsOpen(pObj)) 943 { 944 LogRel2(("DnD: Opening host file '%s' for transferring to guest\n", pcszSrcPath)); 945 946 rc = DnDTransferObjectOpen(pObj, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE, 0 /* fMode */, 947 DNDTRANSFEROBJECT_FLAGS_NONE); 926 948 if (RT_FAILURE(rc)) 927 LogRel(("DnD: Opening host file '%s' failed, rc=%Rrc\n", strPathSrc.c_str(), rc)); 928 } 949 LogRel(("DnD: Opening host file '%s' failed, rc=%Rrc\n", pcszSrcPath, rc)); 950 } 951 952 if (RT_FAILURE(rc)) 953 return rc; 929 954 930 955 bool fSendData = false; … … 933 958 if (mDataBase.m_uProtocolVersion >= 2) 934 959 { 935 uint32_t fState = pObjCtx->getState(); 936 if (!(fState & DND_OBJCTX_STATE_HAS_HDR)) 960 if (!(pCtx->mTransfer.mfObjState & DND_OBJ_STATE_HAS_HDR)) 937 961 { 962 const size_t cchDstPath = RTStrNLen(pcszDstPath, RTPATH_MAX); 963 const size_t cbSize = DnDTransferObjectGetSize(pObj); 964 const RTFMODE fMode = DnDTransferObjectGetMode(pObj); 965 938 966 /* 939 967 * Since protocol v2 the file header and the actual file contents are … … 943 971 pMsg->setType(HOST_DND_HG_SND_FILE_HDR); 944 972 pMsg->setNextUInt32(0); /** @todo ContextID not used yet. */ 945 pMsg->setNextString(pObj->GetPath().c_str()); /* pvName */ 946 pMsg->setNextUInt32((uint32_t)(pObj->GetPath().length() + 1)); /* cbName */ 947 pMsg->setNextUInt32(0); /* uFlags */ 948 pMsg->setNextUInt32(pObj->GetMode()); /* fMode */ 949 pMsg->setNextUInt64(pObj->GetSize()); /* uSize */ 950 951 LogFlowFunc(("Sending file header ...\n")); 952 LogRel2(("DnD: Transferring host file '%s' to guest (%RU64 bytes, mode 0x%x)\n", 953 pObj->GetPath().c_str(), pObj->GetSize(), pObj->GetMode())); 973 pMsg->setNextString(pcszDstPath); /* pvName */ 974 pMsg->setNextUInt32((uint32_t)(cchDstPath + 1)); /* cbName */ 975 pMsg->setNextUInt32(0); /* uFlags */ 976 pMsg->setNextUInt32(fMode); /* fMode */ 977 pMsg->setNextUInt64(cbSize); /* uSize */ 978 979 LogRel2(("DnD: Transferring host file '%s' to guest (%zu bytes, mode %#x)\n", 980 pcszSrcPath, cbSize, fMode)); 954 981 955 982 /** @todo Set progress object title to current file being transferred? */ 956 983 957 pObjCtx->setState(fState | DND_OBJCTX_STATE_HAS_HDR); 984 /* Update object state to reflect that we have sent the file header. */ 985 pCtx->mTransfer.mfObjState |= DND_OBJ_STATE_HAS_HDR; 958 986 } 959 987 else … … 973 1001 && fSendData) 974 1002 { 975 rc = i_sendFileData(pCtx, pObj Ctx, pMsg);1003 rc = i_sendFileData(pCtx, pObj, pMsg); 976 1004 } 977 1005 978 1006 if (RT_FAILURE(rc)) 979 LogRel(("DnD: Sending host file to guest failed, rc=%Rrc\n", rc));1007 LogRel(("DnD: Sending host file '%s' to guest failed, rc=%Rrc\n", pcszSrcPath, rc)); 980 1008 981 1009 LogFlowFuncLeaveRC(rc); … … 983 1011 } 984 1012 985 int GuestDnDTarget::i_sendFileData(GuestDnDSendCtx *pCtx, GuestDnDURIObjCtx *pObjCtx, GuestDnDMsg *pMsg) 986 { 987 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 988 AssertPtrReturn(pObjCtx, VERR_INVALID_POINTER); 989 AssertPtrReturn(pMsg, VERR_INVALID_POINTER); 990 991 DnDURIObject *pObj = pObjCtx->getObj(); 992 AssertPtr(pObj); 993 994 AssertPtr(pCtx->mpResp); 1013 int GuestDnDTarget::i_sendFileData(GuestDnDSendCtx *pCtx, 1014 PDNDTRANSFEROBJECT pObj, GuestDnDMsg *pMsg) 1015 { 1016 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 1017 AssertPtrReturn(pObj, VERR_INVALID_POINTER); 1018 AssertPtrReturn(pMsg, VERR_INVALID_POINTER); 1019 1020 AssertPtrReturn(pCtx->mpResp, VERR_WRONG_ORDER); 995 1021 996 1022 /** @todo Don't allow concurrent reads per context! */ 997 998 /*999 * Start sending stuff.1000 */1001 1023 1002 1024 /* Set the message type. */ 1003 1025 pMsg->setType(HOST_DND_HG_SND_FILE_DATA); 1026 1027 const char *pcszSrcPath = DnDTransferObjectGetSourcePath(pObj); 1028 const char *pcszDstPath = DnDTransferObjectGetDestPath(pObj); 1004 1029 1005 1030 /* Protocol version 1 sends the file path *every* time with a new file chunk. … … 1007 1032 if (mDataBase.m_uProtocolVersion <= 1) 1008 1033 { 1009 pMsg->setNextString(pObj->GetPath().c_str()); /* pvName */ 1010 pMsg->setNextUInt32((uint32_t)(pObj->GetPath().length() + 1)); /* cbName */ 1034 const size_t cchDstPath = RTStrNLen(pcszDstPath, RTPATH_MAX); 1035 1036 pMsg->setNextString(pcszDstPath); /* pvName */ 1037 pMsg->setNextUInt32((uint32_t)cchDstPath + 1); /* cbName */ 1011 1038 } 1012 1039 else if (mDataBase.m_uProtocolVersion >= 2) 1013 1040 { 1014 pMsg->setNextUInt32(0); /** @todo ContextID not used yet. */ 1015 } 1016 1017 uint32_t cbRead = 0; 1018 1019 int rc = pObj->Read(pCtx->mURI.getBufferMutable(), pCtx->mURI.getBufferSize(), &cbRead); 1041 pMsg->setNextUInt32(0); /** @todo ContextID not used yet. */ 1042 } 1043 1044 void *pvBuf = pCtx->mTransfer.pvScratchBuf; 1045 AssertPtr(pvBuf); 1046 size_t cbBuf = pCtx->mTransfer.cbScratchBuf; 1047 Assert(cbBuf); 1048 1049 uint32_t cbRead; 1050 1051 int rc = DnDTransferObjectRead(pObj, pvBuf, cbBuf, &cbRead); 1020 1052 if (RT_SUCCESS(rc)) 1021 1053 { 1022 pCtx->mData.addProcessed(cbRead); 1023 LogFlowFunc(("cbBufSize=%zu, cbRead=%RU32\n", pCtx->mURI.getBufferSize(), cbRead)); 1054 pCtx->addProcessed(cbRead); 1055 1056 LogFlowFunc(("cbBufe=%zu, cbRead=%RU32\n", cbBuf, cbRead)); 1024 1057 1025 1058 if (mDataBase.m_uProtocolVersion <= 1) 1026 1059 { 1027 pMsg->setNextPointer(p Ctx->mURI.getBufferMutable(), cbRead);/* pvData */1060 pMsg->setNextPointer(pvBuf, cbRead); /* pvData */ 1028 1061 pMsg->setNextUInt32(cbRead); /* cbData */ 1029 pMsg->setNextUInt32( pObj->GetMode());/* fMode */1062 pMsg->setNextUInt32(DnDTransferObjectGetMode(pObj)); /* fMode */ 1030 1063 } 1031 1064 else /* Protocol v2 and up. */ 1032 1065 { 1033 pMsg->setNextPointer(p Ctx->mURI.getBufferMutable(), cbRead);/* pvData */1066 pMsg->setNextPointer(pvBuf, cbRead); /* pvData */ 1034 1067 pMsg->setNextUInt32(cbRead); /* cbData */ 1035 1068 … … 1042 1075 } 1043 1076 1044 if (pObj->IsComplete()) /* Done reading? */ 1045 { 1046 LogRel2(("DnD: Transferring file '%s' to guest complete\n", pObj->GetPath().c_str())); 1047 LogFlowFunc(("File '%s' complete\n", pObj->GetPath().c_str())); 1048 1049 /* DnDURIObject::Read() returns VINF_EOF when finished reading the entire fire, 1050 * but we don't want this here -- so just override this with VINF_SUCCESS. */ 1077 if (DnDTransferObjectIsComplete(pObj)) /* Done reading? */ 1078 { 1079 LogRel2(("DnD: Transferring host file '%s' to guest complete\n", pcszSrcPath)); 1080 1081 /* DnDTransferObjectRead() returns VINF_EOF when finished reading the entire file, 1082 * but we don't want this here -- so just set VINF_SUCCESS. */ 1051 1083 rc = VINF_SUCCESS; 1052 1084 } 1053 1085 } 1054 1055 if (RT_FAILURE(rc)) 1056 LogRel(("DnD: Reading from host file '%s' failed, rc=%Rrc\n", pObj->GetPath().c_str(), rc)); 1086 else 1087 LogRel(("DnD: Reading from host file '%s' failed, rc=%Rrc\n", pcszSrcPath, rc)); 1057 1088 1058 1089 LogFlowFuncLeaveRC(rc); … … 1096 1127 GuestDnDMsg *pMsg = new GuestDnDMsg(); 1097 1128 1098 rc = pThis->i_send URIDataLoop(pCtx, pMsg);1129 rc = pThis->i_sendTransferDataLoop(pCtx, pMsg); 1099 1130 if (rc == VINF_EOF) /* Transfer complete? */ 1100 1131 { … … 1272 1303 } 1273 1304 1274 int GuestDnDTarget::i_sendURIData(GuestDnDSendCtx *pCtx, RTMSINTERVAL msTimeout) 1305 /** 1306 * Main function for sending the actual transfer data (i.e. files + directories) to the guest. 1307 * 1308 * @returns VBox status code. 1309 * @param pCtx Send context to use. 1310 * @param msTimeout Timeout (in ms) to use for getting the data sent. 1311 */ 1312 int GuestDnDTarget::i_sendTransferData(GuestDnDSendCtx *pCtx, RTMSINTERVAL msTimeout) 1275 1313 { 1276 1314 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); … … 1290 1328 } while (0) 1291 1329 1292 int rc = pCtx->m URI.init(mData.mcbBlockSize);1330 int rc = pCtx->mTransfer.init(mData.mcbBlockSize); 1293 1331 if (RT_FAILURE(rc)) 1294 1332 return rc; … … 1315 1353 { 1316 1354 /* 1317 * Extract URIlist from current meta data.1355 * Extract transfer list from current meta data. 1318 1356 */ 1319 GuestDnDData *pData = &pCtx->mData; 1320 GuestDnDURIData *pURI = &pCtx->mURI; 1321 1322 rc = pURI->fromLocalMetaData(pData->getMeta()); 1357 rc = DnDTransferListAppendPathsFromBuffer(&pCtx->mTransfer.mList, DNDTRANSFERLISTFMT_NATIVE, 1358 (const char *)pCtx->Meta.pvData, pCtx->Meta.cbData, "\n", DNDTRANSFERLIST_FLAGS_NONE); 1323 1359 if (RT_FAILURE(rc)) 1324 1360 break; 1325 1361 1326 LogFlowFunc(("URI root objects: %zu, total bytes (raw data to transfer): %zu\n",1327 pURI->getURIList().GetRootCount(), pURI->getURIList().GetTotalBytes()));1328 1329 1362 /* 1330 * Set the new meta data with the URI list in it.1363 * Set the extra data size 1331 1364 */ 1332 rc = pData->getMeta().fromURIList(pURI->getURIList()); 1333 if (RT_FAILURE(rc)) 1334 break; 1335 1336 /* 1337 * Set the estimated data sizes we are going to send. 1338 * The total size also contains the meta data size. 1339 */ 1340 const uint32_t cbMeta = pData->getMeta().getSize(); 1341 pData->setEstimatedSize(pURI->getURIList().GetTotalBytes() + cbMeta /* cbTotal */, 1342 cbMeta /* cbMeta */); 1343 1344 /* 1345 * Set the meta format. 1346 */ 1347 void *pvFmt = (void *)pCtx->mFmtReq.c_str(); 1348 uint32_t cbFmt = (uint32_t)pCtx->mFmtReq.length() + 1; /* Include terminating zero. */ 1349 1350 pData->setFmt(pvFmt, cbFmt); 1365 pCtx->cbExtra = DnDTransferListObjTotalBytes(&pCtx->mTransfer.mList); 1351 1366 1352 1367 /* 1353 1368 * The first message always is the data header. The meta data itself then follows 1354 * and *only* contains the root elements of a n URIlist.1369 * and *only* contains the root elements of a transfer list. 1355 1370 * 1356 1371 * After the meta data we generate the messages required to send the … … 1365 1380 */ 1366 1381 if (mDataBase.m_uProtocolVersion >= 3) 1367 rc = i_send DataHeader(pCtx, pData, &pCtx->mURI);1382 rc = i_sendMetaDataHeader(pCtx); 1368 1383 1369 1384 /* … … 1371 1386 */ 1372 1387 if (RT_SUCCESS(rc)) 1373 rc = i_send DataBody(pCtx, pData);1388 rc = i_sendMetaDataBody(pCtx); 1374 1389 1375 1390 if (RT_SUCCESS(rc)) … … 1411 1426 AssertRC(rc2); 1412 1427 1428 LogRel2(("DnD: Sending transfer data to guest cancelled by user\n")); 1429 1413 1430 rc2 = pCtx->mpResp->setProgress(100, DND_PROGRESS_CANCELLED, VINF_SUCCESS); 1414 1431 AssertRC(rc2); … … 1416 1433 else if (rc != VERR_GSTDND_GUEST_ERROR) /* Guest-side error are already handled in the callback. */ 1417 1434 { 1435 LogRel(("DnD: Sending transfer data to guest failed with rc=%Rrc\n", rc)); 1418 1436 int rc2 = pCtx->mpResp->setProgress(100, DND_PROGRESS_ERROR, rc, 1419 1437 GuestDnDTarget::i_hostErrorToString(rc)); … … 1428 1446 } 1429 1447 1430 int GuestDnDTarget::i_send URIDataLoop(GuestDnDSendCtx *pCtx, GuestDnDMsg *pMsg)1448 int GuestDnDTarget::i_sendTransferDataLoop(GuestDnDSendCtx *pCtx, GuestDnDMsg *pMsg) 1431 1449 { 1432 1450 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 1433 1451 AssertPtrReturn(pMsg, VERR_INVALID_POINTER); 1434 1452 1435 int rc = updateProgress( &pCtx->mData, pCtx->mpResp);1453 int rc = updateProgress(pCtx, pCtx->mpResp); 1436 1454 AssertRC(rc); 1437 1455 1438 if ( pCtx-> mData.isComplete()1439 && pCtx->m URI.isComplete())1456 if ( pCtx->isComplete() 1457 && pCtx->mTransfer.isComplete()) 1440 1458 { 1441 1459 return VINF_EOF; 1442 1460 } 1443 1461 1444 GuestDnDURIObjCtx &objCtx = pCtx->mURI.getObjCurrent();1445 if (! objCtx.isValid())1462 PDNDTRANSFEROBJECT pObj = DnDTransferListObjGetFirst(&pCtx->mTransfer.mList); 1463 if (!pObj) 1446 1464 return VERR_WRONG_ORDER; 1447 1465 1448 DnDURIObject *pCurObj = objCtx.getObj(); 1449 AssertPtr(pCurObj); 1450 1451 const DnDURIObject::Type enmType = pCurObj->GetType(); 1452 1453 LogRel3(("DnD: Processing: srcPath=%s, dstPath=%s, enmType=%RU32, cbSize=%RU32\n", 1454 pCurObj->GetPath().c_str(), pCurObj->GetPath().c_str(), 1455 enmType, pCurObj->GetSize())); 1456 1457 if (enmType == DnDURIObject::Type_Directory) 1458 { 1459 rc = i_sendDirectory(pCtx, &objCtx, pMsg); 1460 } 1461 else if (DnDURIObject::Type_File) 1462 { 1463 rc = i_sendFile(pCtx, &objCtx, pMsg); 1464 } 1465 else 1466 { 1467 AssertMsgFailed(("enmType=%RU32 is not supported for srcPath=%s, dstPath=%s\n", 1468 enmType, pCurObj->GetPath().c_str(), pCurObj->GetPath().c_str())); 1469 rc = VERR_NOT_SUPPORTED; 1470 } 1471 1472 bool fRemove = false; /* Remove current entry? */ 1473 if ( pCurObj->IsComplete() 1466 switch (DnDTransferObjectGetType(pObj)) 1467 { 1468 case DNDTRANSFEROBJTYPE_DIRECTORY: 1469 rc = i_sendDirectory(pCtx, pObj, pMsg); 1470 break; 1471 1472 case DNDTRANSFEROBJTYPE_FILE: 1473 rc = i_sendFile(pCtx, pObj, pMsg); 1474 break; 1475 1476 default: 1477 AssertFailedStmt(rc = VERR_NOT_SUPPORTED); 1478 break; 1479 } 1480 1481 if ( DnDTransferObjectIsComplete(pObj) 1474 1482 || RT_FAILURE(rc)) 1475 { 1476 fRemove = true; 1477 } 1478 1479 if (fRemove) 1480 { 1481 LogFlowFunc(("Removing \"%s\" from list, rc=%Rrc\n", pCurObj->GetPath().c_str(), rc)); 1482 pCtx->mURI.removeObjCurrent(); 1483 } 1483 DnDTransferListObjRemoveFirst(&pCtx->mTransfer.mList); 1484 1484 1485 1485 LogFlowFuncLeaveRC(rc); … … 1487 1487 } 1488 1488 1489 /** 1490 * Main function for sending raw data (e.g. text, RTF, ...) to the guest. 1491 * 1492 * @returns VBox status code. 1493 * @param pCtx Send context to use. 1494 * @param msTimeout Timeout (in ms) to use for getting the data sent. 1495 */ 1489 1496 int GuestDnDTarget::i_sendRawData(GuestDnDSendCtx *pCtx, RTMSINTERVAL msTimeout) 1490 1497 { 1491 1498 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 1492 1499 NOREF(msTimeout); 1493 1494 GuestDnDData *pData = &pCtx->mData;1495 1500 1496 1501 /** @todo At the moment we only allow sending up to 64K raw data. 1497 1502 * For protocol v1+v2: Fix this by using HOST_DND_HG_SND_MORE_DATA. 1498 1503 * For protocol v3 : Send another HOST_DND_HG_SND_DATA message. */ 1499 if (!p Data->getMeta().getSize())1504 if (!pCtx->Meta.cbData) 1500 1505 return VINF_SUCCESS; 1501 1506 1502 int rc = VINF_SUCCESS; 1503 1504 /* 1505 * Send the data header first. 1506 */ 1507 if (mDataBase.m_uProtocolVersion >= 3) 1508 rc = i_sendDataHeader(pCtx, pData, NULL /* URI list */); 1509 1510 /* 1511 * Send the (meta) data body. 1512 */ 1507 int rc = i_sendMetaDataHeader(pCtx); 1513 1508 if (RT_SUCCESS(rc)) 1514 rc = i_send DataBody(pCtx, pData);1509 rc = i_sendMetaDataBody(pCtx); 1515 1510 1516 1511 int rc2; 1517 1512 if (RT_FAILURE(rc)) 1518 rc2 = pCtx->mpResp->setProgress(100, DND_PROGRESS_ERROR, rc, 1513 { 1514 LogRel(("DnD: Sending raw data to guest failed with rc=%Rrc\n", rc)); 1515 rc2 = pCtx->mpResp->setProgress(100 /* Percent */, DND_PROGRESS_ERROR, rc, 1519 1516 GuestDnDTarget::i_hostErrorToString(rc)); 1517 } 1520 1518 else 1521 rc2 = pCtx->mpResp->setProgress(100 , DND_PROGRESS_COMPLETE, rc);1519 rc2 = pCtx->mpResp->setProgress(100 /* Percent */, DND_PROGRESS_COMPLETE, rc); 1522 1520 AssertRC(rc2); 1523 1521 … … 1526 1524 } 1527 1525 1526 /** 1527 * Cancels sending DnD data. 1528 * 1529 * @returns VBox status code. 1530 * @param aVeto Whether cancelling was vetoed or not. 1531 * Not implemented yet. 1532 */ 1528 1533 HRESULT GuestDnDTarget::cancel(BOOL *aVeto) 1529 1534 { … … 1532 1537 #else /* VBOX_WITH_DRAG_AND_DROP */ 1533 1538 1539 LogRel2(("DnD: Sending cancelling request to the guest ...\n")); 1540 1534 1541 int rc = GuestDnDBase::sendCancel(); 1535 1542 1536 1543 if (aVeto) 1537 *aVeto = FALSE; /** @todo */1544 *aVeto = FALSE; /** @todo Impplement vetoing. */ 1538 1545 1539 1546 HRESULT hr = RT_SUCCESS(rc) ? S_OK : VBOX_E_IPRT_ERROR;
Note:
See TracChangeset
for help on using the changeset viewer.