- Timestamp:
- Apr 30, 2015 5:04:37 PM (10 years ago)
- svn:sync-xref-src-repo-rev:
- 99943
- Location:
- trunk/src/VBox
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnD.cpp
r55422 r55571 1424 1424 /* 1425 1425 * Note: Don't clear this->lstAllowedFormats at the moment, as this value is initialized 1426 * on class creation. We might later want to modify the allowed formats inruntime,1426 * on class creation. We might later want to modify the allowed formats at runtime, 1427 1427 * so keep this in mind when implementing this. 1428 1428 */ … … 1665 1665 * don't support the stuff we do on the guest side, so make sure we 1666 1666 * don't process invalid messages forever. */ 1667 if (cMsgSkippedInvalid++ > 3) 1667 if (rc == VERR_INVALID_PARAMETER) 1668 cMsgSkippedInvalid++; 1669 if (cMsgSkippedInvalid > 32) 1668 1670 { 1669 1671 LogRel(("DnD: Too many invalid/skipped messages from host, exiting ...\n")); -
trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibDragAndDrop.cpp
r55556 r55571 552 552 } 553 553 554 #if 0 554 #if 0 /* Not used yet. */ 555 555 if (pCtx->uProtocol >= XXX) 556 556 { -
trunk/src/VBox/Additions/x11/VBoxClient/draganddrop.cpp
r55459 r55571 1184 1184 * Do we have a new window which now is under the cursor? 1185 1185 */ 1186 if ( wndCursor != m_wndCur 1186 if ( wndCursor != m_wndCur 1187 1187 && newVer != -1) 1188 1188 { … … 1338 1338 if (RT_UNLIKELY(xrc == 0)) 1339 1339 { 1340 logError(("Error sending SelectionNotify event to window=%#x: %s\n", 1340 logError(("Error sending SelectionNotify event to window=%#x: %s\n", 1341 1341 s.xselection.requestor, gX11->xErrorToString(xrc).c_str())); 1342 1342 } … … 1448 1448 } 1449 1449 1450 /* 1450 /* 1451 1451 * Acknowledge the event by sending a status message back to the window. 1452 1452 */ … … 1466 1466 if (RT_UNLIKELY(xRc == 0)) 1467 1467 { 1468 logError(("Error sending enter XA_XdndStatus to current window=%#x: %s\n", 1468 logError(("Error sending enter XA_XdndStatus to current window=%#x: %s\n", 1469 1469 m_wndCur, gX11->xErrorToString(xRc).c_str())); 1470 1470 } … … 1492 1492 if (RT_UNLIKELY(xRc == 0)) 1493 1493 { 1494 logError(("Error sending position XA_XdndStatus to current window=%#x: %s\n", 1494 logError(("Error sending position XA_XdndStatus to current window=%#x: %s\n", 1495 1495 m_wndCur, gX11->xErrorToString(xRc).c_str())); 1496 1496 } … … 1691 1691 if (RT_UNLIKELY(xrc == 0)) 1692 1692 { 1693 logError(("Error sending XA_XdndFinished to proxy window=%#x: %s\n", 1693 logError(("Error sending XA_XdndFinished to proxy window=%#x: %s\n", 1694 1694 m_wndProxy, gX11->xErrorToString(xrc).c_str())); 1695 1695 } … … 2326 2326 if (rc == VERR_INVALID_PARAMETER) 2327 2327 cMsgSkippedInvalid++; 2328 if (cMsgSkippedInvalid > 3 )2328 if (cMsgSkippedInvalid > 32) 2329 2329 { 2330 2330 LogRel(("DnD: Too many invalid/skipped messages from host, exiting ...\n")); -
trunk/src/VBox/Main/include/GuestDnDPrivate.h
r55556 r55571 110 110 lstDirs.clear(); 111 111 lstFiles.clear(); 112 #if 0 /* Currently the scratch buffer will be maintained elswewhere. */ 112 113 if (pvScratchBuf) 113 114 { … … 116 117 } 117 118 cbScratchBuf = 0; 119 #else 120 pvScratchBuf = NULL; 121 cbScratchBuf = 0; 122 #endif 118 123 } 119 124 … … 549 554 int getProtocolVersion(uint32_t *puVersion); 550 555 551 int addMsg(GuestDnDMsg *pMsg) 552 { 553 mDataBase.mListOutgoing.push_back(pMsg); 554 return VINF_SUCCESS; 555 } 556 557 GuestDnDMsg *nextMsg(void) 558 { 559 if (mDataBase.mListOutgoing.empty()) 560 return NULL; 561 return mDataBase.mListOutgoing.front(); 562 } 563 564 void removeNext(void) 565 { 566 if (!mDataBase.mListOutgoing.empty()) 567 { 568 GuestDnDMsg *pMsg = mDataBase.mListOutgoing.front(); 569 if (pMsg) 570 delete pMsg; 571 mDataBase.mListOutgoing.pop_front(); 572 } 573 } 556 /** @name Functions for handling a simple host HGCM message queue. 557 * @{ */ 558 int msgQueueAdd(GuestDnDMsg *pMsg); 559 GuestDnDMsg *msgQueueGetNext(void); 560 void msgQueueRemoveNext(void); 561 void msgQueueClear(void); 562 /** @} */ 563 564 int sendCancel(void); 565 int waitForEvent(RTMSINTERVAL msTimeout, GuestDnDCallbackEvent &Event, GuestDnDResponse *pResp); 574 566 575 567 protected: -
trunk/src/VBox/Main/include/GuestDnDTargetImpl.h
r55549 r55571 74 74 75 75 int i_cancelOperation(void); 76 int i_sendData(PSENDDATACTX pCtx );76 int i_sendData(PSENDDATACTX pCtx, RTMSINTERVAL msTimeout); 77 77 int i_sendDirectory(PSENDDATACTX pCtx, GuestDnDMsg *pMsg, DnDURIObject &aDirectory); 78 78 int i_sendFile(PSENDDATACTX pCtx, GuestDnDMsg *pMsg, DnDURIObject &aFile); 79 79 int i_sendFileData(PSENDDATACTX pCtx, GuestDnDMsg *pMsg, DnDURIObject &aFile); 80 int i_sendURIData(PSENDDATACTX pCtx); 80 int i_sendURIData(PSENDDATACTX pCtx, RTMSINTERVAL msTimeout); 81 int i_sendRawData(PSENDDATACTX pCtx, RTMSINTERVAL msTimeout); 81 82 int i_sendURIDataLoop(PSENDDATACTX pCtx, GuestDnDMsg *pMsg); 82 83 -
trunk/src/VBox/Main/src-client/GuestDnDPrivate.cpp
r55556 r55571 831 831 return rc; 832 832 } 833 834 int GuestDnDBase::msgQueueAdd(GuestDnDMsg *pMsg) 835 { 836 mDataBase.mListOutgoing.push_back(pMsg); 837 return VINF_SUCCESS; 838 } 839 840 GuestDnDMsg *GuestDnDBase::msgQueueGetNext(void) 841 { 842 if (mDataBase.mListOutgoing.empty()) 843 return NULL; 844 return mDataBase.mListOutgoing.front(); 845 } 846 847 void GuestDnDBase::msgQueueRemoveNext(void) 848 { 849 if (!mDataBase.mListOutgoing.empty()) 850 { 851 GuestDnDMsg *pMsg = mDataBase.mListOutgoing.front(); 852 if (pMsg) 853 delete pMsg; 854 mDataBase.mListOutgoing.pop_front(); 855 } 856 } 857 858 void GuestDnDBase::msgQueueClear(void) 859 { 860 GuestDnDMsgList::iterator itMsg = mDataBase.mListOutgoing.begin(); 861 while (itMsg != mDataBase.mListOutgoing.end()) 862 { 863 delete *itMsg; 864 } 865 866 mDataBase.mListOutgoing.clear(); 867 } 868 869 int GuestDnDBase::sendCancel(void) 870 { 871 LogFlowFunc(("Sending cancelation request to guest ...\n")); 872 873 GuestDnDMsg MsgCancel; 874 MsgCancel.setType(DragAndDropSvc::HOST_DND_HG_EVT_CANCEL); 875 876 return GuestDnDInst()->hostCall(MsgCancel.getType(), MsgCancel.getCount(), MsgCancel.getParms()); 877 } 878 879 /** @todo GuestDnDResponse *pResp needs to go. */ 880 int GuestDnDBase::waitForEvent(RTMSINTERVAL msTimeout, GuestDnDCallbackEvent &Event, GuestDnDResponse *pResp) 881 { 882 int rc; 883 884 uint64_t tsStart = RTTimeMilliTS(); 885 do 886 { 887 /* 888 * Wait until our desired callback triggered the 889 * wait event. As we don't want to block if the guest does not 890 * respond, so do busy waiting here. 891 */ 892 rc = Event.Wait(500 /* ms */); 893 if (RT_SUCCESS(rc)) 894 { 895 rc = Event.Result(); 896 LogFlowFunc(("Callback done, result is %Rrc\n", rc)); 897 break; 898 } 899 else if (rc == VERR_TIMEOUT) /* Continue waiting. */ 900 rc = VINF_SUCCESS; 901 902 if ( msTimeout != RT_INDEFINITE_WAIT 903 && RTTimeMilliTS() - tsStart > msTimeout) 904 { 905 rc = VERR_TIMEOUT; 906 } 907 else if (pResp->isProgressCanceled()) 908 { 909 pResp->setProgress(100 /* Percent */, DragAndDropSvc::DND_PROGRESS_CANCELLED); 910 rc = VERR_CANCELLED; 911 } 912 913 } while (RT_SUCCESS(rc)); 914 915 LogFlowFuncLeaveRC(rc); 916 return rc; 917 } 833 918 #endif /* VBOX_WITH_DRAG_AND_DROP */ 834 919 -
trunk/src/VBox/Main/src-client/GuestDnDSourceImpl.cpp
r55556 r55571 781 781 if (SUCCEEDED(autoCaller.rc())) 782 782 { 783 rc = pSource->i_receiveData(pTask->getCtx(), RT_INDEFINITE_WAIT );783 rc = pSource->i_receiveData(pTask->getCtx(), RT_INDEFINITE_WAIT /* msTimeout */); 784 784 } 785 785 else … … 838 838 rc = pInst->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms()); 839 839 if (RT_SUCCESS(rc)) 840 { 841 /* 842 * Wait until our callback i_receiveRawDataCallback triggered the 843 * wait event. 844 */ 845 LogFlowFunc(("Waiting for raw data callback (%RU32ms timeout) ...\n", msTimeout)); 846 rc = pCtx->mCallback.Wait(msTimeout); 847 LogFlowFunc(("Raw callback done, rc=%Rrc\n", rc)); 848 } 840 rc = waitForEvent(msTimeout, pCtx->mCallback, pCtx->mpResp); 849 841 850 842 } while (0); … … 858 850 #undef REGISTER_CALLBACK 859 851 #undef UNREGISTER_CALLBACK 852 853 if (rc == VERR_CANCELLED) 854 { 855 int rc2 = sendCancel(); 856 AssertRC(rc2); 857 } 860 858 861 859 LogFlowFuncLeaveRC(rc); … … 918 916 919 917 /* Make the initial call to the guest by telling that we initiated the "dropped" event on 920 * the host and therefore now waiting for the actual URI actualdata. */918 * the host and therefore now waiting for the actual URI data. */ 921 919 rc = pInst->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms()); 922 920 if (RT_SUCCESS(rc)) 923 { 924 /* 925 * Wait until our callback i_receiveURIDataCallback triggered the 926 * wait event. 927 */ 928 LogFlowFunc(("Waiting for URI callback (%RU32ms timeout) ...\n", msTimeout)); 929 rc = pCtx->mCallback.Wait(msTimeout); 930 LogFlowFunc(("URI callback done, rc=%Rrc\n", rc)); 931 if (RT_SUCCESS(rc)) 932 { 933 rc = pCtx->mCallback.Result(); 934 LogFlowFunc(("Callback result is %Rrc\n", rc)); 935 } 936 } 921 rc = waitForEvent(msTimeout, pCtx->mCallback, pCtx->mpResp); 937 922 938 923 } while (0); … … 950 935 #undef REGISTER_CALLBACK 951 936 #undef UNREGISTER_CALLBACK 937 938 if (rc == VERR_CANCELLED) 939 { 940 int rc2 = sendCancel(); 941 AssertRC(rc2); 942 } 952 943 953 944 if (RT_FAILURE(rc)) -
trunk/src/VBox/Main/src-client/GuestDnDTargetImpl.cpp
r55556 r55571 491 491 if (SUCCEEDED(autoCaller.rc())) 492 492 { 493 rc = pTarget->i_sendData(pTask->getCtx() );493 rc = pTarget->i_sendData(pTask->getCtx(), RT_INDEFINITE_WAIT /* msTimeout */); 494 494 /* Nothing to do here anymore. */ 495 495 } … … 601 601 } 602 602 603 int GuestDnDTarget::i_sendData(PSENDDATACTX pCtx )603 int GuestDnDTarget::i_sendData(PSENDDATACTX pCtx, RTMSINTERVAL msTimeout) 604 604 { 605 605 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 606 607 #define DATA_IS_VALID_BREAK(x) \608 if (!x) \609 { \610 LogFlowFunc(("Invalid URI data value for \"" #x "\"\n")); \611 rc = VERR_INVALID_PARAMETER; \612 break; \613 }614 606 615 607 GuestDnD *pInst = GuestDnDInst(); … … 624 616 mDataBase.mListOutgoing.clear(); 625 617 626 do 627 { 628 const char *pszFormat = pCtx->mFormat.c_str(); 629 DATA_IS_VALID_BREAK(pszFormat); 630 uint32_t cbFormat = pCtx->mFormat.length() + 1; 631 632 /* Do we need to build up a file tree? */ 633 bool fHasURIList = DnDMIMEHasFileURLs(pszFormat, cbFormat); 634 if (fHasURIList) 635 { 636 rc = i_sendURIData(pCtx); 637 } 638 else 639 { 640 GuestDnDMsg Msg; 641 642 size_t cbDataTotal = pCtx->mData.vecData.size(); 643 DATA_IS_VALID_BREAK(cbDataTotal); 644 645 /* Just copy over the raw data. */ 646 Msg.setType(DragAndDropSvc::HOST_DND_HG_SND_DATA); 647 Msg.setNextUInt32(pCtx->mScreenID); 648 Msg.setNextPointer((void *)pCtx->mFormat.c_str(), (uint32_t)pCtx->mFormat.length() + 1); 649 Msg.setNextUInt32((uint32_t)pCtx->mFormat.length() + 1); 650 Msg.setNextPointer((void*)&pCtx->mData.vecData.front(), (uint32_t)cbDataTotal); 651 Msg.setNextUInt32(cbDataTotal); 652 653 LogFlowFunc(("%zu total bytes of raw data to transfer\n", cbDataTotal)); 654 655 /* Make the initial call to the guest by sending the actual data. This might 656 * be an URI list which in turn can lead to more data to send afterwards. */ 657 rc = pInst->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms()); 658 if (RT_FAILURE(rc)) 659 break; 660 } 661 662 } while (0); 618 const char *pszFormat = pCtx->mFormat.c_str(); 619 uint32_t cbFormat = pCtx->mFormat.length() + 1; 620 621 /* Do we need to build up a file tree? */ 622 bool fHasURIList = DnDMIMEHasFileURLs(pszFormat, cbFormat); 623 if (fHasURIList) 624 { 625 rc = i_sendURIData(pCtx, msTimeout); 626 } 627 else 628 { 629 rc = i_sendRawData(pCtx, msTimeout); 630 } 663 631 664 632 ASMAtomicWriteBool(&pCtx->mIsActive, false); … … 857 825 { 858 826 pMsg = new GuestDnDMsg(); 827 859 828 rc = pThis->i_sendURIDataLoop(pCtx, pMsg); 860 829 if (RT_SUCCESS(rc)) 861 830 { 862 rc = pThis-> addMsg(pMsg);831 rc = pThis->msgQueueAdd(pMsg); 863 832 if (RT_SUCCESS(rc)) /* Return message type & required parameter count to the guest. */ 864 833 { … … 903 872 LogFlowFunc(("pCBData->uMsg=%RU32, paParms=%p, cParms=%RU32\n", pCBData->uMsg, pCBData->paParms, pCBData->cParms)); 904 873 905 GuestDnDMsg *pMsg = pThis-> nextMsg();874 GuestDnDMsg *pMsg = pThis->msgQueueGetNext(); 906 875 if (pMsg) 907 876 { … … 913 882 || pCBData->cParms != pMsg->getCount()) 914 883 { 884 /* Start over. */ 885 pThis->msgQueueClear(); 886 915 887 rc = VERR_INVALID_PARAMETER; 916 888 } … … 923 895 { 924 896 pCBData->cParms = pMsg->getCount(); 925 pThis-> removeNext();897 pThis->msgQueueRemoveNext(); 926 898 } 927 899 else … … 971 943 } 972 944 973 int GuestDnDTarget::i_sendURIData(PSENDDATACTX pCtx )945 int GuestDnDTarget::i_sendURIData(PSENDDATACTX pCtx, RTMSINTERVAL msTimeout) 974 946 { 975 947 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); … … 990 962 int rc; 991 963 992 #define REGISTER_CALLBACK(x) \964 #define REGISTER_CALLBACK(x) \ 993 965 rc = pCtx->mpResp->setCallback(x, i_sendURIDataCallback, pCtx); \ 994 if (RT_FAILURE(rc)) \966 if (RT_FAILURE(rc)) \ 995 967 return rc; 968 969 #define UNREGISTER_CALLBACK(x) \ 970 { \ 971 int rc2 = pCtx->mpResp->setCallback(x, NULL); \ 972 AssertRC(rc2); \ 973 } 996 974 997 975 rc = pCtx->mCallback.Reset(); 998 976 if (RT_FAILURE(rc)) 999 977 return rc; 1000 1001 #define UNREGISTER_CALLBACK(x) \1002 rc = pCtx->mpResp->setCallback(x, NULL); \1003 AssertRC(rc);1004 978 1005 979 /* … … 1057 1031 size_t cbData = strData.length() + 1; /* Include terminating zero. */ 1058 1032 1059 GuestDnDMsg Msg ;1060 Msg .setType(DragAndDropSvc::HOST_DND_HG_SND_DATA);1061 Msg .setNextUInt32(pCtx->mScreenID);1062 Msg .setNextPointer((void *)pCtx->mFormat.c_str(), (uint32_t)pCtx->mFormat.length() + 1);1063 Msg .setNextUInt32((uint32_t)pCtx->mFormat.length() + 1);1064 Msg .setNextPointer((void*)strData.c_str(), (uint32_t)cbData);1065 Msg .setNextUInt32((uint32_t)cbData);1066 1067 rc = GuestDnDInst()->hostCall(Msg .getType(), Msg.getCount(), Msg.getParms());1033 GuestDnDMsg MsgSndData; 1034 MsgSndData.setType(DragAndDropSvc::HOST_DND_HG_SND_DATA); 1035 MsgSndData.setNextUInt32(pCtx->mScreenID); 1036 MsgSndData.setNextPointer((void *)pCtx->mFormat.c_str(), (uint32_t)pCtx->mFormat.length() + 1); 1037 MsgSndData.setNextUInt32((uint32_t)pCtx->mFormat.length() + 1); 1038 MsgSndData.setNextPointer((void*)strData.c_str(), (uint32_t)cbData); 1039 MsgSndData.setNextUInt32((uint32_t)cbData); 1040 1041 rc = GuestDnDInst()->hostCall(MsgSndData.getType(), MsgSndData.getCount(), MsgSndData.getParms()); 1068 1042 if (RT_SUCCESS(rc)) 1069 { 1070 /* 1071 * Wait until our callback i_sendURIDataCallback triggered the 1072 * wait event. 1073 */ 1074 LogFlowFunc(("Waiting for URI callback ...\n")); 1075 rc = pCtx->mCallback.Wait(RT_INDEFINITE_WAIT); 1076 LogFlowFunc(("URI callback done, rc=%Rrc\n", rc)); 1077 } 1043 rc = waitForEvent(msTimeout, pCtx->mCallback, pCtx->mpResp); 1078 1044 1079 1045 } while (0); 1080 1046 1081 1047 /* 1082 * Unregister callbacks again.1048 * Unregister callbacks. 1083 1049 */ 1084 1050 /* Guest callbacks. */ … … 1094 1060 #undef UNREGISTER_CALLBACK 1095 1061 1062 /* 1063 * Now that we've cleaned up tell the guest side to cancel. 1064 */ 1065 if (rc == VERR_CANCELLED) 1066 { 1067 int rc2 = sendCancel(); 1068 AssertRC(rc2); 1069 } 1070 1096 1071 /* Destroy temporary scratch buffer. */ 1097 1072 if (pvBuf) … … 1171 1146 } 1172 1147 1173 if ( pCtx->mpResp1174 && pCtx->mpResp->isProgressCanceled())1175 {1176 LogFlowFunc(("Cancelling ...\n"));1177 1178 rc = i_cancelOperation();1179 if (RT_SUCCESS(rc))1180 rc = VERR_CANCELLED;1181 }1182 1183 1148 LogFlowFuncLeaveRC(rc); 1184 1149 return rc; 1150 } 1151 1152 int GuestDnDTarget::i_sendRawData(PSENDDATACTX pCtx, RTMSINTERVAL msTimeout) 1153 { 1154 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 1155 NOREF(msTimeout); 1156 1157 GuestDnD *pInst = GuestDnDInst(); 1158 AssertPtr(pInst); 1159 1160 /* At the moment we only allow up to 64K raw data. */ 1161 size_t cbDataTotal = pCtx->mData.vecData.size(); 1162 if ( !cbDataTotal 1163 || cbDataTotal > _64K) 1164 { 1165 return VERR_INVALID_PARAMETER; 1166 } 1167 1168 /* Just copy over the raw data. */ 1169 GuestDnDMsg Msg; 1170 Msg.setType(DragAndDropSvc::HOST_DND_HG_SND_DATA); 1171 Msg.setNextUInt32(pCtx->mScreenID); 1172 Msg.setNextPointer((void *)pCtx->mFormat.c_str(), (uint32_t)pCtx->mFormat.length() + 1); 1173 Msg.setNextUInt32((uint32_t)pCtx->mFormat.length() + 1); 1174 Msg.setNextPointer((void*)&pCtx->mData.vecData.front(), (uint32_t)cbDataTotal); 1175 Msg.setNextUInt32(cbDataTotal); 1176 1177 LogFlowFunc(("%zu total bytes of raw data to transfer\n", cbDataTotal)); 1178 1179 return pInst->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms()); 1185 1180 } 1186 1181
Note:
See TracChangeset
for help on using the changeset viewer.