- Timestamp:
- Dec 8, 2019 4:46:38 PM (5 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibClipboard.cpp
r82462 r82500 305 305 uint32_t *pcbRead) 306 306 { 307 VBoxShClReadDataMsg Msg;308 309 307 LogFlowFuncEnter(); 310 308 311 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHCL_GUEST_FN_DATA_READ, 3); 312 313 VbglHGCMParmUInt32Set(&Msg.u.v0.format, fFormat); 314 VbglHGCMParmPtrSet(&Msg.u.v0.ptr, pvData, cbData); 315 VbglHGCMParmUInt32Set(&Msg.u.v0.size, 0); 316 317 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg.hdr) + sizeof(Msg.u.v0)); 309 struct 310 { 311 VBGLIOCHGCMCALL Hdr; 312 VBoxShClParmDataRead Parms; 313 } Msg; 314 315 VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, VBOX_SHCL_GUEST_FN_DATA_READ, VBOX_SHCL_CPARMS_DATA_READ); 316 VbglHGCMParmUInt32Set(&Msg.Parms.f32Format, fFormat); 317 VbglHGCMParmPtrSet( &Msg.Parms.pData, pvData, cbData); 318 VbglHGCMParmUInt32Set(&Msg.Parms.cb32Needed, 0); 319 320 int rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg)); 318 321 if (RT_SUCCESS(rc)) 319 322 { 320 323 uint32_t cbRead; 321 rc = VbglHGCMParmUInt32Get(&Msg. u.v0.size, &cbRead);324 rc = VbglHGCMParmUInt32Get(&Msg.Parms.cb32Needed, &cbRead); 322 325 if (RT_SUCCESS(rc)) 323 326 { … … 349 352 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 350 353 AssertPtrReturn(pData, VERR_INVALID_POINTER); 351 352 int rc; 353 354 LogFlowFuncEnter(); 355 356 if (pCtx->fUseLegacyProtocol) 357 { 358 rc = VbglR3ClipboardReadData(pCtx->uClientID, pData->uFormat, pData->pvData, pData->cbData, pcbRead); 359 } 360 else 361 { 362 VBoxShClReadDataMsg Msg; 363 364 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, VBOX_SHCL_GUEST_FN_DATA_READ, VBOX_SHCL_CPARMS_READ_DATA); 365 366 VbglHGCMParmUInt64Set(&Msg.u.v1.uContext, pCtx->uContextID); 367 VbglHGCMParmUInt32Set(&Msg.u.v1.fFlags, 0); 368 VbglHGCMParmUInt32Set(&Msg.u.v1.uFormat, pData->uFormat); 369 VbglHGCMParmUInt32Set(&Msg.u.v1.cbData, pData->cbData); 370 VbglHGCMParmPtrSet(&Msg.u.v1.pvData, pData->pvData, pData->cbData); 371 372 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg.hdr) + sizeof(Msg.u.v1)); 373 if (RT_SUCCESS(rc)) 374 { 375 uint32_t cbRead; 376 rc = VbglHGCMParmUInt32Get(&Msg.u.v1.cbData, &cbRead); 377 if (RT_SUCCESS(rc)) 378 { 379 LogFlowFunc(("cbRead=%RU32\n", cbRead)); 380 381 if (cbRead > pData->cbData) 382 rc = VINF_BUFFER_OVERFLOW; 383 384 *pcbRead = cbRead; 385 } 386 } 387 } 388 389 LogFlowFuncLeaveRC(rc); 390 return rc; 354 return VbglR3ClipboardReadData(pCtx->uClientID, pData->uFormat, pData->pvData, pData->cbData, pcbRead); 391 355 } 392 356 -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc.cpp
r82488 r82500 1290 1290 } 1291 1291 1292 int shClSvcGetDataRead(PSHCLCLIENT pClient, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 1292 /** 1293 * Handles the VBOX_SHCL_GUEST_FN_DATA_READ message from the guest. 1294 */ 1295 static int shClSvcGetDataRead(PSHCLCLIENT pClient, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 1293 1296 { 1294 1297 LogFlowFuncEnter(); 1295 1298 1296 if ( ShClSvcGetMode() != VBOX_SHCL_MODE_HOST_TO_GUEST 1297 && ShClSvcGetMode() != VBOX_SHCL_MODE_BIDIRECTIONAL) 1298 { 1299 /* 1300 * Check if the service mode allows this operation and whether the guest is 1301 * supposed to be reading from the host. 1302 */ 1303 uint32_t uMode = ShClSvcGetMode(); 1304 if ( uMode == VBOX_SHCL_MODE_BIDIRECTIONAL 1305 || uMode == VBOX_SHCL_MODE_HOST_TO_GUEST) 1306 { /* likely */ } 1307 else 1299 1308 return VERR_ACCESS_DENIED; 1300 } 1301 1302 /* Is the guest supposed to read any clipboard data from the host? */ 1303 if (!(pClient->State.fFlags & SHCLCLIENTSTATE_FLAGS_READ_ACTIVE)) 1304 return VERR_WRONG_ORDER; 1305 1306 int rc; 1307 1309 1310 /// @todo r=bird: The management of the SHCLCLIENTSTATE_FLAGS_READ_ACTIVE 1311 /// makes it impossible for the guest to retrieve more than one format from 1312 /// the clipboard. I.e. it can either get the TEXT or the HTML rendering, 1313 /// but not both. So, I've disable the check. */ 1314 //ASSERT_GUEST_RETURN(pClient->State.fFlags & SHCLCLIENTSTATE_FLAGS_READ_ACTIVE, VERR_WRONG_ORDER); 1315 1316 /* 1317 * Digest parameters. 1318 * 1319 * We are dragging some legacy here from the 6.1 dev cycle, a 5 parameter 1320 * variant which prepends a 64-bit context ID (RAZ as meaning not defined), 1321 * a 32-bit flag (MBZ, no defined meaning) and switches the last two parameters. 1322 */ 1323 ASSERT_GUEST_RETURN( cParms == VBOX_SHCL_CPARMS_DATA_READ 1324 || ( cParms == VBOX_SHCL_CPARMS_DATA_READ_61B 1325 && (pClient->State.fGuestFeatures0 & VBOX_SHCL_GF_0_CONTEXT_ID)), 1326 VERR_WRONG_PARAMETER_COUNT); 1327 1328 uintptr_t iParm = 0; 1308 1329 SHCLCLIENTCMDCTX cmdCtx; 1309 1330 RT_ZERO(cmdCtx); 1331 if (cParms == VBOX_SHCL_CPARMS_DATA_READ_61B) 1332 { 1333 ASSERT_GUEST_RETURN(paParms[iParm].type == VBOX_HGCM_SVC_PARM_64BIT, VERR_WRONG_PARAMETER_TYPE); 1334 /* This has no defined meaning and was never used, however the guest passed stuff, so ignore it and leave idContext=0. */ 1335 iParm++; 1336 ASSERT_GUEST_RETURN(paParms[iParm].type == VBOX_HGCM_SVC_PARM_32BIT, VERR_WRONG_PARAMETER_TYPE); 1337 ASSERT_GUEST_RETURN(paParms[iParm].u.uint32 == 0, VERR_INVALID_FLAGS); 1338 iParm++; 1339 } 1310 1340 1311 1341 SHCLDATABLOCK dataBlock; 1312 RT_ZERO(dataBlock); 1313 1314 if (!(pClient->State.fGuestFeatures0 & VBOX_SHCL_GF_0_CONTEXT_ID)) /* Legacy, Guest Additions < 6.1. */ 1315 { 1316 if (cParms != 3) 1317 { 1318 rc = VERR_INVALID_PARAMETER; 1319 } 1320 else 1321 { 1322 rc = HGCMSvcGetU32(&paParms[0], &dataBlock.uFormat); 1323 if (RT_SUCCESS(rc)) 1324 { 1325 if (pClient->State.POD.uFormat == VBOX_SHCL_FMT_NONE) 1326 pClient->State.POD.uFormat = dataBlock.uFormat; 1327 1328 if (dataBlock.uFormat != pClient->State.POD.uFormat) 1329 { 1330 LogFlowFunc(("Invalid format (pClient->State.POD.uFormat=%RU32 vs dataBlock.uFormat=%RU32)\n", 1331 pClient->State.POD.uFormat, dataBlock.uFormat)); 1332 1333 rc = VERR_INVALID_PARAMETER; 1334 } 1335 else 1336 { 1337 rc = HGCMSvcGetBuf(&paParms[1], &dataBlock.pvData, &dataBlock.cbData); 1338 } 1339 } 1340 } 1342 ASSERT_GUEST_RETURN(paParms[iParm].type == VBOX_HGCM_SVC_PARM_32BIT, VERR_WRONG_PARAMETER_TYPE); 1343 dataBlock.uFormat = paParms[iParm].u.uint32; 1344 iParm++; 1345 if (cParms != VBOX_SHCL_CPARMS_DATA_READ_61B) 1346 { 1347 ASSERT_GUEST_RETURN(paParms[iParm].type == VBOX_HGCM_SVC_PARM_PTR, VERR_WRONG_PARAMETER_TYPE); /* Data buffer */ 1348 dataBlock.pvData = paParms[iParm].u.pointer.addr; 1349 dataBlock.cbData = paParms[iParm].u.pointer.size; 1350 iParm++; 1351 ASSERT_GUEST_RETURN(paParms[iParm].type == VBOX_HGCM_SVC_PARM_32BIT, VERR_WRONG_PARAMETER_TYPE); /*cbDataReturned*/ 1352 iParm++; 1341 1353 } 1342 1354 else 1343 1355 { 1344 if (cParms < VBOX_SHCL_CPARMS_READ_DATA) 1345 { 1346 rc = VERR_INVALID_PARAMETER; 1347 } 1348 else 1349 { 1350 /** @todo Handle paParms[1] flags. */ 1351 1352 rc = HGCMSvcGetU32(&paParms[2], &dataBlock.uFormat); 1353 if (RT_SUCCESS(rc)) 1354 { 1355 uint32_t cbData; 1356 rc = HGCMSvcGetU32(&paParms[3], &cbData); 1357 if (RT_SUCCESS(rc)) 1358 { 1359 rc = HGCMSvcGetBuf(&paParms[4], &dataBlock.pvData, &dataBlock.cbData); 1360 if (RT_SUCCESS(rc)) 1361 { 1362 if (cbData != dataBlock.cbData) 1363 { 1364 LogFlowFunc(("Invalid data (cbData=%RU32 vs dataBlock.cbData=%RU32)\n", cbData, dataBlock.cbData)); 1365 rc = VERR_INVALID_PARAMETER; 1366 } 1367 } 1368 } 1369 } 1370 } 1371 } 1356 ASSERT_GUEST_RETURN(paParms[iParm].type == VBOX_HGCM_SVC_PARM_32BIT, VERR_WRONG_PARAMETER_TYPE); /*cbDataReturned*/ 1357 iParm++; 1358 ASSERT_GUEST_RETURN(paParms[iParm].type == VBOX_HGCM_SVC_PARM_PTR, VERR_WRONG_PARAMETER_TYPE); /* Data buffer */ 1359 dataBlock.pvData = paParms[iParm].u.pointer.addr; 1360 dataBlock.cbData = paParms[iParm].u.pointer.size; 1361 iParm++; 1362 } 1363 Assert(iParm == cParms); 1364 1365 /* 1366 * For some reason we need to do this (makes absolutely no sense to bird). 1367 */ 1368 /** @todo r=bird: I really don't get why you need the State.POD.uFormat 1369 * member. I'm sure there is a reason. Incomplete code? */ 1370 if (!(pClient->State.fGuestFeatures0 & VBOX_SHCL_GF_0_CONTEXT_ID)) 1371 { 1372 if (pClient->State.POD.uFormat == VBOX_SHCL_FMT_NONE) 1373 pClient->State.POD.uFormat = dataBlock.uFormat; 1374 /// @todo r=bird: This actively breaks copying different types of data into the 1375 /// guest (first copy a text snippet, then you cannot copy any bitmaps), so I've 1376 /// disabled it. 1377 //ASSERT_GUEST_MSG_RETURN(pClient->State.POD.uFormat == dataBlock.uFormat, 1378 // ("Requested %#x, POD.uFormat=%#x\n", dataBlock.uFormat, pClient->State.POD.uFormat), 1379 // VERR_BAD_EXE_FORMAT /*VERR_INTERNAL_ERROR*/); 1380 } 1381 1382 /* 1383 * Do the reading. 1384 */ 1385 int rc = VINF_SUCCESS; 1386 uint32_t cbActual = 0; 1387 1388 /* If there is a service extension active, try reading data from it first. */ 1389 if (g_ExtState.pfnExtension) 1390 { 1391 SHCLEXTPARMS parms; 1392 RT_ZERO(parms); 1393 1394 parms.uFormat = dataBlock.uFormat; 1395 parms.u.pvData = dataBlock.pvData; 1396 parms.cbData = dataBlock.cbData; 1397 1398 g_ExtState.fReadingData = true; 1399 1400 /* Read clipboard data from the extension. */ 1401 rc = g_ExtState.pfnExtension(g_ExtState.pvExtension, VBOX_CLIPBOARD_EXT_FN_DATA_READ, &parms, sizeof(parms)); 1402 LogRelFlowFunc(("g_ExtState.fDelayedAnnouncement=%RTbool, g_ExtState.uDelayedFormats=0x%x\n", 1403 g_ExtState.fDelayedAnnouncement, g_ExtState.uDelayedFormats)); 1404 1405 /* Did the extension send the clipboard formats yet? 1406 * Otherwise, do this now. */ 1407 if (g_ExtState.fDelayedAnnouncement) 1408 { 1409 SHCLFORMATDATA FormatData; 1410 FormatData.fFlags = 0; 1411 FormatData.Formats = g_ExtState.uDelayedFormats; 1412 Assert(FormatData.Formats != VBOX_SHCL_FMT_NONE); /* There better is *any* format here now. */ 1413 1414 int rc2 = ShClSvcFormatsReport(pClient, &FormatData); 1415 AssertRC(rc2); 1416 1417 g_ExtState.fDelayedAnnouncement = false; 1418 g_ExtState.uDelayedFormats = 0; 1419 } 1420 1421 g_ExtState.fReadingData = false; 1422 1423 if (RT_SUCCESS(rc)) 1424 cbActual = parms.cbData; 1425 } 1426 1427 /* Note: The host clipboard *always* has precedence over the service extension above, 1428 * so data which has been read above might get overridden by the host clipboard eventually. */ 1429 1430 /** @todo r=bird: This precedency stuff changed with the 6.1 overhaul and I'm 1431 * not quite sure this makes sense. Imagine you think about connecting 1432 * to a VM running in a non-headless process and there is some stuff in 1433 * the host clipboard preventing you from copy & pasting via the RDP 1434 * client. I guess this means clipboard sharing over RDP is only 1435 * possible when using VBoxHeadless? 1436 * 1437 * Also, looking at the code, I think the host will _always_ return data 1438 * here. Need to test. Sigh. */ 1372 1439 1373 1440 if (RT_SUCCESS(rc)) 1374 1441 { 1375 uint32_t cbActual = 0; 1376 1377 /* If there is a service extension active, try reading data from it first. */ 1378 if (g_ExtState.pfnExtension) 1379 { 1380 SHCLEXTPARMS parms; 1381 RT_ZERO(parms); 1382 1383 parms.uFormat = pClient->State.POD.uFormat; 1384 parms.u.pvData = dataBlock.pvData; 1385 parms.cbData = dataBlock.cbData; 1386 1387 g_ExtState.fReadingData = true; 1388 1389 /* Read clipboard data from the extension. */ 1390 rc = g_ExtState.pfnExtension(g_ExtState.pvExtension, VBOX_CLIPBOARD_EXT_FN_DATA_READ, 1391 &parms, sizeof(parms)); 1392 1393 LogFlowFunc(("g_ExtState.fDelayedAnnouncement=%RTbool, g_ExtState.uDelayedFormats=0x%x\n", 1394 g_ExtState.fDelayedAnnouncement, g_ExtState.uDelayedFormats)); 1395 1396 /* Did the extension send the clipboard formats yet? 1397 * Otherwise, do this now. */ 1398 if (g_ExtState.fDelayedAnnouncement) 1399 { 1400 SHCLFORMATDATA formatData; 1401 RT_ZERO(formatData); 1402 1403 formatData.Formats = g_ExtState.uDelayedFormats; 1404 Assert(formatData.Formats != VBOX_SHCL_FMT_NONE); /* There better is *any* format here now. */ 1405 1406 int rc2 = ShClSvcFormatsReport(pClient, &formatData); 1407 AssertRC(rc2); 1408 1409 g_ExtState.fDelayedAnnouncement = false; 1410 g_ExtState.uDelayedFormats = 0; 1411 } 1412 1413 g_ExtState.fReadingData = false; 1414 1415 if (RT_SUCCESS(rc)) 1416 { 1417 cbActual = parms.cbData; 1418 } 1419 } 1420 1421 /* Note: The host clipboard *always* has precedence over the service extension above, 1422 * so data which has been read above might get overridden by the host clipboard eventually. */ 1423 1442 rc = ShClSvcImplReadData(pClient, &cmdCtx, &dataBlock, &cbActual); 1424 1443 if (RT_SUCCESS(rc)) 1425 1444 { 1426 rc = ShClSvcImplReadData(pClient, &cmdCtx, &dataBlock, &cbActual); 1427 if (RT_SUCCESS(rc)) 1428 { 1429 LogFlowFunc(("cbData=%RU32, cbActual=%RU32\n", dataBlock.cbData, cbActual)); 1430 1431 /* Return the actual size required to fullfil the request. */ 1432 if (!(pClient->State.fGuestFeatures0 & VBOX_SHCL_GF_0_CONTEXT_ID)) /* Legacy, Guest Additions < 6.1. */ 1433 { 1434 HGCMSvcSetU32(&paParms[2], cbActual); 1435 } 1436 else 1437 { 1438 HGCMSvcSetU32(&paParms[3], cbActual); 1439 } 1440 1441 /* If the data to return exceeds the buffer the guest supplies, tell it (and let it try again). */ 1442 if (cbActual >= dataBlock.cbData) 1443 rc = VINF_BUFFER_OVERFLOW; 1444 1445 if (rc == VINF_SUCCESS) 1446 { 1447 /* Only remove "read active" flag after successful read again. */ 1448 pClient->State.fFlags &= ~SHCLCLIENTSTATE_FLAGS_READ_ACTIVE; 1449 } 1445 LogFlowFunc(("cbData=%RU32, cbActual=%RU32\n", dataBlock.cbData, cbActual)); 1446 1447 /* Return the actual size required to fullfil the request. */ 1448 if (cParms != VBOX_SHCL_CPARMS_DATA_READ_61B) 1449 HGCMSvcSetU32(&paParms[2], cbActual); 1450 else 1451 HGCMSvcSetU32(&paParms[3], cbActual); 1452 1453 /* If the data to return exceeds the buffer the guest supplies, tell it (and let it try again). */ 1454 if (cbActual >= dataBlock.cbData) 1455 rc = VINF_BUFFER_OVERFLOW; 1456 1457 if (rc == VINF_SUCCESS) 1458 { 1459 /* Only remove "read active" flag after successful read again. */ 1460 /** @todo r=bird: This doesn't make any effing sense. What if the guest 1461 * wants to read another format??? */ 1462 pClient->State.fFlags &= ~SHCLCLIENTSTATE_FLAGS_READ_ACTIVE; 1450 1463 } 1451 1464 } … … 1872 1885 1873 1886 case VBOX_SHCL_GUEST_FN_DATA_READ: 1874 {1875 1887 rc = shClSvcGetDataRead(pClient, cParms, paParms); 1876 1888 break; 1877 }1878 1889 1879 1890 case VBOX_SHCL_GUEST_FN_DATA_WRITE:
Note:
See TracChangeset
for help on using the changeset viewer.