Changeset 50508 in vbox for trunk/src/VBox/Main/src-client
- Timestamp:
- Feb 19, 2014 3:45:58 PM (11 years ago)
- svn:sync-xref-src-repo-rev:
- 92350
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-client/GuestDnDImpl.cpp
r50460 r50508 191 191 Utf8Str format(void) const { return m_strFormat; } 192 192 193 int dataAdd(void *pvData, uint32_t cbData, uint32_t *pcbCurSize); 193 void setDropDir(const Utf8Str &strDropDir) { m_strDropDir = strDropDir; } 194 Utf8Str dropDir(void) const { return m_strDropDir; } 195 196 int dataAdd(const void *pvData, uint32_t cbData, uint32_t *pcbCurSize); 197 int dataSetStatus(size_t cbDataAdd, size_t cbDataTotal = 0); 194 198 void reset(void); 195 199 const void *data(void) { return m_pvData; } … … 205 209 uint32_t m_allActions; 206 210 Utf8Str m_strFormat; 211 212 /** The actual MIME data.*/ 207 213 void *m_pvData; 214 /** Size (in bytes) of MIME data. */ 208 215 uint32_t m_cbData; 216 217 size_t m_cbDataCurrent; 218 size_t m_cbDataTotal; 219 /** Dropped files directory on the host. */ 220 Utf8Str m_strDropDir; 209 221 210 222 ComObjPtr<Guest> m_parent; … … 276 288 , m_pvData(0) 277 289 , m_cbData(0) 290 , m_cbDataCurrent(0) 291 , m_cbDataTotal(0) 278 292 , m_parent(pGuest) 279 293 { … … 303 317 } 304 318 305 int DnDGuestResponse::dataAdd(void *pvData, uint32_t cbData, uint32_t *pcbCurSize) 306 { 319 int DnDGuestResponse::dataAdd(const void *pvData, uint32_t cbData, 320 uint32_t *pcbCurSize) 321 { 322 AssertPtrReturn(pvData, VERR_INVALID_POINTER); 323 AssertReturn(cbData, VERR_INVALID_PARAMETER); 324 /* pcbCurSize is optional. */ 325 307 326 int rc = VINF_SUCCESS; 308 327 … … 348 367 } 349 368 350 int DnDGuestResponse::setProgress(unsigned uPercentage, uint32_t uState, int rcOp /* = VINF_SUCCESS */) 351 { 352 LogFlowFunc(("uPercentage=%RU32, uState=%ld, rcOp=%Rrc\n", uPercentage, uState, rcOp)); 369 int DnDGuestResponse::setProgress(unsigned uPercentage, 370 uint32_t uState, int rcOp /* = VINF_SUCCESS */) 371 { 372 LogFlowFunc(("uPercentage=%RU32, uState=%ld, rcOp=%Rrc\n", 373 uPercentage, uState, rcOp)); 353 374 354 375 int vrc = VINF_SUCCESS; … … 364 385 COM_IIDOF(IGuest), 365 386 m_parent->getComponentName(), 366 m_parent->tr(" Guest error (%Rrc)"), rcOp);387 m_parent->tr("Drag'n drop guest error (%Rrc)"), rcOp); 367 388 } 368 389 else if (uState == DragAndDropSvc::DND_PROGRESS_CANCELLED) … … 390 411 } 391 412 413 int DnDGuestResponse::dataSetStatus(size_t cbDataAdd, size_t cbDataTotal /* = 0 */) 414 { 415 if (cbDataTotal) 416 { 417 AssertMsg(m_cbDataTotal <= cbDataTotal, ("New data size size must not be smaller (%zu) than old value (%zu)\n", 418 cbDataTotal, m_cbDataTotal)); 419 m_cbDataTotal = cbDataTotal; 420 LogFlowFunc(("Updating total data size to: %zu\n", m_cbDataTotal)); 421 } 422 AssertMsg(m_cbDataTotal, ("m_cbDataTotal must not be <= 0\n")); 423 424 m_cbDataCurrent += cbDataAdd; 425 unsigned int cPercentage = RT_MIN(m_cbDataCurrent * 100.0 / m_cbDataTotal, 100); 426 427 /** @todo Don't use anonymous enums (uint32_t). */ 428 uint32_t uStatus = DragAndDropSvc::DND_PROGRESS_RUNNING; 429 if (m_cbDataCurrent >= m_cbDataTotal) 430 uStatus = DragAndDropSvc::DND_PROGRESS_COMPLETE; 431 432 #ifdef DEBUG_andy 433 LogFlowFunc(("Updating transfer status (%zu/%zu), status=%ld\n", 434 m_cbDataCurrent, m_cbDataTotal, uStatus)); 435 #endif 436 437 AssertMsg(m_cbDataCurrent <= m_cbDataTotal, 438 ("More data transferred (%RU32) than initially announced (%RU32)\n", 439 m_cbDataCurrent, m_cbDataTotal)); 440 441 int rc = setProgress(cPercentage, uStatus); 442 443 /** @todo For now we instantly confirm the cancel. Check if the 444 * guest should first clean up stuff itself and than really confirm 445 * the cancel request by an extra message. */ 446 if (rc == VERR_CANCELLED) 447 rc = setProgress(100, DragAndDropSvc::DND_PROGRESS_CANCELLED); 448 449 return rc; 450 } 451 392 452 HRESULT DnDGuestResponse::queryProgressTo(IProgress **ppProgress) 393 453 { … … 503 563 504 564 /* static */ 505 void GuestDnDPrivate::toHGCMActions(DragAndDropAction_T inDefAction, uint32_t *pOutDefAction, ComSafeArrayIn(DragAndDropAction_T, inAllowedActions), uint32_t *pOutAllowedActions) 565 void GuestDnDPrivate::toHGCMActions(DragAndDropAction_T inDefAction, 566 uint32_t *pOutDefAction, 567 ComSafeArrayIn(DragAndDropAction_T, inAllowedActions), 568 uint32_t *pOutAllowedActions) 506 569 { 507 570 const com::SafeArray<DragAndDropAction_T> sfaInActions(ComSafeArrayInArg(inAllowedActions)); … … 529 592 DragAndDropAction_T GuestDnDPrivate::toMainAction(uint32_t uAction) 530 593 { 531 /* For now it doesn't seems useful to allow a link action between host & guest. Maybe later! */ 594 /* For now it doesn't seems useful to allow a 595 * link action between host & guest. Maybe later! */ 532 596 return (isDnDCopyAction(uAction) ? (DragAndDropAction_T)DragAndDropAction_Copy : 533 597 isDnDMoveAction(uAction) ? (DragAndDropAction_T)DragAndDropAction_Move : … … 536 600 537 601 /* static */ 538 void GuestDnDPrivate::toMainActions(uint32_t uActions, ComSafeArrayOut(DragAndDropAction_T, actions)) 539 { 540 /* For now it doesn't seems useful to allow a link action between host & guest. Maybe later! */ 602 void GuestDnDPrivate::toMainActions(uint32_t uActions, 603 ComSafeArrayOut(DragAndDropAction_T, actions)) 604 { 605 /* For now it doesn't seems useful to allow a 606 * link action between host & guest. Maybe later! */ 541 607 RTCList<DragAndDropAction_T> list; 542 608 if (hasDnDCopyAction(uActions)) … … 556 622 } 557 623 558 GuestDnD::~GuestDnD( )624 GuestDnD::~GuestDnD(void) 559 625 { 560 626 delete d_ptr; 561 627 } 562 628 563 HRESULT GuestDnD::dragHGEnter(ULONG uScreenId, ULONG uX, ULONG uY, DragAndDropAction_T defaultAction, ComSafeArrayIn(DragAndDropAction_T, allowedActions), ComSafeArrayIn(IN_BSTR, formats), DragAndDropAction_T *pResultAction) 629 HRESULT GuestDnD::dragHGEnter(ULONG uScreenId, ULONG uX, ULONG uY, 630 DragAndDropAction_T defaultAction, 631 ComSafeArrayIn(DragAndDropAction_T, allowedActions), 632 ComSafeArrayIn(IN_BSTR, formats), 633 DragAndDropAction_T *pResultAction) 564 634 { 565 635 DPTR(GuestDnD); … … 621 691 } 622 692 623 HRESULT GuestDnD::dragHGMove(ULONG uScreenId, ULONG uX, ULONG uY, DragAndDropAction_T defaultAction, ComSafeArrayIn(DragAndDropAction_T, allowedActions), ComSafeArrayIn(IN_BSTR, formats), DragAndDropAction_T *pResultAction) 693 HRESULT GuestDnD::dragHGMove(ULONG uScreenId, ULONG uX, ULONG uY, 694 DragAndDropAction_T defaultAction, 695 ComSafeArrayIn(DragAndDropAction_T, allowedActions), 696 ComSafeArrayIn(IN_BSTR, formats), 697 DragAndDropAction_T *pResultAction) 624 698 { 625 699 DPTR(GuestDnD); … … 879 953 880 954 const char *pcszFormat = strFormat.c_str(); 881 LogFlowFunc(("strFormat=%s, uAction=0x%x\n", pcszFormat, uAction)); 882 if (DnDMIMENeedsDropDir(pcszFormat, strlen(pcszFormat))) 955 bool fNeedsDropDir = DnDMIMENeedsDropDir(pcszFormat, strlen(pcszFormat)); 956 LogFlowFunc(("strFormat=%s, uAction=0x%x, fNeedsDropDir=%RTbool\n", 957 pcszFormat, uAction, fNeedsDropDir)); 958 959 DnDGuestResponse *pDnD = d->response(); 960 AssertPtr(pDnD); 961 962 if (fNeedsDropDir) 883 963 { 884 964 char szDropDir[RTPATH_MAX]; … … 889 969 szDropDir, rc); 890 970 LogFlowFunc(("Dropped files directory on the host is: %s\n", szDropDir)); 971 972 pDnD->setDropDir(szDropDir); 891 973 } 892 974 … … 899 981 paParms[i++].setUInt32(uAction); 900 982 901 DnDGuestResponse *pDnD = d->response();902 903 983 /* Reset any old data and the progress status. */ 904 984 pDnD->reset(); … … 925 1005 const ComObjPtr<Guest> &p = d->p; 926 1006 927 HRESULT rc= S_OK;928 929 DnDGuestResponse *p DnD= d->response();930 if (p DnD)1007 HRESULT hr = S_OK; 1008 1009 DnDGuestResponse *pResp = d->response(); 1010 if (pResp) 931 1011 { 932 1012 com::SafeArray<BYTE> sfaData; 933 1013 934 uint32_t cbData = pDnD->size();1014 size_t cbData = pResp->size(); 935 1015 if (cbData) 936 1016 { 937 /* Copy the data into a safe array of bytes. */ 938 const void *pvData = pDnD->data(); 939 if (sfaData.resize(cbData)) 940 memcpy(sfaData.raw(), pvData, cbData); 1017 const void *pvData = pResp->data(); 1018 AssertPtr(pvData); 1019 1020 Utf8Str strFormat = pResp->format(); 1021 LogFlowFunc(("strFormat=%s, strDropDir=%s\n", 1022 strFormat.c_str(), pResp->dropDir().c_str())); 1023 1024 if (DnDMIMEHasFileURLs(strFormat.c_str(), strFormat.length())) 1025 { 1026 DnDURIList lstURI; 1027 int rc2 = lstURI.RootFromURIData(pvData, cbData, 0 /* fFlags */); 1028 if (RT_SUCCESS(rc2)) 1029 { 1030 Utf8Str strURIs = lstURI.RootToString(pResp->dropDir()); 1031 if (sfaData.resize(strURIs.length())) 1032 memcpy(sfaData.raw(), strURIs.c_str(), strURIs.length()); 1033 else 1034 hr = E_OUTOFMEMORY; 1035 } 1036 else 1037 hr = VBOX_E_IPRT_ERROR; 1038 1039 LogFlowFunc(("Found %zu root URIs, rc=%Rrc\n", lstURI.RootCount(), rc2)); 1040 } 941 1041 else 942 rc = E_OUTOFMEMORY; 1042 { 1043 /* Copy the data into a safe array of bytes. */ 1044 if (sfaData.resize(cbData)) 1045 memcpy(sfaData.raw(), pvData, cbData); 1046 else 1047 hr = E_OUTOFMEMORY; 1048 } 943 1049 } 944 1050 945 #ifdef DEBUG_andy 946 LogFlowFunc(("Received %RU32 bytes\n", cbData)); 947 #endif 1051 LogFlowFunc(("cbData=%zu\n", cbData)); 1052 948 1053 /* Detach in any case, regardless of data size. */ 949 1054 sfaData.detachTo(ComSafeArrayOutArg(data)); 950 1055 951 1056 /* Delete the data. */ 952 p DnD->reset();1057 pResp->reset(); 953 1058 } 954 1059 else 955 rc = VBOX_E_INVALID_OBJECT_STATE; 956 1060 hr = VBOX_E_INVALID_OBJECT_STATE; 1061 1062 LogFlowFunc(("Returning hr=%Rhrc\n", hr)); 1063 return hr; 1064 } 1065 1066 int GuestDnD::onGHSendData(DnDGuestResponse *pResp, 1067 const void *pvData, size_t cbData, 1068 size_t cbTotalSize) 1069 { 1070 AssertPtrReturn(pResp, VERR_INVALID_POINTER); 1071 AssertPtrReturn(pvData, VERR_INVALID_POINTER); 1072 AssertReturn(cbData, VERR_INVALID_PARAMETER); 1073 AssertReturn(cbTotalSize, VERR_INVALID_PARAMETER); 1074 1075 int rc = pResp->dataAdd(pvData, cbData, NULL /* Current size */); 1076 if (RT_SUCCESS(rc)) 1077 rc = pResp->dataSetStatus(cbData, cbTotalSize); 1078 1079 LogFlowFuncLeaveRC(rc); 957 1080 return rc; 958 1081 } 1082 1083 int GuestDnD::onGHSendDir(DnDGuestResponse *pResp, 1084 const char *pszPath, size_t cbPath, 1085 uint32_t fMode) 1086 { 1087 AssertPtrReturn(pResp, VERR_INVALID_POINTER); 1088 AssertPtrReturn(pszPath, VERR_INVALID_POINTER); 1089 AssertReturn(cbPath, VERR_INVALID_PARAMETER); 1090 1091 LogFlowFunc(("strDir=%s, cbPath=%zu, fMode=0x%x\n", 1092 pszPath, cbPath, fMode)); 1093 1094 int rc; 1095 char *pszDir = RTPathJoinA(pResp->dropDir().c_str(), pszPath); 1096 if (pszDir) 1097 { 1098 rc = RTDirCreateFullPath(pszDir, fMode); 1099 RTStrFree(pszDir); 1100 } 1101 else 1102 rc = VERR_NO_MEMORY; 1103 1104 if (RT_SUCCESS(rc)) 1105 rc = pResp->dataSetStatus(cbPath); 1106 1107 LogFlowFuncLeaveRC(rc); 1108 return rc; 1109 } 1110 1111 int GuestDnD::onGHSendFile(DnDGuestResponse *pResp, 1112 const char *pszPath, size_t cbPath, 1113 void *pvData, size_t cbData, uint32_t fMode) 1114 { 1115 AssertPtrReturn(pResp, VERR_INVALID_POINTER); 1116 AssertPtrReturn(pszPath, VERR_INVALID_POINTER); 1117 AssertReturn(cbPath, VERR_INVALID_PARAMETER); 1118 1119 LogFlowFunc(("strFile=%s, cbPath=%zu, fMode=0x%x\n", 1120 pszPath, cbPath, fMode)); 1121 1122 /** @todo Add file locking between calls! */ 1123 int rc; 1124 char *pszFile = RTPathJoinA(pResp->dropDir().c_str(), pszPath); 1125 if (pszFile) 1126 { 1127 RTFILE hFile; 1128 rc = RTFileOpen(&hFile, pszFile, 1129 RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_WRITE | RTFILE_O_WRITE); 1130 if (RT_SUCCESS(rc)) 1131 { 1132 rc = RTFileWrite(hFile, pvData, cbData, 1133 NULL /* No partial writes */); 1134 RTFileClose(hFile); 1135 } 1136 RTStrFree(pszFile); 1137 } 1138 else 1139 rc = VERR_NO_MEMORY; 1140 1141 if (RT_SUCCESS(rc)) 1142 rc = pResp->dataSetStatus(cbData); 1143 1144 LogFlowFuncLeaveRC(rc); 1145 return rc; 1146 } 959 1147 #endif /* VBOX_WITH_DRAG_AND_DROP_GH */ 960 1148 961 DECLCALLBACK(int) GuestDnD::notifyGuestDragAndDropEvent(void *pvExtension, uint32_t u32Function, void *pvParms, uint32_t cbParms) 1149 /* static */ 1150 DECLCALLBACK(int) GuestDnD::notifyGuestDragAndDropEvent(void *pvExtension, uint32_t u32Function, 1151 void *pvParms, uint32_t cbParms) 962 1152 { 963 1153 LogFlowFunc(("pvExtension=%p, u32Function=%RU32, pvParms=%p, cbParms=%RU32\n", … … 967 1157 if (!pGuest->m_pGuestDnD) 968 1158 return VINF_SUCCESS; 1159 1160 GuestDnD *pGuestDnD = pGuest->m_pGuestDnD; 1161 AssertPtr(pGuestDnD); 969 1162 970 1163 GuestDnDPrivate *d = static_cast<GuestDnDPrivate*>(pGuest->m_pGuestDnD->d_ptr); … … 984 1177 AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBHGACKOPDATA) == cbParms, VERR_INVALID_PARAMETER); 985 1178 AssertReturn(DragAndDropSvc::CB_MAGIC_DND_HG_ACK_OP == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER); 1179 986 1180 pResp->setDefAction(pCBData->uAction); 1181 987 1182 rc = pResp->notifyAboutGuestResponse(); 988 1183 break; … … 995 1190 AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBHGREQDATADATA) == cbParms, VERR_INVALID_PARAMETER); 996 1191 AssertReturn(DragAndDropSvc::CB_MAGIC_DND_HG_REQ_DATA == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER); 1192 997 1193 pResp->setFormat(pCBData->pszFormat); 1194 998 1195 rc = pResp->notifyAboutGuestResponse(); 999 1196 break; … … 1006 1203 AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBHGEVTPROGRESSDATA) == cbParms, VERR_INVALID_PARAMETER); 1007 1204 AssertReturn(DragAndDropSvc::CB_MAGIC_DND_HG_EVT_PROGRESS == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER); 1205 1008 1206 rc = pResp->setProgress(pCBData->uPercentage, pCBData->uState, pCBData->rc); 1009 1207 break; … … 1017 1215 AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBGHACKPENDINGDATA) == cbParms, VERR_INVALID_PARAMETER); 1018 1216 AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_ACK_PENDING == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER); 1217 1019 1218 pResp->setFormat(pCBData->pszFormat); 1020 1219 pResp->setDefAction(pCBData->uDefAction); 1021 1220 pResp->setAllActions(pCBData->uAllActions); 1221 1022 1222 rc = pResp->notifyAboutGuestResponse(); 1023 1223 break; … … 1031 1231 AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_SND_DATA == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER); 1032 1232 1033 uint32_t cbCurSize = 0; 1034 rc = pResp->dataAdd(pCBData->pvData, pCBData->cbData, &cbCurSize); 1035 if (RT_SUCCESS(rc)) 1036 { 1037 /** @todo Store pCBData->cbAllSize in the guest's response struct 1038 * if not set already. */ 1039 uint32_t cbTotalSize = pCBData->cbAllSize; 1040 unsigned int cPercentage; 1041 if (!cbTotalSize) /* Watch out for division by zero. */ 1042 cPercentage = 100; 1043 else 1044 cPercentage = cbCurSize * 100.0 / cbTotalSize; 1045 1046 /** @todo Don't use anonymous enums. */ 1047 uint32_t uState = DragAndDropSvc::DND_PROGRESS_RUNNING; 1048 if ( cbTotalSize == cbCurSize 1049 /* Empty data? Should not happen, but anyway ... */ 1050 || !cbTotalSize) 1051 { 1052 uState = DragAndDropSvc::DND_PROGRESS_COMPLETE; 1053 } 1054 1055 rc = pResp->setProgress(cPercentage, uState); 1056 } 1057 1058 /** @todo For now we instantly confirm the cancel. Check if the 1059 * guest should first clean up stuff itself and than really confirm 1060 * the cancel request by an extra message. */ 1061 if (rc == VERR_CANCELLED) 1062 pResp->setProgress(100, DragAndDropSvc::DND_PROGRESS_CANCELLED); 1233 rc = pGuestDnD->onGHSendData(pResp, pCBData->pvData, pCBData->cbData, 1234 pCBData->cbTotalSize); 1235 break; 1236 } 1237 1238 case DragAndDropSvc::GUEST_DND_GH_SND_DIR: 1239 { 1240 DragAndDropSvc::PVBOXDNDCBSNDDIRDATA pCBData = reinterpret_cast<DragAndDropSvc::PVBOXDNDCBSNDDIRDATA>(pvParms); 1241 AssertPtr(pCBData); 1242 AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBSNDDIRDATA) == cbParms, VERR_INVALID_PARAMETER); 1243 AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_SND_DIR == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER); 1244 1245 rc = pGuestDnD->onGHSendDir(pResp, pCBData->pszPath, pCBData->cbPath, pCBData->fMode); 1246 break; 1247 } 1248 1249 case DragAndDropSvc::GUEST_DND_GH_SND_FILE: 1250 { 1251 DragAndDropSvc::PVBOXDNDCBSNDFILEDATA pCBData = reinterpret_cast<DragAndDropSvc::PVBOXDNDCBSNDFILEDATA>(pvParms); 1252 AssertPtr(pCBData); 1253 AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBSNDFILEDATA) == cbParms, VERR_INVALID_PARAMETER); 1254 AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_SND_FILE == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER); 1255 1256 rc = pGuestDnD->onGHSendFile(pResp, pCBData->pszFilePath, pCBData->cbFilePath, 1257 pCBData->pvData, pCBData->cbData, pCBData->fMode); 1063 1258 break; 1064 1259 } … … 1071 1266 AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_EVT_ERROR == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER); 1072 1267 1073 /* Cleanup */1268 /* Cleanup. */ 1074 1269 pResp->reset(); 1075 1270 rc = pResp->setProgress(100, DragAndDropSvc::DND_PROGRESS_ERROR, pCBData->rc);
Note:
See TracChangeset
for help on using the changeset viewer.