VirtualBox

Changeset 82500 in vbox for trunk/src


Ignore:
Timestamp:
Dec 8, 2019 4:46:38 PM (5 years ago)
Author:
vboxsync
Message:

SharedClipboardSvc,Vbgl: Reviewed and adjusted the handling of the VBOX_SHCL_GUEST_FN_DATA_READ message, paddling back on the parameter changes from the 6.1 dev cycle and fixing a couple of bugs introduced (buggy code commented out and marked with @todos). Also documented the message. bugref:9437

Location:
trunk/src/VBox
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibClipboard.cpp

    r82462 r82500  
    305305                                        uint32_t *pcbRead)
    306306{
    307     VBoxShClReadDataMsg Msg;
    308 
    309307    LogFlowFuncEnter();
    310308
    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));
    318321    if (RT_SUCCESS(rc))
    319322    {
    320323        uint32_t cbRead;
    321         rc = VbglHGCMParmUInt32Get(&Msg.u.v0.size, &cbRead);
     324        rc = VbglHGCMParmUInt32Get(&Msg.Parms.cb32Needed, &cbRead);
    322325        if (RT_SUCCESS(rc))
    323326        {
     
    349352    AssertPtrReturn(pCtx,  VERR_INVALID_POINTER);
    350353    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);
    391355}
    392356
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc.cpp

    r82488 r82500  
    12901290}
    12911291
    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 */
     1295static int shClSvcGetDataRead(PSHCLCLIENT pClient, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
    12931296{
    12941297    LogFlowFuncEnter();
    12951298
    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
    12991308        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;
    13081329    SHCLCLIENTCMDCTX cmdCtx;
    13091330    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    }
    13101340
    13111341    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++;
    13411353    }
    13421354    else
    13431355    {
    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. */
    13721439
    13731440    if (RT_SUCCESS(rc))
    13741441    {
    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);
    14241443        if (RT_SUCCESS(rc))
    14251444        {
    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;
    14501463            }
    14511464        }
     
    18721885
    18731886        case VBOX_SHCL_GUEST_FN_DATA_READ:
    1874         {
    18751887            rc = shClSvcGetDataRead(pClient, cParms, paParms);
    18761888            break;
    1877         }
    18781889
    18791890        case VBOX_SHCL_GUEST_FN_DATA_WRITE:
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette