Changeset 58212 in vbox for trunk/src/VBox/Main/src-client/GuestDnDTargetImpl.cpp
- Timestamp:
- Oct 13, 2015 11:49:33 AM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-client/GuestDnDTargetImpl.cpp
r57505 r58212 262 262 263 263 /* Determine guest DnD protocol to use. */ 264 GuestDnDBase::getProtocolVersion(&mDataBase.m ProtocolVersion);264 GuestDnDBase::getProtocolVersion(&mDataBase.m_uProtocolVersion); 265 265 266 266 /* Default action is ignoring. */ … … 302 302 { 303 303 GuestDnDMsg Msg; 304 Msg.setType( DragAndDropSvc::HOST_DND_HG_EVT_ENTER);304 Msg.setType(HOST_DND_HG_EVT_ENTER); 305 305 Msg.setNextUInt32(aScreenId); 306 306 Msg.setNextUInt32(aX); … … 376 376 { 377 377 GuestDnDMsg Msg; 378 Msg.setType( DragAndDropSvc::HOST_DND_HG_EVT_MOVE);378 Msg.setType(HOST_DND_HG_EVT_MOVE); 379 379 Msg.setNextUInt32(aScreenId); 380 380 Msg.setNextUInt32(aX); … … 418 418 419 419 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, 421 421 0 /* cParms */, NULL /* paParms */); 422 422 if (RT_SUCCESS(rc)) … … 488 488 { 489 489 GuestDnDMsg Msg; 490 Msg.setType( DragAndDropSvc::HOST_DND_HG_EVT_DROPPED);490 Msg.setType(HOST_DND_HG_EVT_DROPPED); 491 491 Msg.setNextUInt32(aScreenId); 492 492 Msg.setNextUInt32(aX); … … 545 545 AssertPtrReturn(pTask, VERR_INVALID_POINTER); 546 546 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 */); 562 557 563 558 if (pTask) 564 559 delete pTask; 565 560 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)); 567 567 return rc; 568 568 } … … 594 594 return setError(E_INVALIDARG, tr("No data to send specified")); 595 595 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")); 601 601 602 602 /* Dito. */ … … 617 617 pSendCtx->mScreenID = aScreenId; 618 618 pSendCtx->mFmtReq = aFormat; 619 pSendCtx->mData.vecData = aData; 619 620 pSendCtx->mData.getMeta().add(aData); 620 621 621 622 SendDataTask *pTask = new SendDataTask(this, pSendCtx); … … 624 625 LogFlowFunc(("Starting thread ...\n")); 625 626 626 int rc = RTThreadCreate(NULL, GuestDnDTarget::i_sendDataThread, 627 RTTHREAD threadSnd; 628 int rc = RTThreadCreate(&threadSnd, GuestDnDTarget::i_sendDataThread, 627 629 (void *)pTask, 0, RTTHREADTYPE_MAIN_WORKER, 0, "dndTgtSndData"); 628 630 if (RT_SUCCESS(rc)) 629 631 { 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); 634 644 } 635 645 else 636 646 hr = setError(VBOX_E_IPRT_ERROR, tr("Starting thread failed (%Rrc)"), rc); 637 647 638 if ( RT_FAILURE(rc))648 if (FAILED(hr)) 639 649 delete pSendCtx; 640 650 } … … 643 653 hr = setError(E_OUTOFMEMORY); 644 654 } 645 646 /* Note: mDataBase.mfTransferIsPending will be set to false again by i_sendDataThread. */647 655 648 656 LogFlowFunc(("Returning hr=%Rhrc\n", hr)); … … 662 670 663 671 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*/); 665 673 } 666 674 … … 746 754 747 755 /* Clear all remaining outgoing messages. */ 748 mDataBase.m ListOutgoing.clear();756 mDataBase.m_lstMsgOut.clear(); 749 757 750 758 /** … … 775 783 } 776 784 785 int 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 827 int 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 777 856 int GuestDnDTarget::i_sendDirectory(PSENDDATACTX pCtx, GuestDnDURIObjCtx *pObjCtx, GuestDnDMsg *pMsg) 778 857 { … … 790 869 return VERR_BUFFER_OVERFLOW; 791 870 792 Log FlowFunc(("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); 795 874 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). */ 797 876 pMsg->setNextUInt32(pObj->GetMode()); /* mode */ 798 877 … … 816 895 817 896 LogFlowFunc(("Sending file with %RU32 bytes buffer, using protocol v%RU32 ...\n", 818 mData.mcbBlockSize, mDataBase.m ProtocolVersion));897 mData.mcbBlockSize, mDataBase.m_uProtocolVersion)); 819 898 LogFlowFunc(("strPathSrc=%s, fIsOpen=%RTbool, cbSize=%RU64\n", strPathSrc.c_str(), pObj->IsOpen(), pObj->GetSize())); 820 899 … … 831 910 if (RT_SUCCESS(rc)) 832 911 { 833 if (mDataBase.m ProtocolVersion >= 2)912 if (mDataBase.m_uProtocolVersion >= 2) 834 913 { 835 914 if (!pObjCtx->fHeaderSent) … … 840 919 * The just registered callback will be called by the guest afterwards. 841 920 */ 842 pMsg->setType( DragAndDropSvc::HOST_DND_HG_SND_FILE_HDR);921 pMsg->setType(HOST_DND_HG_SND_FILE_HDR); 843 922 pMsg->setNextUInt32(0); /* uContextID */ 844 923 rc = pMsg->setNextString(pObj->GetDestPath().c_str()); /* pvName */ … … 899 978 900 979 /* Set the message type. */ 901 pMsg->setType( DragAndDropSvc::HOST_DND_HG_SND_FILE_DATA);980 pMsg->setType(HOST_DND_HG_SND_FILE_DATA); 902 981 903 982 /* Protocol version 1 sends the file path *every* time with a new file chunk. 904 983 * In protocol version 2 we only do this once with HOST_DND_HG_SND_FILE_HDR. */ 905 if (mDataBase.m ProtocolVersion <= 1)984 if (mDataBase.m_uProtocolVersion <= 1) 906 985 { 907 986 pMsg->setNextString(pObj->GetDestPath().c_str()); /* pvName */ 908 987 pMsg->setNextUInt32((uint32_t)(pObj->GetDestPath().length() + 1)); /* cbName */ 909 988 } 910 else 911 { 912 /* Protocol version 2 also sendsthe 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 */ 914 993 } 915 994 916 995 uint32_t cbRead = 0; 917 996 918 int rc = pObj->Read(pCtx->mURI. GetBufferMutable(), pCtx->mURI.GetBufferSize(), &cbRead);997 int rc = pObj->Read(pCtx->mURI.getBufferMutable(), pCtx->mURI.getBufferSize(), &cbRead); 919 998 if (RT_SUCCESS(rc)) 920 999 { 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 } 935 1020 } 936 1021 … … 961 1046 LogFlowFunc(("pThis=%p, uMsg=%RU32\n", pThis, uMsg)); 962 1047 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. */ 965 1050 bool fNotify = false; 966 1051 967 1052 switch (uMsg) 968 1053 { 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); 972 1057 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); 975 1060 976 1061 try … … 1007 1092 break; 1008 1093 } 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); 1012 1097 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); 1015 1100 1016 1101 pCtx->mpResp->reset(); … … 1022 1107 } 1023 1108 1024 rc = pCtx->mpResp->setProgress(100, D ragAndDropSvc::DND_PROGRESS_ERROR, pCBData->rc,1109 rc = pCtx->mpResp->setProgress(100, DND_PROGRESS_ERROR, pCBData->rc, 1025 1110 GuestDnDTarget::i_guestErrorToString(pCBData->rc)); 1026 1111 if (RT_SUCCESS(rc)) … … 1031 1116 break; 1032 1117 } 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 pCBData1038 = 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); 1039 1124 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); 1042 1127 1043 1128 LogFlowFunc(("pCBData->uMsg=%RU32, paParms=%p, cParms=%RU32\n", pCBData->uMsg, pCBData->paParms, pCBData->cParms)); … … 1053 1138 || pCBData->cParms != pMsg->getCount()) 1054 1139 { 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 1055 1145 /* Start over. */ 1056 1146 pThis->msgQueueClear(); … … 1141 1231 if (fNotify) 1142 1232 { 1143 int rc2 = pCtx->mC allback.Notify(rc); /** @todo Also pass guest error back? */1233 int rc2 = pCtx->mCBEvent.Notify(rc); /** @todo Also pass guest error back? */ 1144 1234 AssertRC(rc2); 1145 1235 } … … 1173 1263 } 1174 1264 1175 int rc = pCtx->mURI. Init(mData.mcbBlockSize);1265 int rc = pCtx->mURI.init(mData.mcbBlockSize); 1176 1266 if (RT_FAILURE(rc)) 1177 1267 return rc; 1178 1268 1179 rc = pCtx->mC allback.Reset();1269 rc = pCtx->mCBEvent.Reset(); 1180 1270 if (RT_FAILURE(rc)) 1181 1271 return rc; … … 1185 1275 */ 1186 1276 /* 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); 1189 1279 /* Host callbacks. */ 1190 REGISTER_CALLBACK( DragAndDropSvc::HOST_DND_HG_SND_DIR);1191 if (mDataBase.m ProtocolVersion >= 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); 1194 1284 1195 1285 do 1196 1286 { 1197 1287 /* 1198 * Extract URI list from bytedata.1288 * Extract URI list from current meta data. 1199 1289 */ 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 */ 1214 1338 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 1242 1341 if (RT_SUCCESS(rc)) 1243 1342 { 1244 rc = waitForEvent( msTimeout, pCtx->mCallback, pCtx->mpResp);1343 rc = waitForEvent(&pCtx->mCBEvent, pCtx->mpResp, msTimeout); 1245 1344 if (RT_FAILURE(rc)) 1246 1345 { 1247 1346 if (rc == VERR_CANCELLED) 1248 rc = pCtx->mpResp->setProgress(100, D ragAndDropSvc::DND_PROGRESS_CANCELLED, VINF_SUCCESS);1347 rc = pCtx->mpResp->setProgress(100, DND_PROGRESS_CANCELLED, VINF_SUCCESS); 1249 1348 else if (rc != VERR_GSTDND_GUEST_ERROR) /* Guest-side error are already handled in the callback. */ 1250 rc = pCtx->mpResp->setProgress(100, D ragAndDropSvc::DND_PROGRESS_ERROR, rc,1349 rc = pCtx->mpResp->setProgress(100, DND_PROGRESS_ERROR, rc, 1251 1350 GuestDnDTarget::i_hostErrorToString(rc)); 1252 1351 } 1253 1352 else 1254 rc = pCtx->mpResp->setProgress(100, D ragAndDropSvc::DND_PROGRESS_COMPLETE, VINF_SUCCESS);1353 rc = pCtx->mpResp->setProgress(100, DND_PROGRESS_COMPLETE, VINF_SUCCESS); 1255 1354 } 1256 1355 … … 1261 1360 */ 1262 1361 /* 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); 1265 1364 /* Host callbacks. */ 1266 UNREGISTER_CALLBACK( DragAndDropSvc::HOST_DND_HG_SND_DIR);1267 if (mDataBase.m ProtocolVersion >= 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); 1270 1369 1271 1370 #undef REGISTER_CALLBACK … … 1292 1391 { 1293 1392 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 { 1314 1401 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); 1325 1410 1326 1411 uint32_t fMode = pCurObj->GetMode(); 1327 Log FlowFunc(("ProcessingsrcPath=%s, dstPath=%s, fMode=0x%x, cbSize=%RU32, fIsDir=%RTbool, fIsFile=%RTbool\n",1328 1329 1330 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 1332 1417 if (RTFS_IS_DIRECTORY(fMode)) 1333 1418 { 1334 rc = i_sendDirectory(pCtx, pObjCtx, pMsg);1419 rc = i_sendDirectory(pCtx, &objCtx, pMsg); 1335 1420 } 1336 1421 else if (RTFS_IS_FILE(fMode)) 1337 1422 { 1338 rc = i_sendFile(pCtx, pObjCtx, pMsg);1423 rc = i_sendFile(pCtx, &objCtx, pMsg); 1339 1424 } 1340 1425 else … … 1355 1440 { 1356 1441 LogFlowFunc(("Removing \"%s\" from list, rc=%Rrc\n", pCurObj->GetSourcePath().c_str(), rc)); 1357 lstURI.RemoveFirst();1442 pCtx->mURI.removeObjCurrent(); 1358 1443 } 1359 1444 … … 1370 1455 AssertPtr(pInst); 1371 1456 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); 1391 1478 1392 1479 int rc2; 1393 1394 int rc = pInst->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms());1395 1480 if (RT_FAILURE(rc)) 1396 rc2 = pCtx->mpResp->setProgress(100, D ragAndDropSvc::DND_PROGRESS_ERROR, rc,1481 rc2 = pCtx->mpResp->setProgress(100, DND_PROGRESS_ERROR, rc, 1397 1482 GuestDnDTarget::i_hostErrorToString(rc)); 1398 1483 else 1399 rc2 = pCtx->mpResp->setProgress(100, D ragAndDropSvc::DND_PROGRESS_COMPLETE, rc);1484 rc2 = pCtx->mpResp->setProgress(100, DND_PROGRESS_COMPLETE, rc); 1400 1485 AssertRC(rc2); 1401 1486
Note:
See TracChangeset
for help on using the changeset viewer.