Changeset 85423 in vbox for trunk/src/VBox/Main/src-client
- Timestamp:
- Jul 23, 2020 8:12:42 AM (5 years ago)
- Location:
- trunk/src/VBox/Main/src-client
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-client/GuestDnDPrivate.cpp
r85402 r85423 273 273 } 274 274 275 int GuestDnDResponse::setProgress(unsigned uPercentage, 276 uint32_t uStatus, 275 int GuestDnDResponse::setProgress(unsigned uPercentage, uint32_t uStatus, 277 276 int rcOp /* = VINF_SUCCESS */, const Utf8Str &strMsg /* = "" */) 278 277 { 279 RT_NOREF(rcOp); 280 LogFlowFunc(("uStatus=%RU32, uPercentage=%RU32, rcOp=%Rrc, strMsg=%s\n", 281 uStatus, uPercentage, rcOp, strMsg.c_str())); 278 LogFlowFunc(("uPercentage=%u, uStatus=%RU32, , rcOp=%Rrc, strMsg=%s\n", 279 uPercentage, uStatus, rcOp, strMsg.c_str())); 280 281 HRESULT hr = S_OK; 282 283 BOOL fCompleted = FALSE; 284 BOOL fCanceled = FALSE; 282 285 283 286 int rc = VINF_SUCCESS; 287 284 288 if (!m_pProgress.isNull()) 285 289 { 286 BOOL fCompleted; 287 HRESULT hr = m_pProgress->COMGETTER(Completed)(&fCompleted); 290 hr = m_pProgress->COMGETTER(Completed)(&fCompleted); 288 291 AssertComRC(hr); 289 292 290 BOOL fCanceled;291 293 hr = m_pProgress->COMGETTER(Canceled)(&fCanceled); 292 294 AssertComRC(hr); 293 295 294 LogFlowFunc(("Current: fCompleted=%RTbool, fCanceled=%RTbool\n", fCompleted, fCanceled)); 295 296 if (!fCompleted) 297 { 298 switch (uStatus) 296 LogFlowFunc(("Progress fCompleted=%RTbool, fCanceled=%RTbool\n", fCompleted, fCanceled)); 297 } 298 299 switch (uStatus) 300 { 301 case DragAndDropSvc::DND_PROGRESS_ERROR: 302 { 303 LogRel(("DnD: Guest reported error %Rrc\n", rcOp)); 304 305 if ( !m_pProgress.isNull() 306 && !fCompleted) 307 hr = m_pProgress->i_notifyComplete(VBOX_E_IPRT_ERROR, 308 COM_IIDOF(IGuest), 309 m_pParent->getComponentName(), strMsg.c_str()); 310 reset(); 311 break; 312 } 313 314 case DragAndDropSvc::DND_PROGRESS_CANCELLED: 315 { 316 LogRel2(("DnD: Guest cancelled operation\n")); 317 318 if ( !m_pProgress.isNull() 319 && !fCompleted) 299 320 { 300 case DragAndDropSvc::DND_PROGRESS_ERROR: 321 hr = m_pProgress->Cancel(); 322 AssertComRC(hr); 323 hr = m_pProgress->i_notifyComplete(S_OK); 324 AssertComRC(hr); 325 } 326 327 reset(); 328 break; 329 } 330 331 case DragAndDropSvc::DND_PROGRESS_RUNNING: 332 RT_FALL_THROUGH(); 333 case DragAndDropSvc::DND_PROGRESS_COMPLETE: 334 { 335 LogRel2(("DnD: Guest reporting running/completion status with %u%%\n", uPercentage)); 336 337 if ( !m_pProgress.isNull() 338 && !fCompleted) 339 { 340 hr = m_pProgress->SetCurrentOperationProgress(uPercentage); 341 AssertComRC(hr); 342 if ( uStatus == DragAndDropSvc::DND_PROGRESS_COMPLETE 343 || uPercentage >= 100) 301 344 { 302 hr = m_pProgress->i_notifyComplete(VBOX_E_IPRT_ERROR,303 COM_IIDOF(IGuest),304 m_pParent->getComponentName(), strMsg.c_str());305 reset();306 break;307 }308 309 case DragAndDropSvc::DND_PROGRESS_CANCELLED:310 {311 hr = m_pProgress->Cancel();312 AssertComRC(hr);313 345 hr = m_pProgress->i_notifyComplete(S_OK); 314 346 AssertComRC(hr); 315 316 reset();317 break;318 347 } 319 320 case DragAndDropSvc::DND_PROGRESS_RUNNING:321 case DragAndDropSvc::DND_PROGRESS_COMPLETE:322 {323 if (!fCanceled)324 {325 hr = m_pProgress->SetCurrentOperationProgress(uPercentage);326 AssertComRC(hr);327 if ( uStatus == DragAndDropSvc::DND_PROGRESS_COMPLETE328 || uPercentage >= 100)329 {330 hr = m_pProgress->i_notifyComplete(S_OK);331 AssertComRC(hr);332 }333 }334 break;335 }336 337 default:338 break;339 348 } 340 } 341 349 break; 350 } 351 352 default: 353 break; 354 } 355 356 if (!m_pProgress.isNull()) 357 { 342 358 hr = m_pProgress->COMGETTER(Completed)(&fCompleted); 343 359 AssertComRC(hr); … … 345 361 AssertComRC(hr); 346 362 347 LogFlowFunc((" New:fCompleted=%RTbool, fCanceled=%RTbool\n", fCompleted, fCanceled));363 LogFlowFunc(("Progress fCompleted=%RTbool, fCanceled=%RTbool\n", fCompleted, fCanceled)); 348 364 } 349 365 … … 942 958 pData->cbExtra, pData->cbProcessed, pData->getRemaining(), cbDataAdd)); 943 959 944 if (!pResp) 960 if ( !pResp 961 || !cbDataAdd) /* Only update if something really changes. */ 945 962 return VINF_SUCCESS; 946 963 … … 948 965 pData->addProcessed(cbDataAdd); 949 966 950 int rc = pResp->setProgress(pData->getPercentComplete(), 967 const uint8_t uPercent = pData->getPercentComplete(); 968 969 LogRel2(("DnD: Transfer %RU8%% complete\n", uPercent)); 970 971 int rc = pResp->setProgress(uPercent, 951 972 pData->isComplete() 952 973 ? DND_PROGRESS_COMPLETE -
trunk/src/VBox/Main/src-client/GuestDnDTargetImpl.cpp
r85402 r85423 648 648 pSendCtx->pResp = pResp; 649 649 pSendCtx->uScreenID = aScreenId; 650 pSendCtx->strFmtReq = aFormat; 651 650 651 pSendCtx->Meta.strFmt = aFormat; 652 652 pSendCtx->Meta.add(aData); 653 653 … … 820 820 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 821 821 822 /** @todo Add support for multiple HOST_DND_HG_SND_DATA messages in case of more than 64K data! */ 823 if (pCtx->Meta.cbData > _64K) 824 return VERR_NOT_IMPLEMENTED; 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 830 GuestDnDMsg Msg; 831 Msg.setType(HOST_DND_HG_SND_DATA); 832 if (m_DataBase.uProtocolVersion < 3) 833 { 834 Msg.setNextUInt32(pCtx->uScreenID); /* 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 */ 838 /* Fill in the current data block size to send. 839 * Note: Only supports uint32_t. */ 840 Msg.setNextUInt32((uint32_t)pCtx->Meta.cbData); /* cbData */ 841 } 842 else 843 { 844 Msg.setNextUInt32(0); /** @todo ContextID 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. */ 849 } 850 851 int rc = GUESTDNDINST()->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms()); 822 uint8_t *pvData = (uint8_t *)pCtx->Meta.pvData; 823 size_t cbData = pCtx->Meta.cbData; 824 825 int rc = VINF_SUCCESS; 826 827 const size_t cbFmt = pCtx->Meta.strFmt.length() + 1; /* Include terminator. */ 828 const char *pcszFmt = pCtx->Meta.strFmt.c_str(); 829 830 LogFlowFunc(("uProto=%u, szFmt=%s, cbFmt=%RU32, cbData=%zu\n", m_DataBase.uProtocolVersion, pcszFmt, cbFmt, cbData)); 831 832 LogRel2(("DnD: Sending meta data to guest as '%s' (%zu bytes)\n", pcszFmt, cbData)); 833 834 #ifdef DEBUG 835 RTCList<RTCString> lstFilesURI = RTCString((char *)pvData, cbData).split("\r\n"); 836 LogFlowFunc(("lstFilesURI=%zu\n", lstFilesURI.size())); 837 for (size_t i = 0; i < lstFilesURI.size(); i++) 838 LogFlowFunc(("\t%s\n", lstFilesURI.at(i).c_str())); 839 #endif 840 841 uint8_t *pvChunk = pvData; 842 size_t cbChunk = RT_MIN(mData.mcbBlockSize, cbData); 843 while (cbData) 844 { 845 GuestDnDMsg Msg; 846 Msg.setType(HOST_DND_HG_SND_DATA); 847 848 if (m_DataBase.uProtocolVersion < 3) 849 { 850 Msg.setNextUInt32(pCtx->uScreenID); /* uScreenId */ 851 Msg.setNextPointer(unconst(pcszFmt), (uint32_t)cbFmt); /* pvFormat */ 852 Msg.setNextUInt32((uint32_t)cbFmt); /* cbFormat */ 853 Msg.setNextPointer(pvChunk, (uint32_t)cbChunk); /* pvData */ 854 /* Fill in the current data block size to send. 855 * Note: Only supports uint32_t. */ 856 Msg.setNextUInt32((uint32_t)cbChunk); /* cbData */ 857 } 858 else 859 { 860 Msg.setNextUInt32(0); /** @todo ContextID not used yet. */ 861 Msg.setNextPointer(pvChunk, (uint32_t)cbChunk); /* pvData */ 862 Msg.setNextUInt32((uint32_t)cbChunk); /* cbData */ 863 Msg.setNextPointer(NULL, 0); /** @todo pvChecksum; not used yet. */ 864 Msg.setNextUInt32(0); /** @todo cbChecksum; not used yet. */ 865 } 866 867 rc = GUESTDNDINST()->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms()); 868 if (RT_FAILURE(rc)) 869 break; 870 871 pvChunk += cbChunk; 872 AssertBreakStmt(cbData >= cbChunk, VERR_BUFFER_UNDERFLOW); 873 cbData -= cbChunk; 874 } 875 852 876 if (RT_SUCCESS(rc)) 853 877 { 854 rc = updateProgress(pCtx, pCtx->pResp, pCtx->Meta.cbData);878 rc = updateProgress(pCtx, pCtx->pResp, (uint32_t)pCtx->Meta.cbData); 855 879 AssertRC(rc); 856 880 } … … 875 899 GuestDnDMsg Msg; 876 900 Msg.setType(HOST_DND_HG_SND_DATA_HDR); 901 902 LogRel2(("DnD: Sending meta data header to guest (%RU64 bytes total data, %RU32 bytes meta data, %RU64 objects)\n", 903 pCtx->getTotal(), pCtx->Meta.cbData, pCtx->Transfer.cObjToProcess)); 877 904 878 905 Msg.setNextUInt32(0); /** @todo uContext; not used yet. */ … … 976 1003 pMsg->setNextUInt64(cbSize); /* uSize */ 977 1004 978 LogRel2(("DnD: Transferring host file '%s' to guest ( %zu bytes, mode %#x)\n",979 pcszSrcPath, cbSize, fMode));1005 LogRel2(("DnD: Transferring host file '%s' to guest (as '%s', %zu bytes, mode %#x)\n", 1006 pcszSrcPath, pcszDstPath, cbSize, fMode)); 980 1007 981 1008 /** @todo Set progress object title to current file being transferred? */ … … 1051 1078 if (RT_SUCCESS(rc)) 1052 1079 { 1053 pCtx->addProcessed(cbRead);1054 1055 1080 LogFlowFunc(("cbBufe=%zu, cbRead=%RU32\n", cbBuf, cbRead)); 1056 1081 … … 1074 1099 } 1075 1100 1101 int rc2 = updateProgress(pCtx, pCtx->pResp, (uint32_t)cbRead); 1102 AssertRC(rc2); 1103 1104 /* DnDTransferObjectRead() will return VINF_EOF if reading is complete. */ 1105 if (rc == VINF_EOF) 1106 rc = VINF_SUCCESS; 1107 1076 1108 if (DnDTransferObjectIsComplete(pObj)) /* Done reading? */ 1077 {1078 1109 LogRel2(("DnD: Transferring host file '%s' to guest complete\n", pcszSrcPath)); 1079 1080 /* DnDTransferObjectRead() returns VINF_EOF when finished reading the entire file,1081 * but we don't want this here -- so just set VINF_SUCCESS. */1082 rc = VINF_SUCCESS;1083 }1084 1110 } 1085 1111 else … … 1099 1125 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 1100 1126 1101 LogFlowFunc(("pThis=%p, uMsg=%RU32\n", pThis, uMsg)); 1127 /* At the moment we only have one transfer list per transfer. */ 1128 PDNDTRANSFERLIST pList = &pCtx->Transfer.List; 1129 1130 LogFlowFunc(("pThis=%p, pList=%p, uMsg=%RU32\n", pThis, pList, uMsg)); 1102 1131 1103 1132 int rc = VINF_SUCCESS; … … 1126 1155 GuestDnDMsg *pMsg = new GuestDnDMsg(); 1127 1156 1128 rc = pThis->i_sendTransfer DataLoop(pCtx, pMsg);1157 rc = pThis->i_sendTransferListObject(pCtx, pList, pMsg); 1129 1158 if (rc == VINF_EOF) /* Transfer complete? */ 1130 1159 { … … 1171 1200 1172 1201 rc = pCtx->pResp->setProgress(100, DND_PROGRESS_ERROR, pCBData->rc, 1173 1202 GuestDnDTarget::i_guestErrorToString(pCBData->rc)); 1174 1203 if (RT_SUCCESS(rc)) 1175 1204 { … … 1354 1383 * Extract transfer list from current meta data. 1355 1384 */ 1356 rc = DnDTransferListAppendPathsFromBuffer(&pCtx->Transfer.List, DNDTRANSFERLISTFMT_NATIVE, 1357 (const char *)pCtx->Meta.pvData, pCtx->Meta.cbData, "\n", DNDTRANSFERLIST_FLAGS_NONE); 1385 rc = DnDTransferListAppendPathsFromBuffer(&pCtx->Transfer.List, DNDTRANSFERLISTFMT_URI, 1386 (const char *)pCtx->Meta.pvData, pCtx->Meta.cbData, DND_PATH_SEPARATOR, 1387 DNDTRANSFERLIST_FLAGS_RECURSIVE); 1358 1388 if (RT_FAILURE(rc)) 1359 1389 break; … … 1362 1392 * Update internal state to reflect everything we need to work with it. 1363 1393 */ 1364 pCtx->cbExtra = DnDTransferListObjTotalBytes(&pCtx->Transfer.List); 1394 pCtx->cbExtra = DnDTransferListObjTotalBytes(&pCtx->Transfer.List); 1395 /* cbExtra can be 0, if all files are of 0 bytes size. */ 1396 pCtx->Transfer.cObjToProcess = DnDTransferListObjCount(&pCtx->Transfer.List); 1397 AssertBreakStmt(pCtx->Transfer.cObjToProcess, rc = VERR_INVALID_PARAMETER); 1398 1399 /* Update the meta data to have the current root transfer entries in the right shape. */ 1400 if (DnDMIMEHasFileURLs(pCtx->Meta.strFmt.c_str(), RTSTR_MAX)) 1401 { 1402 /* Save original format we're still going to use after updating the actual meta data. */ 1403 Utf8Str strFmt = pCtx->Meta.strFmt; 1404 1405 /* Reset stale data. */ 1406 pCtx->Meta.reset(); 1407 1408 void *pvData; 1409 size_t cbData; 1410 #ifdef DEBUG 1411 rc = DnDTransferListGetRootsEx(&pCtx->Transfer.List, DNDTRANSFERLISTFMT_URI, "" /* pcszPathBase */, 1412 "\n" /* pcszSeparator */, (char **)&pvData, &cbData); 1413 AssertRCReturn(rc, rc); 1414 LogFlowFunc(("URI data:\n%s", (char *)pvData)); 1415 RTMemFree(pvData); 1416 cbData = 0; 1417 #endif 1418 rc = DnDTransferListGetRoots(&pCtx->Transfer.List, DNDTRANSFERLISTFMT_URI, 1419 (char **)&pvData, &cbData); 1420 AssertRCReturn(rc, rc); 1421 1422 /* pCtx->Meta now owns the allocated data. */ 1423 pCtx->Meta.strFmt = strFmt; 1424 pCtx->Meta.pvData = pvData; 1425 pCtx->Meta.cbData = cbData; 1426 pCtx->Meta.cbAllocated = cbData; 1427 } 1365 1428 1366 1429 /* … … 1444 1507 } 1445 1508 1446 int GuestDnDTarget::i_sendTransferDataLoop(GuestDnDSendCtx *pCtx, GuestDnDMsg *pMsg) 1509 /** 1510 * Sends the next object of a transfer list to the guest. 1511 * 1512 * @returns VBox status code. VINF_EOF if the transfer list is complete. 1513 * @param pCtx Send context to use. 1514 * @param pList Transfer list to use. 1515 * @param pMsg Message to store send data into. 1516 */ 1517 int GuestDnDTarget::i_sendTransferListObject(GuestDnDSendCtx *pCtx, PDNDTRANSFERLIST pList, GuestDnDMsg *pMsg) 1447 1518 { 1448 1519 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 1520 AssertPtrReturn(pList, VERR_INVALID_POINTER); 1449 1521 AssertPtrReturn(pMsg, VERR_INVALID_POINTER); 1450 1522 1451 1523 int rc = updateProgress(pCtx, pCtx->pResp); 1452 AssertRC (rc);1453 1454 if ( pCtx->isComplete()1455 && pCtx->Transfer.isComplete())1456 {1524 AssertRCReturn(rc, rc); 1525 1526 if (pCtx->isComplete()) 1527 { 1528 Assert(pCtx->Transfer.isComplete()); 1457 1529 return VINF_EOF; 1458 1530 } 1459 1531 1460 PDNDTRANSFEROBJECT pObj = DnDTransferListObjGetFirst(&pCtx->Transfer.List); 1461 if (!pObj) 1462 return VERR_WRONG_ORDER; 1532 PDNDTRANSFEROBJECT pObj = DnDTransferListObjGetFirst(pList); 1533 AssertPtrReturn(pObj, VERR_WRONG_ORDER); 1463 1534 1464 1535 switch (DnDTransferObjectGetType(pObj)) … … 1477 1548 } 1478 1549 1479 if ( DnDTransferObjectIsComplete(pObj) 1480 || RT_FAILURE(rc)) 1481 DnDTransferListObjRemoveFirst(&pCtx->Transfer.List); 1550 if ( RT_SUCCESS(rc) 1551 && DnDTransferObjectIsComplete(pObj)) 1552 { 1553 DnDTransferListObjRemove(pList, pObj); 1554 pObj = NULL; 1555 1556 AssertReturn(pCtx->Transfer.cObjProcessed + 1 <= pCtx->Transfer.cObjToProcess, VERR_WRONG_ORDER); 1557 pCtx->Transfer.cObjProcessed++; 1558 1559 pCtx->Transfer.fObjState = DND_OBJ_STATE_NONE; 1560 } 1482 1561 1483 1562 LogFlowFuncLeaveRC(rc);
Note:
See TracChangeset
for help on using the changeset viewer.