VirtualBox

Changeset 81768 in vbox for trunk/src/VBox/HostServices


Ignore:
Timestamp:
Nov 11, 2019 4:36:41 PM (5 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
134559
Message:

Shared Clipboard: Update.

Location:
trunk/src/VBox/HostServices/SharedClipboard
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-internal.h

    r81746 r81768  
    7272    SHCLTRANSFERDIR enmTransferDir;
    7373} SHCLCLIENTTRANSFERSTATE, *PSHCLCLIENTTRANSFERSTATE;
     74
     75/**
     76 * Structure for holding a single POD (plain old data) transfer.
     77 * This mostly is plain text, but also can be stuff like bitmap (BMP) or other binary data.
     78 */
     79typedef struct SHCLCLIENTPODSTATE
     80{
     81    /** POD transfer direction. */
     82    SHCLTRANSFERDIR         enmDir;
     83    /** Format of the data to be read / written. */
     84    SHCLFORMAT              uFormat;
     85    /** How much data (in bytes) to read/write for the current operation. */
     86    uint64_t                cbToReadWriteTotal;
     87    /** How much data (in bytes) already has been read/written for the current operation. */
     88    uint64_t                cbReadWritten;
     89    /** Timestamp (in ms) of Last read/write operation. */
     90    uint64_t                tsLastReadWrittenMs;
     91} SHCLCLIENTPODSTATE, *PSHCLCLIENTPODSTATE;
     92
     93/** No Shared Clipboard client flags defined. */
     94#define SHCLCLIENTSTATE_FLAGS_NONE              0
     95/** Client has a guest read operation active. */
     96#define SHCLCLIENTSTATE_FLAGS_READ_ACTIVE       RT_BIT(0)
     97/** Client has a guest write operation active. */
     98#define SHCLCLIENTSTATE_FLAGS_WRITE_ACTIVE      RT_BIT(1)
    7499
    75100/**
     
    96121    /** Where the transfer sources its data from. */
    97122    SHCLSOURCE              enmSource;
     123    /** Client state flags of type SHCLCLIENTSTATE_FLAGS_. */
     124    uint32_t                fFlags;
     125    /** POD (plain old data) state. */
     126    SHCLCLIENTPODSTATE      POD;
    98127    /** The client's transfers state. */
    99128    SHCLCLIENTTRANSFERSTATE Transfers;
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-win.cpp

    r81746 r81768  
    170170                                       void **ppvData, uint32_t *pcbData)
    171171{
    172     LogFlowFunc(("cfFormat=%u\n", cfFormat));
    173 
    174172    SHCLDATAREQ dataReq;
    175173    RT_ZERO(dataReq);
     
    177175    dataReq.uFmt   = SharedClipboardWinClipboardFormatToVBox(cfFormat);
    178176    dataReq.cbSize = _64K; /** @todo Make this more dynamic. */
     177
     178    LogFlowFunc(("cfFormat=%u -> uFmt=0x%x\n", cfFormat, dataReq.uFmt));
     179
     180    if (dataReq.uFmt == VBOX_SHCL_FMT_NONE)
     181    {
     182        LogRel2(("Shared Clipbaord: Windows format %u not supported, ingoring\n", cfFormat));
     183        return VERR_NOT_SUPPORTED;
     184    }
    179185
    180186    SHCLEVENTID uEvent = 0;
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc.cpp

    r81746 r81768  
    462462            uint32_t uSrcFmt = VBOX_SHCL_FMT_NONE;
    463463            uint32_t uDstFmt = VBOX_SHCL_FMT_NONE;
    464             rc = HGCMSvcGetU32(&pMsg->paParms[1] /* uFormat */, &uSrcFmt);
     464            rc = HGCMSvcGetU32(&pMsg->paParms[2] /* uFormat */, &uSrcFmt);
    465465            if (RT_SUCCESS(rc))
    466466            {
     
    474474                    AssertStmt(uSrcFmt == VBOX_SHCL_FMT_NONE, uSrcFmt = VBOX_SHCL_FMT_NONE);
    475475
     476                LogFlowFunc(("uSrcFmt=0x%x, uDstFmt=0x%x\n", uSrcFmt, uDstFmt));
     477
    476478                /* Remove format we're going to return from the queued message. */
    477479                uSrcFmt &= ~uDstFmt;
    478                 HGCMSvcSetU32(&pMsg->paParms[1], uSrcFmt);
     480                HGCMSvcSetU32(&pMsg->paParms[2], uSrcFmt);
    479481
    480482                /* Only report back one format at a time. */
     
    10101012                    fDonePending = true;
    10111013                }
    1012                 else if (pClient->Pending.uType == VBOX_SHCL_GUEST_FN_GET_HOST_MSG_OLD) /* Legacy */
     1014                else if (pClient->Pending.uType == VBOX_SHCL_GUEST_FN_GET_HOST_MSG_OLD) /* Legacy, Guest Additions < 6.1. */
    10131015                {
    10141016                    bool fRemove;
     
    10731075
    10741076    PSHCLCLIENTMSG pMsgReadData = shclSvcMsgAlloc(VBOX_SHCL_HOST_MSG_READ_DATA,
    1075                                                   VBOX_SHCL_CPARMS_READ_DATA);
     1077                                                  VBOX_SHCL_CPARMS_READ_DATA_REQ);
    10761078    if (pMsgReadData)
    10771079    {
    10781080        const SHCLEVENTID uEvent = ShClEventIDGenerate(&pClient->Events);
     1081
     1082        LogFlowFunc(("uFmt=0x%x\n", pDataReq->uFmt));
    10791083
    10801084        HGCMSvcSetU64(&pMsgReadData->paParms[0], VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID,
    10811085                                                                          pClient->Events.uID, uEvent));
    1082         HGCMSvcSetU32(&pMsgReadData->paParms[1], pDataReq->uFmt);
    1083         HGCMSvcSetU32(&pMsgReadData->paParms[2], pClient->State.cbChunkSize);
     1086        HGCMSvcSetU32(&pMsgReadData->paParms[1], 0 /* fFlags */);
     1087        HGCMSvcSetU32(&pMsgReadData->paParms[2], pDataReq->uFmt);
     1088        HGCMSvcSetU32(&pMsgReadData->paParms[3], pClient->State.cbChunkSize);
    10841089
    10851090        rc = shclSvcMsgAdd(pClient, pMsgReadData, true /* fAppend */);
     
    11171122
    11181123    SHCLEVENTID uEvent;
    1119     if (!(pClient->State.fGuestFeatures0 & VBOX_SHCL_GF_0_CONTEXT_ID)) /* Legacy */
     1124    if (!(pClient->State.fGuestFeatures0 & VBOX_SHCL_GF_0_CONTEXT_ID)) /* Legacy, Guest Additions < 6.1. */
    11201125    {
    11211126        /* Older Guest Additions (<= VBox 6.0) did not have any context ID handling, so we ASSUME that the last event registered
     
    11781183            {
    11791184#endif
     1185                pClient->State.fFlags |= SHCLCLIENTSTATE_FLAGS_READ_ACTIVE;
     1186
    11801187                rc = shclSvcClientWakeup(pClient);
    1181 
    11821188#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
    11831189            }
     
    11921198}
    11931199
    1194 int shclSvcGetDataWrite(PSHCLCLIENT pClient, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
     1200int shClSvcGetDataRead(PSHCLCLIENT pClient, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
     1201{
     1202    LogFlowFuncEnter();
     1203
     1204    if (   ShClSvcGetMode() != VBOX_SHCL_MODE_HOST_TO_GUEST
     1205        && ShClSvcGetMode() != VBOX_SHCL_MODE_BIDIRECTIONAL)
     1206    {
     1207        return VERR_ACCESS_DENIED;
     1208    }
     1209
     1210    /* Is the guest supposed to read any clipboard data from the host? */
     1211    if (!(pClient->State.fFlags & SHCLCLIENTSTATE_FLAGS_READ_ACTIVE))
     1212        return VERR_WRONG_ORDER;
     1213
     1214    int rc;
     1215
     1216    SHCLCLIENTCMDCTX cmdCtx;
     1217    RT_ZERO(cmdCtx);
     1218
     1219    SHCLDATABLOCK dataBlock;
     1220    RT_ZERO(dataBlock);
     1221
     1222    if (!(pClient->State.fGuestFeatures0 & VBOX_SHCL_GF_0_CONTEXT_ID)) /* Legacy, Guest Additions < 6.1. */
     1223    {
     1224        if (cParms != 3)
     1225        {
     1226            rc = VERR_INVALID_PARAMETER;
     1227        }
     1228        else
     1229        {
     1230            rc = HGCMSvcGetU32(&paParms[0], &dataBlock.uFormat);
     1231            if (RT_SUCCESS(rc))
     1232            {
     1233                if (pClient->State.POD.uFormat == VBOX_SHCL_FMT_NONE)
     1234                    pClient->State.POD.uFormat = dataBlock.uFormat;
     1235
     1236                if (dataBlock.uFormat != pClient->State.POD.uFormat)
     1237                {
     1238                    LogFlowFunc(("Invalid format (pClient->State.POD.uFormat=%RU32 vs dataBlock.uFormat=%RU32\n",
     1239                                 pClient->State.POD.uFormat = dataBlock.uFormat));
     1240
     1241                    rc = VERR_INVALID_PARAMETER;
     1242                }
     1243                else
     1244                {
     1245                    rc = HGCMSvcGetBuf(&paParms[1], &dataBlock.pvData, &dataBlock.cbData);
     1246                }
     1247            }
     1248        }
     1249    }
     1250    else
     1251    {
     1252        if (cParms < VBOX_SHCL_CPARMS_READ_DATA)
     1253        {
     1254            rc = VERR_INVALID_PARAMETER;
     1255        }
     1256        else
     1257        {
     1258            /** @todo Handle paParms[1] flags. */
     1259
     1260            rc = HGCMSvcGetU32(&paParms[2], &dataBlock.uFormat);
     1261            if (RT_SUCCESS(rc))
     1262            {
     1263                uint32_t cbData;
     1264                rc = HGCMSvcGetU32(&paParms[3], &cbData);
     1265                if (RT_SUCCESS(rc))
     1266                {
     1267                    rc = HGCMSvcGetBuf(&paParms[4], &dataBlock.pvData, &dataBlock.cbData);
     1268                    if (RT_SUCCESS(rc))
     1269                    {
     1270                        if (cbData != dataBlock.cbData)
     1271                        {
     1272                            LogFlowFunc(("Invalid data (cbData=%RU32 vs dataBlock.cbData=%RU32)\n", cbData, dataBlock.cbData));
     1273                            rc = VERR_INVALID_PARAMETER;
     1274                        }
     1275                    }
     1276                }
     1277            }
     1278        }
     1279    }
     1280
     1281    if (RT_SUCCESS(rc))
     1282    {
     1283        uint32_t cbActual = 0;
     1284
     1285        /* If there is a service extension active, try reading data from it first. */
     1286        if (g_ExtState.pfnExtension)
     1287        {
     1288            SHCLEXTPARMS parms;
     1289            RT_ZERO(parms);
     1290
     1291            parms.uFormat  = pClient->State.POD.uFormat;
     1292            parms.u.pvData = dataBlock.pvData;
     1293            parms.cbData   = dataBlock.cbData;
     1294
     1295            g_ExtState.fReadingData = true;
     1296
     1297            /* Read clipboard data from the extension. */
     1298            rc = g_ExtState.pfnExtension(g_ExtState.pvExtension, VBOX_CLIPBOARD_EXT_FN_DATA_READ,
     1299                                         &parms, sizeof(parms));
     1300
     1301            LogFlowFunc(("g_ExtState.fDelayedAnnouncement=%RTbool, g_ExtState.uDelayedFormats=0x%x\n",
     1302                         g_ExtState.fDelayedAnnouncement, g_ExtState.uDelayedFormats));
     1303
     1304            /* Did the extension send the clipboard formats yet?
     1305             * Otherwise, do this now. */
     1306            if (g_ExtState.fDelayedAnnouncement)
     1307            {
     1308                SHCLFORMATDATA formatData;
     1309                RT_ZERO(formatData);
     1310
     1311                formatData.uFormats = g_ExtState.uDelayedFormats;
     1312                Assert(formatData.uFormats != VBOX_SHCL_FMT_NONE); /* There better is *any* format here now. */
     1313
     1314                int rc2 = ShClSvcFormatsReport(pClient, &formatData);
     1315                AssertRC(rc2);
     1316
     1317                g_ExtState.fDelayedAnnouncement = false;
     1318                g_ExtState.uDelayedFormats = 0;
     1319            }
     1320
     1321            g_ExtState.fReadingData = false;
     1322
     1323            if (RT_SUCCESS(rc))
     1324            {
     1325                cbActual = parms.cbData;
     1326            }
     1327        }
     1328
     1329        /* Note: The host clipboard *always* has precedence over the service extension above,
     1330         *       so data which has been read above might get overridden by the host clipboard eventually. */
     1331
     1332        if (RT_SUCCESS(rc))
     1333        {
     1334            rc = ShClSvcImplReadData(pClient, &cmdCtx, &dataBlock, &cbActual);
     1335            if (RT_SUCCESS(rc))
     1336            {
     1337                LogFlowFunc(("cbData=%RU32, cbActual=%RU32\n", dataBlock.cbData, cbActual));
     1338
     1339                /* Return the actual size required to fullfil the request. */
     1340                if (!(pClient->State.fGuestFeatures0 & VBOX_SHCL_GF_0_CONTEXT_ID)) /* Legacy, Guest Additions < 6.1. */
     1341                {
     1342                    HGCMSvcSetU32(&paParms[2], cbActual);
     1343                }
     1344                else
     1345                {
     1346                    HGCMSvcSetU32(&paParms[3], cbActual);
     1347                }
     1348
     1349                /* If the data to return exceeds the buffer the guest supplies, tell it (and let it try again). */
     1350                if (cbActual >= dataBlock.cbData)
     1351                    rc = VINF_BUFFER_OVERFLOW;
     1352
     1353                if (rc == VINF_SUCCESS)
     1354                {
     1355                    /* Only remove "read active" flag after successful read again. */
     1356                    pClient->State.fFlags &= ~SHCLCLIENTSTATE_FLAGS_READ_ACTIVE;
     1357                }
     1358            }
     1359        }
     1360    }
     1361
     1362    LogFlowFuncLeaveRC(rc);
     1363    return rc;
     1364}
     1365
     1366int shClSvcGetDataWrite(PSHCLCLIENT pClient, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
    11951367{
    11961368    LogFlowFuncEnter();
     
    11991371        && ShClSvcGetMode() != VBOX_SHCL_MODE_BIDIRECTIONAL)
    12001372    {
    1201         return VERR_NOT_SUPPORTED;
    1202     }
     1373        return VERR_ACCESS_DENIED;
     1374    }
     1375
     1376    /* Is the guest supposed to write any clipboard data from the host? */
     1377    if (!(pClient->State.fFlags & SHCLCLIENTSTATE_FLAGS_WRITE_ACTIVE))
     1378        return VERR_WRONG_ORDER;
    12031379
    12041380    int rc;
     
    12101386    RT_ZERO(cmdCtx);
    12111387
    1212     if (!(pClient->State.fGuestFeatures0 & VBOX_SHCL_GF_0_CONTEXT_ID)) /* Legacy */
    1213     {
    1214         if (cParms < 2)
    1215         {
    1216             rc = VERR_INVALID_PARAMETER;
    1217         }
    1218         else if (   paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT   /* format */
    1219                  || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR)    /* ptr */
     1388    if (!(pClient->State.fGuestFeatures0 & VBOX_SHCL_GF_0_CONTEXT_ID)) /* Legacy, Guest Additions < 6.1. */
     1389    {
     1390        if (cParms != 2)
    12201391        {
    12211392            rc = VERR_INVALID_PARAMETER;
     
    12251396            rc = HGCMSvcGetU32(&paParms[0], &dataBlock.uFormat);
    12261397            if (RT_SUCCESS(rc))
    1227                 rc = HGCMSvcGetBuf(&paParms[1], &dataBlock.pvData, &dataBlock.cbData);
     1398            {
     1399                if (pClient->State.POD.uFormat == VBOX_SHCL_FMT_NONE)
     1400                    pClient->State.POD.uFormat = dataBlock.uFormat;
     1401
     1402                if (   dataBlock.uFormat == VBOX_SHCL_FMT_NONE
     1403                    || dataBlock.uFormat != pClient->State.POD.uFormat)
     1404                {
     1405                    LogFunc(("Invalid format (client=%RU32 vs host=%RU32)\n", dataBlock.uFormat, pClient->State.POD.uFormat));
     1406                    rc = VERR_INVALID_PARAMETER;
     1407                }
     1408                else
     1409                    rc = HGCMSvcGetBuf(&paParms[1], &dataBlock.pvData, &dataBlock.cbData);
     1410            }
    12281411        }
    12291412    }
    12301413    else
    12311414    {
    1232         if (cParms < VBOX_SHCL_CPARMS_WRITE_DATA)
     1415        if (cParms != VBOX_SHCL_CPARMS_WRITE_DATA)
    12331416        {
    12341417            rc = VERR_INVALID_PARAMETER;
    12351418        }
    1236         else if (   paParms[0].type != VBOX_HGCM_SVC_PARM_64BIT   /* uContext */
    1237                  || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT   /* uFormat */
    1238                  || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT   /* cbData */
    1239                  || paParms[3].type != VBOX_HGCM_SVC_PARM_PTR)    /* pvData */
    1240         {
    1241             rc = VERR_INVALID_PARAMETER;
    1242         }
    12431419        else
    12441420        {
    12451421            rc = HGCMSvcGetU64(&paParms[0], &cmdCtx.uContextID);
     1422
     1423            /** @todo Handle paParms[1] flags. */
     1424
    12461425            if (RT_SUCCESS(rc))
    1247                 rc = HGCMSvcGetU32(&paParms[1], &dataBlock.uFormat);
     1426                rc = HGCMSvcGetU32(&paParms[2], &dataBlock.uFormat);
    12481427            if (RT_SUCCESS(rc))
    1249                 rc = HGCMSvcGetBuf(&paParms[3], &dataBlock.pvData, &dataBlock.cbData);
    1250 
    1251             /** @todo Handle the rest. */
     1428                rc = HGCMSvcGetBuf(&paParms[4], &dataBlock.pvData, &dataBlock.cbData);
    12521429        }
    12531430    }
     
    12681445
    12691446        rc = ShClSvcImplWriteData(pClient, &cmdCtx, &dataBlock);
     1447        if (RT_SUCCESS(rc))
     1448        {
     1449            /* Remove "write active" flag after successful read again. */
     1450            pClient->State.fFlags &= ~SHCLCLIENTSTATE_FLAGS_WRITE_ACTIVE;
     1451        }
    12701452    }
    12711453
     
    14501632#endif
    14511633
     1634    LogFunc(("Client state: fFlags=0x%x, fGuestFeatures0=0x%x, fGuestFeatures1=0x%x\n",
     1635             pClient->State.fFlags, pClient->State.fGuestFeatures0, pClient->State.fGuestFeatures1));
     1636
    14521637    switch (u32Function)
    14531638    {
     
    15191704            uint32_t uFormats = 0;
    15201705
    1521             if (!(pClient->State.fGuestFeatures0 & VBOX_SHCL_GF_0_CONTEXT_ID)) /* Legacy */
     1706            if (!(pClient->State.fGuestFeatures0 & VBOX_SHCL_GF_0_CONTEXT_ID)) /* Legacy, Guest Additions < 6.1. */
    15221707            {
    15231708                if (cParms != 1)
     
    15871772
    15881773                        rc = ShClSvcImplFormatAnnounce(pClient, &cmdCtx, &formatData);
    1589                     }
    1590                 }
    1591             }
    1592 
    1593             break;
    1594         }
    1595 
    1596         case VBOX_SHCL_GUEST_FN_DATA_READ:
    1597         {
    1598             if (cParms != VBOX_SHCL_CPARMS_READ_DATA)
    1599             {
    1600                 rc = VERR_INVALID_PARAMETER;
    1601             }
    1602             else if (   paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT   /* format */
    1603                      || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR     /* ptr */
    1604                      || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT   /* size */
    1605                     )
    1606             {
    1607                 rc = VERR_INVALID_PARAMETER;
    1608             }
    1609             else
    1610             {
    1611                 if (   ShClSvcGetMode() != VBOX_SHCL_MODE_HOST_TO_GUEST
    1612                     && ShClSvcGetMode() != VBOX_SHCL_MODE_BIDIRECTIONAL)
    1613                 {
    1614                     rc = VERR_ACCESS_DENIED;
    1615                     break;
    1616                 }
    1617 
    1618                 uint32_t uFormat;
    1619                 rc = HGCMSvcGetU32(&paParms[0], &uFormat);
    1620                 if (RT_SUCCESS(rc))
    1621                 {
    1622                     void    *pv;
    1623                     uint32_t cb;
    1624                     rc = HGCMSvcGetBuf(&paParms[1], &pv, &cb);
    1625                     if (RT_SUCCESS(rc))
    1626                     {
    1627                         uint32_t cbActual = 0;
    1628 
    1629                         /* If there is a service extension active, try reading data from it first. */
    1630                         if (g_ExtState.pfnExtension)
    1631                         {
    1632                             SHCLEXTPARMS parms;
    1633                             RT_ZERO(parms);
    1634 
    1635                             parms.uFormat  = uFormat;
    1636                             parms.u.pvData = pv;
    1637                             parms.cbData   = cb;
    1638 
    1639                             g_ExtState.fReadingData = true;
    1640 
    1641                             /* Read clipboard data from the extension. */
    1642                             rc = g_ExtState.pfnExtension(g_ExtState.pvExtension, VBOX_CLIPBOARD_EXT_FN_DATA_READ,
    1643                                                          &parms, sizeof(parms));
    1644 
    1645                             LogFlowFunc(("g_ExtState.fDelayedAnnouncement=%RTbool, g_ExtState.uDelayedFormats=0x%x\n",
    1646                                          g_ExtState.fDelayedAnnouncement, g_ExtState.uDelayedFormats));
    1647 
    1648                             /* Did the extension send the clipboard formats yet?
    1649                              * Otherwise, do this now. */
    1650                             if (g_ExtState.fDelayedAnnouncement)
    1651                             {
    1652                                 SHCLFORMATDATA formatData;
    1653                                 RT_ZERO(formatData);
    1654 
    1655                                 formatData.uFormats = g_ExtState.uDelayedFormats;
    1656                                 Assert(formatData.uFormats != VBOX_SHCL_FMT_NONE); /* There better is *any* format here now. */
    1657 
    1658                                 int rc2 = ShClSvcFormatsReport(pClient, &formatData);
    1659                                 AssertRC(rc2);
    1660 
    1661                                 g_ExtState.fDelayedAnnouncement = false;
    1662                                 g_ExtState.uDelayedFormats = 0;
    1663                             }
    1664 
    1665                             g_ExtState.fReadingData = false;
    1666 
    1667                             if (RT_SUCCESS(rc))
    1668                             {
    1669                                 cbActual = parms.cbData;
    1670                             }
    1671                         }
    1672 
    1673                         /* Note: The host clipboard *always* has precedence over the service extension above,
    1674                          *       so data which has been read above might get overridden by the host clipboard eventually. */
    1675 
    1676                         SHCLCLIENTCMDCTX cmdCtx;
    1677                         RT_ZERO(cmdCtx);
    1678 
    1679                         /* Release any other pending read, as we only
    1680                          * support one pending read at one time. */
    16811774                        if (RT_SUCCESS(rc))
    16821775                        {
    1683                             SHCLDATABLOCK dataBlock;
    1684                             RT_ZERO(dataBlock);
    1685 
    1686                             dataBlock.pvData  = pv;
    1687                             dataBlock.cbData  = cb;
    1688                             dataBlock.uFormat = uFormat;
    1689 
    1690                             rc = ShClSvcImplReadData(pClient, &cmdCtx, &dataBlock, &cbActual);
    1691                             if (RT_SUCCESS(rc))
    1692                                 HGCMSvcSetU32(&paParms[2], cbActual);
     1776                            pClient->State.fFlags |= SHCLCLIENTSTATE_FLAGS_WRITE_ACTIVE;
    16931777                        }
    16941778                    }
     
    16991783        }
    17001784
     1785        case VBOX_SHCL_GUEST_FN_DATA_READ:
     1786        {
     1787            rc = shClSvcGetDataRead(pClient, cParms, paParms);
     1788            break;
     1789        }
     1790
    17011791        case VBOX_SHCL_GUEST_FN_DATA_WRITE:
    17021792        {
    1703             rc = shclSvcGetDataWrite(pClient, cParms, paParms);
     1793            rc = shClSvcGetDataWrite(pClient, cParms, paParms);
    17041794            break;
    17051795        }
     
    17091799            LogRel2(("Shared Clipboard: Operation canceled by guest side\n"));
    17101800
    1711             /** @todo Do we need to do anything here? */
     1801            /* Reset client state and start over. */
     1802            shclSvcClientStateReset(&pClient->State);
     1803#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
     1804            shclSvcClientTransfersReset(pClient);
     1805#endif
     1806            /** @todo Do we need to do anything else here? */
    17121807            break;
    17131808        }
     
    18011896    pClientState->fGuestFeatures1 = VBOX_SHCL_GF_NONE;
    18021897
    1803     pClientState->cbChunkSize  = _64K; /** Make this configurable. */
     1898    pClientState->cbChunkSize        = _64K; /** Make this configurable. */
     1899    pClientState->enmSource          = SHCLSOURCE_INVALID;
     1900    pClientState->fFlags             = SHCLCLIENTSTATE_FLAGS_NONE;
     1901
     1902    pClientState->POD.enmDir             = SHCLTRANSFERDIR_UNKNOWN;
     1903    pClientState->POD.uFormat            = VBOX_SHCL_FMT_NONE;
     1904    pClientState->POD.cbToReadWriteTotal = 0;
     1905    pClientState->POD.cbReadWritten      = 0;
    18041906
    18051907#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
    18061908    pClientState->Transfers.enmTransferDir = SHCLTRANSFERDIR_UNKNOWN;
    18071909#endif
     1910
     1911
    18081912}
    18091913
     
    18992003{
    19002004    /** Note: Saving the session ID not necessary, as they're not persistent across state save/restore. */
    1901     SSMFIELD_ENTRY    (SHCLCLIENTSTATE, fGuestFeatures0),
    1902     SSMFIELD_ENTRY    (SHCLCLIENTSTATE, fGuestFeatures1),
    1903     SSMFIELD_ENTRY    (SHCLCLIENTSTATE, cbChunkSize),
    1904     SSMFIELD_ENTRY    (SHCLCLIENTSTATE, enmSource),
     2005    SSMFIELD_ENTRY(SHCLCLIENTSTATE, fGuestFeatures0),
     2006    SSMFIELD_ENTRY(SHCLCLIENTSTATE, fGuestFeatures1),
     2007    SSMFIELD_ENTRY(SHCLCLIENTSTATE, cbChunkSize),
     2008    SSMFIELD_ENTRY(SHCLCLIENTSTATE, enmSource),
     2009    SSMFIELD_ENTRY(SHCLCLIENTSTATE, fFlags),
     2010    SSMFIELD_ENTRY_TERM()
     2011};
     2012
     2013/**
     2014 * SSM descriptor table for the SHCLCLIENTPODSTATE structure.
     2015 */
     2016static SSMFIELD const s_aShClSSMClientPODState[] =
     2017{
     2018    SSMFIELD_ENTRY(SHCLCLIENTPODSTATE, enmDir),
     2019    SSMFIELD_ENTRY(SHCLCLIENTPODSTATE, uFormat),
     2020    SSMFIELD_ENTRY(SHCLCLIENTPODSTATE, cbToReadWriteTotal),
     2021    SSMFIELD_ENTRY(SHCLCLIENTPODSTATE, cbReadWritten),
     2022    SSMFIELD_ENTRY(SHCLCLIENTPODSTATE, tsLastReadWrittenMs),
    19052023    SSMFIELD_ENTRY_TERM()
    19062024};
     
    19542072
    19552073    /* Write Shared Clipboard saved state version. */
    1956     SSMR3PutU32(pSSM, VBOX_SHCL_SSM_VER_1);
     2074    SSMR3PutU32(pSSM, VBOX_SHCL_SSM_VER_LATEST);
    19572075
    19582076    int rc = SSMR3PutStructEx(pSSM, &pClient->State, sizeof(pClient->State), 0 /*fFlags*/, &s_aShClSSMClientState[0], NULL);
     2077    AssertRCReturn(rc, rc);
     2078
     2079    rc = SSMR3PutStructEx(pSSM, &pClient->State.POD, sizeof(pClient->State.POD), 0 /*fFlags*/, &s_aShClSSMClientPODState[0], NULL);
    19592080    AssertRCReturn(rc, rc);
    19602081
     
    20472168        return svcLoadStateV0(u32ClientID, pvClient, pSSM, uVersion);
    20482169    }
    2049     else if (lenOrVer == VBOX_SHCL_SSM_VER_1)
    2050     {
    2051         rc = SSMR3GetStructEx(pSSM, &pClient->State, sizeof(pClient->State), 0 /* fFlags */,
    2052                               &s_aShClSSMClientState[0], NULL);
    2053         AssertRCReturn(rc, rc);
     2170    else if (lenOrVer >= VBOX_SHCL_SSM_VER_1)
     2171    {
     2172        if (lenOrVer >= VBOX_SHCL_SSM_VER_2)
     2173        {
     2174            rc = SSMR3GetStructEx(pSSM, &pClient->State, sizeof(pClient->State), 0 /* fFlags */,
     2175                                  &s_aShClSSMClientState[0], NULL);
     2176            AssertRCReturn(rc, rc);
     2177
     2178            rc = SSMR3GetStructEx(pSSM, &pClient->State.POD, sizeof(pClient->State.POD), 0 /* fFlags */,
     2179                                  &s_aShClSSMClientPODState[0], NULL);
     2180            AssertRCReturn(rc, rc);
     2181        }
     2182        else /** @todo Remove this block after 6.1 RC; don't annoy team members with broken saved states. */
     2183        {
     2184            rc = SSMR3Skip(pSSM, sizeof(uint32_t));         /* Begin marker */
     2185            AssertRC(rc);
     2186
     2187            rc = SSMR3GetU64(pSSM, &pClient->State.fGuestFeatures0);
     2188            AssertRC(rc);
     2189
     2190            rc = SSMR3GetU64(pSSM, &pClient->State.fGuestFeatures1);
     2191            AssertRC(rc);
     2192
     2193            rc = SSMR3GetU32(pSSM, &pClient->State.cbChunkSize);
     2194            AssertRC(rc);
     2195
     2196            rc = SSMR3GetU32(pSSM, (uint32_t *)&pClient->State.enmSource);
     2197            AssertRC(rc);
     2198
     2199            rc = SSMR3Skip(pSSM, sizeof(uint32_t));         /* End marker */
     2200            AssertRC(rc);
     2201        }
    20542202
    20552203        rc = SSMR3GetStructEx(pSSM, &pClient->State.Transfers, sizeof(pClient->State.Transfers), 0 /* fFlags */,
Note: See TracChangeset for help on using the changeset viewer.

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