Changeset 57500 in vbox for trunk/src/VBox/Main/src-client/GuestDnDTargetImpl.cpp
- Timestamp:
- Aug 21, 2015 4:54:50 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-client/GuestDnDTargetImpl.cpp
r57469 r57500 771 771 ASMAtomicWriteBool(&pCtx->mIsActive, false); 772 772 773 #undef DATA_IS_VALID_BREAK774 775 773 LogFlowFuncLeaveRC(rc); 776 774 return rc; 777 775 } 778 776 779 int GuestDnDTarget::i_sendDirectory(PSENDDATACTX pCtx, GuestDnDMsg *pMsg, DnDURIObject *pObject) 780 { 781 AssertPtrReturn(pObject, VERR_INVALID_POINTER); 777 int GuestDnDTarget::i_sendDirectory(PSENDDATACTX pCtx, GuestDnDURIObjCtx *pObjCtx, GuestDnDMsg *pMsg) 778 { 782 779 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 783 784 RTCString strPath = pObject->GetDestPath(); 780 AssertPtrReturn(pObjCtx, VERR_INVALID_POINTER); 781 AssertPtrReturn(pMsg, VERR_INVALID_POINTER); 782 783 DnDURIObject *pObj = pObjCtx->pObjURI; 784 AssertPtr(pObj); 785 786 RTCString strPath = pObj->GetDestPath(); 785 787 if (strPath.isEmpty()) 786 788 return VERR_INVALID_PARAMETER; … … 793 795 pMsg->setNextString(strPath.c_str()); /* path */ 794 796 pMsg->setNextUInt32((uint32_t)(strPath.length() + 1)); /* path length - note: Maximum is RTPATH_MAX on guest side. */ 795 pMsg->setNextUInt32(pObj ect->GetMode());/* mode */797 pMsg->setNextUInt32(pObj->GetMode()); /* mode */ 796 798 797 799 return VINF_SUCCESS; 798 800 } 799 801 800 int GuestDnDTarget::i_sendFile(PSENDDATACTX pCtx, GuestDnDMsg *pMsg, DnDURIObject *pObject) 801 { 802 AssertPtrReturn(pObject, VERR_INVALID_POINTER); 802 int GuestDnDTarget::i_sendFile(PSENDDATACTX pCtx, GuestDnDURIObjCtx *pObjCtx, GuestDnDMsg *pMsg) 803 { 803 804 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 804 805 RTCString strPathSrc = pObject->GetSourcePath(); 805 AssertPtrReturn(pObjCtx, VERR_INVALID_POINTER); 806 AssertPtrReturn(pMsg, VERR_INVALID_POINTER); 807 808 DnDURIObject *pObj = pObjCtx->pObjURI; 809 AssertPtr(pObj); 810 811 RTCString strPathSrc = pObj->GetSourcePath(); 806 812 if (strPathSrc.isEmpty()) 807 813 return VERR_INVALID_PARAMETER; … … 809 815 int rc = VINF_SUCCESS; 810 816 811 LogFlowFunc(("Sending \"%s\" (%RU32 bytes buffer)using protocol v%RU32 ...\n",812 strPathSrc.c_str(),mData.mcbBlockSize, mDataBase.mProtocolVersion));813 814 bool fOpen = pObject->IsOpen(); 815 if (! fOpen)816 { 817 Log FlowFunc(("Opening \"%s\" ...\n", strPathSrc.c_str()));818 rc = pObj ect->OpenEx(strPathSrc, DnDURIObject::File, DnDURIObject::Source,817 LogFlowFunc(("Sending file with %RU32 bytes buffer, using protocol v%RU32 ...\n", 818 mData.mcbBlockSize, mDataBase.mProtocolVersion)); 819 LogFlowFunc(("strPathSrc=%s, fIsOpen=%RTbool, cbSize=%RU64\n", strPathSrc.c_str(), pObj->IsOpen(), pObj->GetSize())); 820 821 if (!pObj->IsOpen()) 822 { 823 LogRel2(("DnD: Opening host file for transferring to guest: %s\n", strPathSrc.c_str())); 824 rc = pObj->OpenEx(strPathSrc, DnDURIObject::File, DnDURIObject::Source, 819 825 RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE, 0 /* fFlags */); 820 826 if (RT_FAILURE(rc)) 821 LogRel(("DnD: Error opening host file \"%s\", rc=%Rrc\n", strPathSrc.c_str(), rc));822 } 823 824 bool fSend FileData = false;827 LogRel(("DnD: Error opening host file '%s', rc=%Rrc\n", strPathSrc.c_str(), rc)); 828 } 829 830 bool fSendData = false; 825 831 if (RT_SUCCESS(rc)) 826 832 { 827 833 if (mDataBase.mProtocolVersion >= 2) 828 834 { 829 if (! fOpen)835 if (!pObjCtx->fHeaderSent) 830 836 { 831 837 /* … … 835 841 */ 836 842 pMsg->setType(DragAndDropSvc::HOST_DND_HG_SND_FILE_HDR); 837 pMsg->setNextUInt32(0); /* contextID */838 rc = pMsg->setNextString(pObj ect->GetDestPath().c_str()); /* pvName */843 pMsg->setNextUInt32(0); /* uContextID */ 844 rc = pMsg->setNextString(pObj->GetDestPath().c_str()); /* pvName */ 839 845 AssertRC(rc); 840 pMsg->setNextUInt32((uint32_t)(pObj ect->GetDestPath().length() + 1)); /* cbName */846 pMsg->setNextUInt32((uint32_t)(pObj->GetDestPath().length() + 1)); /* cbName */ 841 847 pMsg->setNextUInt32(0); /* uFlags */ 842 pMsg->setNextUInt32(pObj ect->GetMode()); /* fMode */843 pMsg->setNextUInt64(pObj ect->GetSize()); /* uSize */848 pMsg->setNextUInt32(pObj->GetMode()); /* fMode */ 849 pMsg->setNextUInt64(pObj->GetSize()); /* uSize */ 844 850 845 851 LogFlowFunc(("Sending file header ...\n")); 846 852 LogRel2(("DnD: Transferring host file to guest: %s (%RU64 bytes, mode 0x%x)\n", 847 strPathSrc.c_str(), pObj ect->GetSize(), pObject->GetMode()));853 strPathSrc.c_str(), pObj->GetSize(), pObj->GetMode())); 848 854 849 855 /** @todo Set progress object title to current file being transferred? */ 856 857 pObjCtx->fHeaderSent = true; 850 858 } 851 859 else 852 860 { 853 861 /* File header was sent, so only send the actual file data. */ 854 fSend FileData = true;862 fSendData = true; 855 863 } 856 864 } … … 858 866 { 859 867 /* Always send the file data, every time. */ 860 fSend FileData = true;868 fSendData = true; 861 869 } 862 870 } 863 871 864 872 if ( RT_SUCCESS(rc) 865 && fSend FileData)866 { 867 rc = i_sendFileData(pCtx, p Msg, pObject);873 && fSendData) 874 { 875 rc = i_sendFileData(pCtx, pObjCtx, pMsg); 868 876 } 869 877 … … 872 880 } 873 881 874 int GuestDnDTarget::i_sendFileData(PSENDDATACTX pCtx, GuestDnDMsg *pMsg, DnDURIObject *pObject) 875 { 876 AssertPtrReturn(pObject, VERR_INVALID_POINTER); 882 int GuestDnDTarget::i_sendFileData(PSENDDATACTX pCtx, GuestDnDURIObjCtx *pObjCtx, GuestDnDMsg *pMsg) 883 { 877 884 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 885 AssertPtrReturn(pObjCtx, VERR_INVALID_POINTER); 878 886 AssertPtrReturn(pMsg, VERR_INVALID_POINTER); 887 888 DnDURIObject *pObj = pObjCtx->pObjURI; 889 AssertPtr(pObj); 879 890 880 891 GuestDnDResponse *pResp = pCtx->mpResp; … … 882 893 883 894 /** @todo Don't allow concurrent reads per context! */ 884 885 /* Something to transfer? */886 if ( pCtx->mURI.lstURI.IsEmpty()887 || !pCtx->mIsActive)888 {889 return VERR_WRONG_ORDER;890 }891 895 892 896 /* … … 901 905 if (mDataBase.mProtocolVersion <= 1) 902 906 { 903 pMsg->setNextString(pObj ect->GetDestPath().c_str()); /* pvName */904 pMsg->setNextUInt32((uint32_t)(pObj ect->GetDestPath().length() + 1)); /* cbName */907 pMsg->setNextString(pObj->GetDestPath().c_str()); /* pvName */ 908 pMsg->setNextUInt32((uint32_t)(pObj->GetDestPath().length() + 1)); /* cbName */ 905 909 } 906 910 else 907 911 { 908 912 /* Protocol version 2 also sends the context ID. Currently unused. */ 909 pMsg->setNextUInt32(0); 913 pMsg->setNextUInt32(0); /* context ID */ 910 914 } 911 915 912 916 uint32_t cbRead = 0; 913 917 914 int rc = pObj ect->Read(pCtx->mURI.GetBufferMutable(), pCtx->mURI.GetBufferSize(), &cbRead);918 int rc = pObj->Read(pCtx->mURI.GetBufferMutable(), pCtx->mURI.GetBufferSize(), &cbRead); 915 919 if (RT_SUCCESS(rc)) 916 920 { 917 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)); 918 924 919 925 if (mDataBase.mProtocolVersion <= 1) 920 926 { 921 pMsg->setNextPointer(pCtx->mURI.GetBufferMutable(), cbRead); /* pvData */922 pMsg->setNextUInt32(cbRead); /* cbData */923 pMsg->setNextUInt32(pObj ect->GetMode());/* fMode */927 pMsg->setNextPointer(pCtx->mURI.GetBufferMutable(), cbRead); /* pvData */ 928 pMsg->setNextUInt32(cbRead); /* cbData */ 929 pMsg->setNextUInt32(pObj->GetMode()); /* fMode */ 924 930 } 925 931 else 926 932 { 927 pMsg->setNextPointer(pCtx->mURI.GetBufferMutable(), cbRead); /* pvData */ 928 pMsg->setNextUInt32(cbRead); /* cbData */ 929 } 930 931 if (pObject->IsComplete()) /* Done reading? */ 932 { 933 LogRel2(("DnD: File transfer to guest complete: %s\n", pObject->GetSourcePath().c_str())); 934 LogFlowFunc(("File \"%s\" complete\n", pObject->GetSourcePath().c_str())); 935 rc = VINF_EOF; 933 pMsg->setNextPointer(pCtx->mURI.GetBufferMutable(), cbRead); /* pvData */ 934 pMsg->setNextUInt32(cbRead); /* cbData */ 935 } 936 937 if (pObj->IsComplete()) /* Done reading? */ 938 { 939 LogRel2(("DnD: File transfer to guest complete: %s\n", pObj->GetSourcePath().c_str())); 940 LogFlowFunc(("File '%s' complete\n", pObj->GetSourcePath().c_str())); 941 942 /* DnDURIObject::Read() returns VINF_EOF when finished reading the entire fire, 943 * but we don't want this here -- so just override this with VINF_SUCCESS. */ 944 rc = VINF_SUCCESS; 936 945 } 937 946 } … … 952 961 LogFlowFunc(("pThis=%p, uMsg=%RU32\n", pThis, uMsg)); 953 962 954 int rc = VINF_SUCCESS; /* Will be reported back to guest. */ 955 956 int rcCallback = VINF_SUCCESS; /* rc for the callback. */ 963 int rc = VINF_SUCCESS; /* Will be reported back to guest. */ 964 int rcGuest; /* Contains error code from guest in case of VERR_GSTDND_GUEST_ERROR. */ 957 965 bool fNotify = false; 958 966 … … 971 979 972 980 rc = pThis->i_sendURIDataLoop(pCtx, pMsg); 973 if (RT_SUCCESS(rc)) 981 if (rc == VINF_EOF) /* Transfer complete? */ 982 { 983 LogFlowFunc(("Last URI item processed, bailing out\n")); 984 } 985 else if (RT_SUCCESS(rc)) 974 986 { 975 987 rc = pThis->msgQueueAdd(pMsg); … … 982 994 } 983 995 984 if (RT_FAILURE(rc)) 996 if ( RT_FAILURE(rc) 997 || rc == VINF_EOF) /* Transfer complete? */ 998 { 985 999 delete pMsg; 1000 pMsg = NULL; 1001 } 986 1002 } 987 1003 catch(std::bad_alloc & /*e*/) … … 1001 1017 1002 1018 if (RT_SUCCESS(pCBData->rc)) 1019 { 1020 AssertMsgFailed(("Guest has sent an error event but did not specify an actual error code\n")); 1003 1021 pCBData->rc = VERR_GENERAL_FAILURE; /* Make sure some error is set. */ 1022 } 1004 1023 1005 1024 rc = pCtx->mpResp->setProgress(100, DragAndDropSvc::DND_PROGRESS_ERROR, pCBData->rc, 1006 1025 GuestDnDTarget::i_guestErrorToString(pCBData->rc)); 1007 1026 if (RT_SUCCESS(rc)) 1008 rcCallback = VERR_GSTDND_GUEST_ERROR; 1027 { 1028 rc = VERR_GSTDND_GUEST_ERROR; 1029 rcGuest = pCBData->rc; 1030 } 1009 1031 break; 1010 1032 } … … 1061 1083 } 1062 1084 1063 if ( RT_FAILURE(rc) 1064 || RT_FAILURE(rcCallback)) 1065 { 1066 fNotify = true; 1067 if (RT_SUCCESS(rcCallback)) 1068 rcCallback = rc; 1085 int rcToGuest = VINF_SUCCESS; /* Status which will be sent back to the guest. */ 1086 1087 /* 1088 * Resolve errors. 1089 */ 1090 switch (rc) 1091 { 1092 case VINF_SUCCESS: 1093 break; 1094 1095 case VINF_EOF: 1096 { 1097 LogRel2(("DnD: Transfer to guest complete\n")); 1098 1099 /* Complete operation on host side. */ 1100 fNotify = true; 1101 1102 /* The guest expects VERR_NO_DATA if the transfer is complete. */ 1103 rcToGuest = VERR_NO_DATA; 1104 break; 1105 } 1106 1107 case VERR_GSTDND_GUEST_ERROR: 1108 { 1109 LogRel(("DnD: Guest reported error %Rrc, aborting transfer to guest\n", rcGuest)); 1110 break; 1111 } 1112 1113 case VERR_CANCELLED: 1114 { 1115 LogRel2(("DnD: Transfer to guest canceled\n")); 1116 rcToGuest = VERR_CANCELLED; /* Also cancel on guest side. */ 1117 break; 1118 } 1119 1120 default: 1121 { 1122 LogRel(("DnD: Host error %Rrc occurred, aborting transfer to guest\n", rc)); 1123 rcToGuest = VERR_CANCELLED; /* Also cancel on guest side. */ 1124 break; 1125 } 1069 1126 } 1070 1127 1071 1128 if (RT_FAILURE(rc)) 1072 1129 { 1073 switch (rc)1074 {1075 case VERR_NO_DATA:1076 LogRel2(("DnD: Transfer to guest complete\n"));1077 break;1078 1079 case VERR_CANCELLED:1080 LogRel2(("DnD: Transfer to guest canceled\n"));1081 break;1082 1083 default:1084 LogRel(("DnD: Error %Rrc occurred, aborting transfer to guest\n", rc));1085 break;1086 }1087 1088 1130 /* Unregister this callback. */ 1089 1131 AssertPtr(pCtx->mpResp); 1090 1132 int rc2 = pCtx->mpResp->setCallback(uMsg, NULL /* PFNGUESTDNDCALLBACK */); 1091 1133 AssertRC(rc2); 1092 } 1093 1094 LogFlowFunc(("fNotify=%RTbool, rcCallback=%Rrc, rc=%Rrc\n", fNotify, rcCallback, rc)); 1134 1135 /* Let the waiter(s) know. */ 1136 fNotify = true; 1137 } 1138 1139 LogFlowFunc(("fNotify=%RTbool, rc=%Rrc, rcToGuest=%Rrc\n", fNotify, rc, rcToGuest)); 1095 1140 1096 1141 if (fNotify) 1097 1142 { 1098 int rc2 = pCtx->mCallback.Notify(rc Callback);1143 int rc2 = pCtx->mCallback.Notify(rc); /** @todo Also pass guest error back? */ 1099 1144 AssertRC(rc2); 1100 1145 } 1101 1146 1102 1147 LogFlowFuncLeaveRC(rc); 1103 return rc ; /* Tell the guest. */1148 return rcToGuest; /* Tell the guest. */ 1104 1149 } 1105 1150 … … 1164 1209 URI_DATA_IS_VALID_BREAK(!lstURIOrg.isEmpty()); 1165 1210 1166 uint32_t fFlags = DNDURILIST_FLAGS_KEEP_OPEN;1167 1168 rc = lstURI.AppendURIPathsFromList(lstURIOrg, fFlags);1211 /* Note: All files to be transferred will be kept open during the entire DnD 1212 * operation, also to keep the accounting right. */ 1213 rc = lstURI.AppendURIPathsFromList(lstURIOrg, DNDURILIST_FLAGS_KEEP_OPEN); 1169 1214 if (RT_SUCCESS(rc)) 1170 1215 LogFlowFunc(("URI root objects: %zu, total bytes (raw data to transfer): %zu\n", … … 1267 1312 1268 1313 if (fComplete) 1269 { 1270 LogFlowFunc(("Last URI item processed, bailing out\n")); 1271 return VERR_NO_DATA; 1272 } 1314 return VINF_EOF; 1273 1315 1274 1316 Assert(!lstURI.IsEmpty()); 1275 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; 1276 1325 1277 1326 uint32_t fMode = pCurObj->GetMode(); … … 1283 1332 if (RTFS_IS_DIRECTORY(fMode)) 1284 1333 { 1285 rc = i_sendDirectory(pCtx, p Msg, pCurObj);1334 rc = i_sendDirectory(pCtx, pObjCtx, pMsg); 1286 1335 } 1287 1336 else if (RTFS_IS_FILE(fMode)) 1288 1337 { 1289 rc = i_sendFile(pCtx, p Msg, pCurObj);1338 rc = i_sendFile(pCtx, pObjCtx, pMsg); 1290 1339 } 1291 1340 else
Note:
See TracChangeset
for help on using the changeset viewer.