VirtualBox

Changeset 20551 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Jun 14, 2009 4:31:50 PM (16 years ago)
Author:
vboxsync
Message:

GuestHost/SharedClipboard: refactored the shared clipboard code to move knowledge of some host-specific buffering mechanisms into the host-specific code

Location:
trunk/src/VBox
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • TabularUnified trunk/src/VBox/GuestHost/SharedClipboard/x11-clipboard.cpp

    r20137 r20551  
    11311131/**
    11321132 * Massage generic Utf16 with CR end-of-lines into the format Windows expects
    1133  * and put the result in a user-supplied buffer.
     1133 * and return the result in a RTMemAlloc allocated buffer.
    11341134 * @returns  IPRT status code
    1135  * @returns  VERR_BUFFER_OVERFLOW  if the buffer is not large enough
    11361135 * @param  pwcSrc     The source Utf16
    11371136 * @param  cwcSrc     The number of 16bit elements in @a pwcSrc, not counting
    11381137 *                    the terminating zero
    1139  * @param  pvBuf      The buffer to write the result into
    1140  * @param  cbBuf      The size of the buffer
    1141  * @param  pcbActual  On success, where to store the number of bytes written.
    1142  *                    On overflow, the buffer size needed.  Undefined
    1143  *                    otherwise.  Optional
     1138 * @param  ppwszDest  Where to store the buffer address
     1139 * @param  pcbDest    On success, where to store the number of bytes written.
     1140 *                    Undefined otherwise.  Optional
    11441141 */
    11451142static int clipUtf16ToWinTxt(RTUTF16 *pwcSrc, size_t cwcSrc,
    1146                              void *pvBuf, unsigned cbBuf, uint32_t *pcbActual)
    1147 {
    1148     LogFlowFunc(("pwcSrc=%p, cwcSrc=%u, pvBuf=%p, cbBuf=%u", pwcSrc, cwcSrc,
    1149                  pvBuf, cbBuf));
     1143                             PRTUTF16 *ppwszDest, uint32_t *pcbDest)
     1144{
     1145    LogFlowFunc(("pwcSrc=%p, cwcSrc=%u, ppwszDest=%p\n", pwcSrc, cwcSrc,
     1146                 ppwszDest));
    11501147    AssertPtrReturn(pwcSrc, VERR_INVALID_POINTER);
    1151     AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
    1152     if (pcbActual)
    1153         *pcbActual = 0;
    1154     PRTUTF16 pwcDest = reinterpret_cast<PRTUTF16>(pvBuf);
     1148    AssertPtrReturn(ppwszDest, VERR_INVALID_POINTER);
     1149    if (pcbDest)
     1150        *pcbDest = 0;
     1151    PRTUTF16 pwszDest = NULL;
    11551152    size_t cwcDest;
    11561153    int rc = vboxClipboardUtf16GetWinSize(pwcSrc, cwcSrc + 1, &cwcDest);
    1157     if (RT_SUCCESS(rc) && (cbBuf < cwcDest * 2))
    1158     {
    1159         rc = VERR_BUFFER_OVERFLOW;
    1160         if (pcbActual)
    1161             *pcbActual = cwcDest * 2;
    1162     }
    11631154    if (RT_SUCCESS(rc))
    1164         rc = vboxClipboardUtf16LinToWin(pwcSrc, cwcSrc + 1, pwcDest,
    1165                                         cbBuf / 2);
     1155    {
     1156        pwszDest = (PRTUTF16) RTMemAlloc(cwcDest * 2);
     1157        if (!pwszDest)
     1158            rc = VERR_NO_MEMORY;
     1159    }
    11661160    if (RT_SUCCESS(rc))
    1167     {
    1168         LogFlowFunc (("converted string is %.*ls\n", cwcDest, pwcDest));
    1169         if (pcbActual)
    1170             *pcbActual = cwcDest * 2;
    1171     }
     1161        rc = vboxClipboardUtf16LinToWin(pwcSrc, cwcSrc + 1, pwszDest,
     1162                                        cwcDest);
     1163    if (RT_SUCCESS(rc))
     1164    {
     1165        LogFlowFunc (("converted string is %.*ls\n", cwcDest, pwszDest));
     1166        *ppwszDest = pwszDest;
     1167        if (pcbDest)
     1168            *pcbDest = cwcDest * 2;
     1169    }
     1170    else
     1171        RTMemFree(pwszDest);
    11721172    LogFlowFunc(("returning %Rrc\n", rc));
    1173     if (pcbActual)
    1174         LogFlowFunc(("*pcbActual=%u\n", *pcbActual));
     1173    if (pcbDest)
     1174        LogFlowFunc(("*pcbDest=%u\n", *pcbDest));
    11751175    return rc;
    11761176}
     
    11781178/**
    11791179 * Convert Utf-8 text with CR end-of-lines into Utf-16 as Windows expects it
    1180  * and put the result in a user-supplied buffer.
     1180 * and return the result in a RTMemAlloc allocated buffer.
    11811181 * @returns  IPRT status code
    1182  * @returns  VERR_BUFFER_OVERFLOW  if the buffer is not large enough
    11831182 * @param  pcSrc      The source Utf-8
    11841183 * @param  cbSrc      The size of the source in bytes, not counting the
    11851184 *                    terminating zero
    1186  * @param  pvBuf      The buffer to write the result into
    1187  * @param  cbBuf      The size of the buffer
    1188  * @param  pcbActual  On success, where to store the number of bytes written.
    1189  *                    On overflow, the buffer size needed.  Undefined
    1190  *                    otherwise.  Optional
    1191  */
    1192 static int clipUtf8ToWinTxt(const char *pcSrc, unsigned cbSrc, void *pvBuf,
    1193                             unsigned cbBuf, uint32_t *pcbActual)
    1194 {
    1195     LogFlowFunc (("pcSrc = %.*s, cbSrc=%d, cbBuf=%d\n", cbSrc, pcSrc, cbSrc,
    1196                   cbBuf));
     1185 * @param  ppwszDest  Where to store the buffer address
     1186 * @param  pcbDest    On success, where to store the number of bytes written.
     1187 *                    Undefined otherwise.  Optional
     1188 */
     1189static int clipUtf8ToWinTxt(const char *pcSrc, unsigned cbSrc,
     1190                            PRTUTF16 *ppwszDest, uint32_t *pcbDest)
     1191{
     1192    LogFlowFunc(("pcSrc=%p, cbSrc=%u, ppwszDest=%p\n", pcSrc, cbSrc,
     1193                 ppwszDest));
    11971194    AssertPtrReturn(pcSrc, VERR_INVALID_POINTER);
    1198     AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
    1199     if (pcbActual)
    1200         *pcbActual = 0;
     1195    AssertPtrReturn(ppwszDest, VERR_INVALID_POINTER);
     1196    if (pcbDest)
     1197        *pcbDest = 0;
    12011198    /* Intermediate conversion to UTF16 */
    12021199    size_t cwcTmp;
     
    12041201    int rc = RTStrToUtf16Ex(pcSrc, cbSrc, &pwcTmp, 0, &cwcTmp);
    12051202    if (RT_SUCCESS(rc))
    1206         rc = clipUtf16ToWinTxt(pwcTmp, cwcTmp, pvBuf, cbBuf, pcbActual);
     1203        rc = clipUtf16ToWinTxt(pwcTmp, cwcTmp, ppwszDest, pcbDest);
    12071204    RTUtf16Free(pwcTmp);
    12081205    LogFlowFunc(("Returning %Rrc\n", rc));
    1209     if (pcbActual)
    1210         LogFlowFunc(("*pcbActual=%u\n", *pcbActual));
     1206    if (pcbDest)
     1207        LogFlowFunc(("*pcbDest=%u\n", *pcbDest));
    12111208    return rc;
    12121209}
     
    12141211/**
    12151212 * Convert COMPOUND TEXT with CR end-of-lines into Utf-16 as Windows expects
    1216  * it and put the result in a user-supplied buffer.
     1213 * it and return the result in a RTMemAlloc allocated buffer.
    12171214 * @returns  IPRT status code
    1218  * @returns  VERR_BUFFER_OVERFLOW  if the buffer is not large enough
    12191215 * @param  widget     An Xt widget, necessary because we use Xt/Xlib for the
    12201216 *                    conversion
     
    12221218 * @param  cbSrc      The size of the source in bytes, not counting the
    12231219 *                    terminating zero
    1224  * @param  pvBuf      The buffer to write the result into
    1225  * @param  cbBuf      The size of the buffer
    1226  * @param  pcbActual  On success, where to store the number of bytes written.
    1227  *                    On overflow, the buffer size needed.  Undefined
    1228  *                    otherwise.  Optional
     1220 * @param  ppwszDest  Where to store the buffer address
     1221 * @param  pcbDest    On success, where to store the number of bytes written.
     1222 *                    Undefined otherwise.  Optional
    12291223 */
    12301224static int clipCTextToWinTxt(Widget widget, unsigned char *pcSrc,
    1231                              unsigned cbSrc, void *pvBuf, unsigned cbBuf,
    1232                              uint32_t *pcbActual)
    1233 {
    1234     LogFlowFunc (("widget=%p, pcSrc=%.*s, cbSrc=%u, pvBuf=%p, cbBuf=%u\n",
    1235                   widget, cbSrc, (char *) pcSrc, cbSrc, pvBuf, cbBuf));
     1225                             unsigned cbSrc, PRTUTF16 *ppwszDest,
     1226                             uint32_t *pcbDest)
     1227{
     1228    LogFlowFunc(("widget=%p, pcSrc=%p, cbSrc=%u, ppwszDest=%p\n", widget,
     1229                 pcSrc, cbSrc, ppwszDest));
    12361230    AssertReturn(widget, VERR_INVALID_PARAMETER);
    12371231    AssertPtrReturn(pcSrc, VERR_INVALID_POINTER);
    1238     AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
     1232    AssertPtrReturn(ppwszDest, VERR_INVALID_POINTER);
     1233    if (pcbDest)
     1234        *pcbDest = 0;
    12391235
    12401236    /* Special case as X*TextProperty* can't seem to handle empty strings. */
    12411237    if (cbSrc == 0)
    12421238    {
    1243         *pcbActual = 2;
    1244         if (cbBuf < 2)
    1245             return VERR_BUFFER_OVERFLOW;
    1246         *(PRTUTF16) pvBuf = 0;
     1239        *ppwszDest = (PRTUTF16) RTMemAlloc(2);
     1240        if (!ppwszDest)
     1241            return VERR_NO_MEMORY;
     1242        **ppwszDest = 0;
     1243        if (pcbDest)
     1244            *pcbDest = 2;
    12471245        return VINF_SUCCESS;
    12481246    }
    12491247
    1250     if (pcbActual)
    1251         *pcbActual = 0;
     1248    if (pcbDest)
     1249        *pcbDest = 0;
    12521250    /* Intermediate conversion to Utf8 */
    12531251    int rc = VINF_SUCCESS;
     
    12741272    /* Now convert the UTF8 to UTF16 */
    12751273    if (RT_SUCCESS(rc))
    1276         rc = clipUtf8ToWinTxt(*ppcTmp, strlen(*ppcTmp), pvBuf, cbBuf,
    1277                               pcbActual);
     1274        rc = clipUtf8ToWinTxt(*ppcTmp, strlen(*ppcTmp), ppwszDest, pcbDest);
    12781275    if (ppcTmp != NULL)
    12791276        XFreeStringList(ppcTmp);
    12801277    LogFlowFunc(("Returning %Rrc\n", rc));
    1281     if (pcbActual)
    1282         LogFlowFunc(("*pcbActual=%u\n", *pcbActual));
     1278    if (pcbDest)
     1279        LogFlowFunc(("*pcbDest=%u\n", *pcbDest));
    12831280    return rc;
    12841281}
     
    12861283/**
    12871284 * Convert Latin-1 text with CR end-of-lines into Utf-16 as Windows expects
    1288  * it and put the result in a user-supplied buffer.
     1285 * it and return the result in a RTMemAlloc allocated buffer.
    12891286 * @returns  IPRT status code
    1290  * @returns  VERR_BUFFER_OVERFLOW  if the buffer is not large enough
    12911287 * @param  pcSrc      The source text
    12921288 * @param  cbSrc      The size of the source in bytes, not counting the
    12931289 *                    terminating zero
    1294  * @param  pvBuf      The buffer to write the result into
    1295  * @param  cbBuf      The size of the buffer
    1296  * @param  pcbActual  On success, where to store the number of bytes written.
    1297  *                    On overflow, the buffer size needed.  Undefined
    1298  *                    otherwise.  Optional
    1299  */
    1300 static int clipLatin1ToWinTxt(char *pcSrc, unsigned cbSrc, void *pvBuf,
    1301                               size_t cbBuf, uint32_t *pcbActual)
    1302 {
    1303     LogFlowFunc (("pcSrc=%.*s, cbSrc=%u, pvBuf=%p, cbBuf=%u\n", cbSrc,
    1304                   (char *) pcSrc, cbSrc, pvBuf, cbBuf));
     1290 * @param  ppwszDest  Where to store the buffer address
     1291 * @param  pcbDest    On success, where to store the number of bytes written.
     1292 *                    Undefined otherwise.  Optional
     1293 */
     1294static int clipLatin1ToWinTxt(char *pcSrc, unsigned cbSrc,
     1295                              PRTUTF16 *ppwszDest, uint32_t *pcbDest)
     1296{
     1297    LogFlowFunc (("pcSrc=%.*s, cbSrc=%u, ppwszDest=%p\n", cbSrc,
     1298                  (char *) pcSrc, cbSrc, ppwszDest));
    13051299    AssertPtrReturn(pcSrc, VERR_INVALID_POINTER);
    1306     AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
     1300    AssertPtrReturn(ppwszDest, VERR_INVALID_POINTER);
     1301    PRTUTF16 pwszDest = NULL;
    13071302    int rc = VINF_SUCCESS;
    13081303
     
    13151310            ++cwcDest;
    13161311    ++cwcDest;  /* Leave space for the terminator */
    1317     if (pcbActual)
    1318         *pcbActual = cwcDest * 2;
    1319     if (cbBuf < cwcDest * 2)
    1320         rc = VERR_BUFFER_OVERFLOW;
     1312    if (pcbDest)
     1313        *pcbDest = cwcDest * 2;
     1314    pwszDest = (PRTUTF16) RTMemAlloc(cwcDest * 2);
     1315    if (!pwszDest)
     1316        rc = VERR_NO_MEMORY;
    13211317
    13221318    /* And do the convertion, bearing in mind that Latin-1 expands "naturally"
     
    13241320    if (RT_SUCCESS(rc))
    13251321    {
    1326         PRTUTF16 pwcDest = (PRTUTF16) pvBuf;
    13271322        for (unsigned i = 0, j = 0; i < cbSrc; ++i, ++j)
    13281323            if (pcSrc[i] != LINEFEED)
    1329                 pwcDest[j] = pcSrc[i];
     1324                pwszDest[j] = pcSrc[i];
    13301325            else
    13311326            {
    1332                 pwcDest[j] = CARRIAGERETURN;
    1333                 pwcDest[j + 1] = LINEFEED;
     1327                pwszDest[j] = CARRIAGERETURN;
     1328                pwszDest[j + 1] = LINEFEED;
    13341329                ++j;
    13351330            }
    1336         pwcDest[cwcDest - 1] = '\0';  /* Make sure we are zero-terminated. */
    1337         LogFlowFunc (("converted text is %.*ls\n", cwcDest, pwcDest));
    1338     }
     1331        pwszDest[cwcDest - 1] = '\0';  /* Make sure we are zero-terminated. */
     1332        LogFlowFunc (("converted text is %.*ls\n", cwcDest, pwszDest));
     1333    }
     1334    if (RT_SUCCESS(rc))
     1335        *ppwszDest = pwszDest;
     1336    else
     1337        RTMemFree(pwszDest);
    13391338    LogFlowFunc(("Returning %Rrc\n", rc));
    1340     if (pcbActual)
    1341         LogFlowFunc(("*pcbActual=%u\n", *pcbActual));
     1339    if (pcbDest)
     1340        LogFlowFunc(("*pcbDest=%u\n", *pcbDest));
    13421341    return rc;
    13431342}
     
    13471346struct _CLIPREADX11CBREQ
    13481347{
    1349     /** The buffer to write X11 clipboard data to (valid during a request
    1350      * for the clipboard contents) */
    1351     void *mBuffer;
    1352     /** The size of the buffer to write X11 clipboard data to (valid during
    1353      * a request for the clipboard contents) */
    1354     unsigned mSize;
    13551348    /** The format VBox would like the data in */
    13561349    uint32_t mFormat;
     
    13591352    /** The clipboard context this request is associated with */
    13601353    CLIPBACKEND *mCtx;
     1354    /** The request structure passed in from the backend. */
     1355    CLIPREADCBREQ *mReq;
    13611356};
    13621357
     
    13751370{
    13761371    CLIPREADX11CBREQ *pReq = (CLIPREADX11CBREQ *) pClientData;
    1377     LogFlowFunc(("pReq->mBuffer=%p, pReq->mSize=%u, pReq->mFormat=%02X, pReq->mTextFormat=%u, pReq->mCtx=%p\n",
    1378                  pReq->mBuffer, pReq->mSize, pReq->mFormat,
    1379                  pReq->mTextFormat, pReq->mCtx));
    1380     AssertPtr(pReq->mBuffer);    /* We can't really return either... */
     1372    LogFlowFunc(("pReq->mFormat=%02X, pReq->mTextFormat=%u, pReq->mCtx=%p\n",
     1373                 pReq->mFormat, pReq->mTextFormat, pReq->mCtx));
    13811374    AssertPtr(pReq->mCtx);
    13821375    Assert(pReq->mFormat != 0);  /* sanity */
     
    13841377    CLIPBACKEND *pCtx = pReq->mCtx;
    13851378    unsigned cbSrc = (*pcLen) * (*piFormat) / 8;
    1386     uint32_t cbActual = 0;
     1379    void *pvDest = NULL;
     1380    uint32_t cbDest = 0;
    13871381
    13881382    if (pvSrc == NULL)
     
    13981392            case CTEXT:
    13991393                rc = clipCTextToWinTxt(widget, (unsigned char *)pvSrc, cbSrc,
    1400                                        pReq->mBuffer, pReq->mSize,
    1401                                        &cbActual);
     1394                                       (PRTUTF16 *) &pvDest, &cbDest);
    14021395                break;
    14031396            case UTF8:
     
    14081401                                                       0)))
    14091402                    rc = clipUtf8ToWinTxt((const char *)pvSrc, cbSrc,
    1410                                           pReq->mBuffer, pReq->mSize,
    1411                                           &cbActual);
     1403                                          (PRTUTF16 *) &pvDest, &cbDest);
    14121404                else
    14131405                    rc = clipLatin1ToWinTxt((char *) pvSrc, cbSrc,
    1414                                             pReq->mBuffer, pReq->mSize,
    1415                                             &cbActual);
     1406                                            (PRTUTF16 *) &pvDest, &cbDest);
    14161407                break;
    14171408            }
     
    14231414        rc = VERR_NOT_IMPLEMENTED;
    14241415    XtFree((char *)pvSrc);
    1425     ClipCompleteDataRequestFromX11(pReq->mCtx->pFrontend, rc, cbActual);
     1416    ClipCompleteDataRequestFromX11(pReq->mCtx->pFrontend, rc, pReq->mReq,
     1417                                   pvDest, cbDest);
     1418    RTMemFree(pvDest);
    14261419    RTMemFree(pReq);
    14271420    if (RT_SUCCESS(rc))
     
    14421435    CLIPREADX11CBREQ *pReq = (CLIPREADX11CBREQ *)pUserData;
    14431436    CLIPBACKEND *pCtx = pReq->mCtx;
    1444     LogFlowFunc (("pReq->mFormat = %02X, pReq->mSize = %d\n", pReq->mFormat,
    1445                   pReq->mSize));
     1437    LogFlowFunc (("pReq->mFormat = %02X\n", pReq->mFormat));
    14461438
    14471439    int rc = VINF_SUCCESS;
     
    14771469        /* The clipboard callback was never scheduled, so we must signal
    14781470         * that the request processing is finished and clean up ourselves. */
    1479         ClipCompleteDataRequestFromX11(pReq->mCtx->pFrontend, rc, 0);
     1471        ClipCompleteDataRequestFromX11(pReq->mCtx->pFrontend, rc, pReq->mReq,
     1472                                       NULL, 0);
    14801473        RTMemFree(pReq);
    14811474    }
     
    14951488 * @note   We allocate a request structure which must be freed by the worker
    14961489 */
    1497 int ClipRequestDataFromX11(CLIPBACKEND *pCtx, uint32_t u32Format, void *pv,
    1498                            uint32_t cb)
     1490int ClipRequestDataFromX11(CLIPBACKEND *pCtx, uint32_t u32Format,
     1491                           CLIPREADCBREQ *pReq)
    14991492{
    15001493    /*
     
    15041497        return VERR_NO_DATA;
    15051498    int rc = VINF_SUCCESS;
    1506     CLIPREADX11CBREQ *pReq = (CLIPREADX11CBREQ *)RTMemAllocZ(sizeof(*pReq));
    1507     if (!pReq)
     1499    CLIPREADX11CBREQ *pX11Req;
     1500    pX11Req = (CLIPREADX11CBREQ *)RTMemAllocZ(sizeof(*pX11Req));
     1501    if (!pX11Req)
    15081502        rc = VERR_NO_MEMORY;
    15091503    else
    15101504    {
    1511         pReq->mBuffer = pv;
    1512         pReq->mSize = cb;
    1513         pReq->mFormat = u32Format;
    1514         pReq->mCtx = pCtx;
     1505        pX11Req->mFormat = u32Format;
     1506        pX11Req->mCtx = pCtx;
     1507        pX11Req->mReq = pReq;
    15151508        /* We use this to schedule a worker function on the event thread. */
    15161509        clipQueueToEventThread(pCtx->appContext, vboxClipboardReadX11Worker,
    1517                                (XtPointer) pReq);
     1510                               (XtPointer) pX11Req);
    15181511    }
    15191512    return rc;
     
    19501943}
    19511944
     1945#define MAX_BUF_SIZE 256
     1946
    19521947static int g_completedRC = VINF_SUCCESS;
    1953 static int g_completedActual = 0;
     1948static int g_completedCB = 0;
     1949static CLIPREADCBREQ *g_completedReq = NULL;
     1950static char g_completedBuf[MAX_BUF_SIZE];
    19541951
    19551952void ClipCompleteDataRequestFromX11(VBOXCLIPBOARDCONTEXT *pCtx, int rc,
    1956                                     uint32_t cbActual)
    1957 {
    1958     g_completedRC = rc;
    1959     g_completedActual = cbActual;
    1960 }
    1961 
    1962 static void clipGetCompletedRequest(int *prc, uint32_t *pcbActual)
     1953                                    CLIPREADCBREQ *pReq, void *pv,
     1954                                    uint32_t cb)
     1955{
     1956    if (cb <= MAX_BUF_SIZE)
     1957    {
     1958        g_completedRC = rc;
     1959        memcpy(g_completedBuf, pv, cb);
     1960    }
     1961    else
     1962        g_completedRC = VERR_BUFFER_OVERFLOW;
     1963    g_completedCB = cb;
     1964    g_completedReq = pReq;
     1965}
     1966
     1967static void clipGetCompletedRequest(int *prc, char ** ppc, uint32_t *pcb,
     1968                                    CLIPREADCBREQ **ppReq)
    19631969{
    19641970    *prc = g_completedRC;
    1965     *pcbActual = g_completedActual;
     1971    *ppc = g_completedBuf;
     1972    *pcb = g_completedCB;
     1973    *ppReq = g_completedReq;
    19661974}
    19671975#ifdef RT_OS_SOLARIS_10
     
    19841992#endif
    19851993
    1986 #define MAX_BUF_SIZE 256
    1987 
    1988 static bool testStringFromX11(CLIPBACKEND *pCtx, uint32_t cbBuf,
    1989                               const char *pcszExp, int rcExp)
     1994static bool testStringFromX11(CLIPBACKEND *pCtx, const char *pcszExp,
     1995                              int rcExp)
    19901996{
    19911997    bool retval = false;
    1992     AssertReturn(cbBuf <= MAX_BUF_SIZE, false);
    19931998    if (!clipPollTargets())
    19941999        RTPrintf("Failed to poll for targets\n");
     
    19972002    else
    19982003    {
    1999         char pc[MAX_BUF_SIZE];
     2004        char *pc;
     2005        CLIPREADCBREQ *pReq = (CLIPREADCBREQ *)&pReq, *pReqRet = NULL;
    20002006        ClipRequestDataFromX11(pCtx, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT,
    2001                                (void *) pc, cbBuf);
     2007                               pReq);
    20022008        int rc = VINF_SUCCESS;
    20032009        uint32_t cbActual = 0;
    2004         clipGetCompletedRequest(&rc, &cbActual);
     2010        clipGetCompletedRequest(&rc, &pc, &cbActual, &pReqRet);
    20052011        if (rc != rcExp)
    20062012            RTPrintf("Wrong return code, expected %Rrc, got %Rrc\n", rcExp,
    20072013                     rc);
     2014        else if (pReqRet != pReq)
     2015            RTPrintf("Wrong returned request data, expected %p, got %p\n",
     2016                     pReq, pReqRet);
    20082017        else if (RT_FAILURE(rcExp))
    20092018            retval = true;
     
    20382047    }
    20392048    if (!retval)
    2040         RTPrintf("Expected: string \"%s\", rc %Rrc (buffer size %u)\n",
    2041                  pcszExp, rcExp, cbBuf);
     2049        RTPrintf("Expected: string \"%s\", rc %Rrc\n", pcszExp, rcExp);
    20422050    return retval;
    20432051}
    20442052
    2045 static bool testLatin1FromX11(CLIPBACKEND *pCtx, uint32_t cbBuf,
    2046                               const char *pcszExp, int rcExp)
     2053static bool testLatin1FromX11(CLIPBACKEND *pCtx,const char *pcszExp,
     2054                              int rcExp)
    20472055{
    20482056    bool retval = false;
    2049     AssertReturn(cbBuf <= MAX_BUF_SIZE, false);
    20502057    if (!clipPollTargets())
    20512058        RTPrintf("Failed to poll for targets\n");
     
    20542061    else
    20552062    {
    2056         char pc[MAX_BUF_SIZE];
     2063        char *pc;
     2064        CLIPREADCBREQ *pReq = (CLIPREADCBREQ *)&pReq, *pReqRet = NULL;
    20572065        ClipRequestDataFromX11(pCtx, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT,
    2058                                (void *) pc, cbBuf);
     2066                               pReq);
    20592067        int rc = VINF_SUCCESS;
    20602068        uint32_t cbActual = 0;
    2061         clipGetCompletedRequest(&rc, &cbActual);
     2069        clipGetCompletedRequest(&rc, &pc, &cbActual, &pReqRet);
    20622070        if (rc != rcExp)
    20632071            RTPrintf("Wrong return code, expected %Rrc, got %Rrc\n", rcExp,
    20642072                     rc);
     2073        else if (pReqRet != pReq)
     2074            RTPrintf("Wrong returned request data, expected %p, got %p\n",
     2075                     pReq, pReqRet);
    20652076        else if (RT_FAILURE(rcExp))
    20662077            retval = true;
     
    20912102    }
    20922103    if (!retval)
    2093         RTPrintf("Expected: string \"%s\", rc %Rrc (buffer size %u)\n",
    2094                  pcszExp, rcExp, cbBuf);
     2104        RTPrintf("Expected: string \"%s\", rc %Rrc\n", pcszExp, rcExp);
    20952105    return retval;
    20962106}
     
    21562166    CLIPBACKEND *pCtx = ClipConstructX11(NULL);
    21572167    unsigned cErrs = 0;
    2158     char pc[MAX_BUF_SIZE];
     2168    char *pc;
    21592169    uint32_t cbActual;
     2170    CLIPREADCBREQ *pReq = (CLIPREADCBREQ *)&pReq, *pReqRet = NULL;
    21602171    int rc = ClipStartX11(pCtx);
    21612172    AssertRCReturn(rc, 1);
     
    21662177    clipSetSelectionValues("UTF8_STRING", XA_STRING, "hello world",
    21672178                           sizeof("hello world"), 8);
    2168     if (!testStringFromX11(pCtx, 256, "hello world", VINF_SUCCESS))
    2169         ++cErrs;
    2170     /* Receiving buffer of the exact size needed */
    2171     if (!testStringFromX11(pCtx, sizeof("hello world") * 2, "hello world",
    2172                            VINF_SUCCESS))
    2173         ++cErrs;
    2174     /* Buffer one too small */
    2175     if (!testStringFromX11(pCtx, sizeof("hello world") * 2 - 1, "hello world",
    2176                            VERR_BUFFER_OVERFLOW))
    2177         ++cErrs;
    2178     /* Zero-size buffer */
    2179     if (!testStringFromX11(pCtx, 0, "hello world", VERR_BUFFER_OVERFLOW))
     2179    if (!testStringFromX11(pCtx, "hello world", VINF_SUCCESS))
    21802180        ++cErrs;
    21812181    /* With an embedded carriage return */
    21822182    clipSetSelectionValues("text/plain;charset=UTF-8", XA_STRING,
    21832183                           "hello\nworld", sizeof("hello\nworld"), 8);
    2184     if (!testStringFromX11(pCtx, sizeof("hello\r\nworld") * 2,
    2185                            "hello\r\nworld", VINF_SUCCESS))
     2184    if (!testStringFromX11(pCtx, "hello\r\nworld", VINF_SUCCESS))
    21862185        ++cErrs;
    21872186    /* An empty string */
    21882187    clipSetSelectionValues("text/plain;charset=utf-8", XA_STRING, "",
    21892188                           sizeof(""), 8);
    2190     if (!testStringFromX11(pCtx, sizeof("") * 2, "", VINF_SUCCESS))
     2189    if (!testStringFromX11(pCtx, "", VINF_SUCCESS))
    21912190        ++cErrs;
    21922191    /* With an embedded Utf-8 character. */
     
    21942193                           "100\xE2\x82\xAC" /* 100 Euro */,
    21952194                           sizeof("100\xE2\x82\xAC"), 8);
    2196     if (!testStringFromX11(pCtx, sizeof("100\xE2\x82\xAC") * 2,
    2197                            "100\xE2\x82\xAC", VINF_SUCCESS))
     2195    if (!testStringFromX11(pCtx, "100\xE2\x82\xAC", VINF_SUCCESS))
    21982196        ++cErrs;
    21992197    /* A non-zero-terminated string */
    22002198    clipSetSelectionValues("TEXT", XA_STRING,
    22012199                           "hello world", sizeof("hello world") - 2, 8);
    2202     if (!testStringFromX11(pCtx, sizeof("hello world") * 2 - 2,
    2203                            "hello worl", VINF_SUCCESS))
     2200    if (!testStringFromX11(pCtx, "hello worl", VINF_SUCCESS))
    22042201        ++cErrs;
    22052202
     
    22092206    clipSetSelectionValues("COMPOUND_TEXT", XA_STRING, "hello world",
    22102207                           sizeof("hello world"), 8);
    2211     if (!testStringFromX11(pCtx, 256, "hello world", VINF_SUCCESS))
    2212         ++cErrs;
    2213     /* Receiving buffer of the exact size needed */
    2214     if (!testStringFromX11(pCtx, sizeof("hello world") * 2, "hello world",
    2215                            VINF_SUCCESS))
    2216         ++cErrs;
    2217     /* Buffer one too small */
    2218     if (!testStringFromX11(pCtx, sizeof("hello world") * 2 - 1, "hello world",
    2219                            VERR_BUFFER_OVERFLOW))
    2220         ++cErrs;
    2221     /* Zero-size buffer */
    2222     if (!testStringFromX11(pCtx, 0, "hello world", VERR_BUFFER_OVERFLOW))
     2208    if (!testStringFromX11(pCtx, "hello world", VINF_SUCCESS))
    22232209        ++cErrs;
    22242210    /* With an embedded carriage return */
    22252211    clipSetSelectionValues("COMPOUND_TEXT", XA_STRING, "hello\nworld",
    22262212                           sizeof("hello\nworld"), 8);
    2227     if (!testStringFromX11(pCtx, sizeof("hello\r\nworld") * 2,
    2228                            "hello\r\nworld", VINF_SUCCESS))
     2213    if (!testStringFromX11(pCtx, "hello\r\nworld", VINF_SUCCESS))
    22292214        ++cErrs;
    22302215    /* An empty string */
    22312216    clipSetSelectionValues("COMPOUND_TEXT", XA_STRING, "",
    22322217                           sizeof(""), 8);
    2233     if (!testStringFromX11(pCtx, sizeof("") * 2, "", VINF_SUCCESS))
     2218    if (!testStringFromX11(pCtx, "", VINF_SUCCESS))
    22342219        ++cErrs;
    22352220    /* A non-zero-terminated string */
    22362221    clipSetSelectionValues("COMPOUND_TEXT", XA_STRING,
    22372222                           "hello world", sizeof("hello world") - 2, 8);
    2238     if (!testStringFromX11(pCtx, sizeof("hello world") * 2 - 2,
    2239                            "hello worl", VINF_SUCCESS))
     2223    if (!testStringFromX11(pCtx, "hello worl", VINF_SUCCESS))
    22402224        ++cErrs;
    22412225
     
    22452229    clipSetSelectionValues("STRING", XA_STRING, "Georges Dupr\xEA",
    22462230                           sizeof("Georges Dupr\xEA"), 8);
    2247     if (!testLatin1FromX11(pCtx, 256, "Georges Dupr\xEA", VINF_SUCCESS))
    2248         ++cErrs;
    2249     /* Receiving buffer of the exact size needed */
    2250     if (!testLatin1FromX11(pCtx, sizeof("Georges Dupr\xEA") * 2,
    2251                            "Georges Dupr\xEA", VINF_SUCCESS))
    2252         ++cErrs;
    2253     /* Buffer one too small */
    2254     if (!testLatin1FromX11(pCtx, sizeof("Georges Dupr\xEA") * 2 - 1,
    2255                            "Georges Dupr\xEA", VERR_BUFFER_OVERFLOW))
    2256         ++cErrs;
    2257     /* Zero-size buffer */
    2258     if (!testLatin1FromX11(pCtx, 0, "Georges Dupr\xEA", VERR_BUFFER_OVERFLOW))
     2231    if (!testLatin1FromX11(pCtx, "Georges Dupr\xEA", VINF_SUCCESS))
    22592232        ++cErrs;
    22602233    /* With an embedded carriage return */
    22612234    clipSetSelectionValues("TEXT", XA_STRING, "Georges\nDupr\xEA",
    22622235                           sizeof("Georges\nDupr\xEA"), 8);
    2263     if (!testLatin1FromX11(pCtx, sizeof("Georges\r\nDupr\xEA") * 2,
    2264                            "Georges\r\nDupr\xEA", VINF_SUCCESS))
     2236    if (!testLatin1FromX11(pCtx, "Georges\r\nDupr\xEA", VINF_SUCCESS))
    22652237        ++cErrs;
    22662238    /* A non-zero-terminated string */
     
    22682240                           "Georges Dupr\xEA!",
    22692241                           sizeof("Georges Dupr\xEA!") - 2, 8);
    2270     if (!testLatin1FromX11(pCtx, sizeof("Georges Dupr\xEA!") * 2 - 2,
    2271                            "Georges Dupr\xEA", VINF_SUCCESS))
     2242    if (!testLatin1FromX11(pCtx, "Georges Dupr\xEA", VINF_SUCCESS))
    22722243        ++cErrs;
    22732244
     
    22772248    clipSetSelectionValues("UTF8_STRING", XT_CONVERT_FAIL, "hello world",
    22782249                           sizeof("hello world"), 8);
    2279     if (!testStringFromX11(pCtx, 256, "hello world", VERR_TIMEOUT))
     2250    if (!testStringFromX11(pCtx, "hello world", VERR_TIMEOUT))
    22802251        ++cErrs;
    22812252
     
    22852256                           0, 8);
    22862257    ClipRequestDataFromX11(pCtx, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT,
    2287                            (void *) pc, sizeof(pc));
    2288     clipGetCompletedRequest(&rc, &cbActual);
     2258                           pReq);
     2259    clipGetCompletedRequest(&rc, &pc, &cbActual, &pReqRet);
    22892260    if (rc != VERR_NO_DATA)
    22902261    {
    22912262        RTPrintf("Returned %Rrc instead of VERR_NO_DATA\n", rc);
     2263        ++cErrs;
     2264    }
     2265    if (pReqRet != pReq)
     2266    {
     2267        RTPrintf("Wrong returned request data, expected %p, got %p\n",
     2268                 pReq, pReqRet);
    22922269        ++cErrs;
    22932270    }
     
    22952272    /*** request for an invalid VBox format from X11 ***/
    22962273    RTPrintf(TEST_NAME ": TESTING a request for an invalid VBox format from X11\n");
    2297     ClipRequestDataFromX11(pCtx, 0xffff, (void *) pc, sizeof(pc));
    2298     clipGetCompletedRequest(&rc, &cbActual);
     2274    ClipRequestDataFromX11(pCtx, 0xffff, pReq);
     2275    clipGetCompletedRequest(&rc, &pc, &cbActual, &pReqRet);
    22992276    if (rc != VERR_NOT_IMPLEMENTED)
    23002277    {
    23012278        RTPrintf("Returned %Rrc instead of VERR_NOT_IMPLEMENTED\n", rc);
     2279        ++cErrs;
     2280    }
     2281    if (pReqRet != pReq)
     2282    {
     2283        RTPrintf("Wrong returned request data, expected %p, got %p\n",
     2284                 pReq, pReqRet);
    23022285        ++cErrs;
    23032286    }
     
    24522435
    24532436void ClipCompleteDataRequestFromX11(VBOXCLIPBOARDCONTEXT *pCtx, int rc,
    2454                                     uint32_t cbActual)
     2437                                    CLIPREADCBREQ *pReq, void *pv,
     2438                                    uint32_t cb)
    24552439{}
    24562440
  • TabularUnified trunk/src/VBox/HostServices/SharedClipboard/x11-clipboard.cpp

    r19875 r20551  
    197197}
    198198
     199/** Structure describing a request for clipoard data from the guest. */
     200struct _CLIPREADCBREQ
     201{
     202    /** Where to write the returned data to. */
     203    void *pv;
     204    /** The size of the buffer in pv */
     205    uint32_t cb;
     206    /** The actual size of the data written */
     207    uint32_t *pcbActual;
     208};
     209
    199210/**
    200211 * Called when VBox wants to read the X11 clipboard.
     
    210221 * @param  pcbActual Where to write the actual size of the written data
    211222 * @note   We always fail or complete asynchronously
    212  * @note   On success allocates a CLIPREADX11CBCONTEXT structure which must be
     223 * @note   On success allocates a CLIPREADCBREQ structure which must be
    213224 *         freed in ClipCompleteDataRequestFromX11 when it is called back from
    214225 *         the backend code.
     
    222233                 pClient, u32Format, pv, cb, pcbActual));
    223234   
    224     int rc = ClipRequestDataFromX11(pClient->pCtx->pBackend, u32Format, pv,
    225                                     cb);
    226     if (RT_SUCCESS(rc))
    227         rc = VINF_HGCM_ASYNC_EXECUTE;
     235    int rc = VINF_SUCCESS;
     236    CLIPREADCBREQ *pReq = (CLIPREADCBREQ *) RTMemAlloc(sizeof(CLIPREADCBREQ));
     237    if (!pReq)
     238        rc = VERR_NO_MEMORY;
     239    else
     240    {
     241        pReq->pv = pv;
     242        pReq->cb = cb;
     243        pReq->pcbActual = pcbActual;
     244        rc = ClipRequestDataFromX11(pClient->pCtx->pBackend, u32Format, pReq);
     245        if (RT_SUCCESS(rc))
     246            rc = VINF_HGCM_ASYNC_EXECUTE;
     247    }
    228248    LogFlowFunc(("returning %Rrc\n", rc));
    229249    return rc;
     
    242262 */
    243263void ClipCompleteDataRequestFromX11(VBOXCLIPBOARDCONTEXT *pCtx, int rc,
    244                                     uint32_t cbActual)
    245 {
    246     vboxSvcClipboardCompleteReadData(pCtx->pClient, rc, cbActual);
     264                                    CLIPREADCBREQ *pReq, void *pv,
     265                                    uint32_t cb)
     266{
     267    if (cb <= pReq->cb)
     268        memcpy(pReq->pv, pv, cb);
     269    RTMemFree(pReq);
     270    vboxSvcClipboardCompleteReadData(pCtx->pClient, rc, cb);
    247271}
    248272
     
    410434    {
    411435        uint32_t format;
    412         void *pv;
    413         uint32_t cb;
    414436        int rc;
     437        CLIPREADCBREQ *pReq;
    415438    } readData;
    416439    struct _COMPLETEREAD
     
    478501
    479502extern int ClipRequestDataFromX11(CLIPBACKEND *pBackend, uint32_t u32Format,
    480                                   void *pv, uint32_t cb)
     503                                  CLIPREADCBREQ *pReq)
    481504{
    482505    pBackend->readData.format = u32Format;
    483     pBackend->readData.pv = pv;
    484     pBackend->readData.cb = cb;
     506    pBackend->readData.pReq = pReq;
    485507    return pBackend->readData.rc;
    486508}
     
    518540        if (   pBackend->readData.format !=
    519541                       VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT
    520             || pBackend->readData.pv != &u32Dummy
    521             || pBackend->readData.cb != 42)
     542            || pBackend->readData.pReq->pv != &u32Dummy
     543            || pBackend->readData.pReq->cb != 42
     544            || pBackend->readData.pReq->pcbActual != &u32Dummy)
    522545        {
    523             RTPrintf(TEST_NAME ": format=%u, pv=%p, cb=%u\n",
    524                      pBackend->readData.format, pBackend->readData.pv,
    525                      pBackend->readData.cb);
     546            RTPrintf(TEST_NAME ": format=%u, pReq->pv=%p, pReq->cb=%u, pReq->pcbActual=%p\n",
     547                     pBackend->readData.format, pBackend->readData.pReq->pv,
     548                     pBackend->readData.pReq->cb,
     549                     pBackend->readData.pReq->pcbActual);
    526550            ++cErrors;
    527551        }
    528552        else
    529553        {
    530             ClipCompleteDataRequestFromX11(client.pCtx, VERR_NO_DATA, 43);
     554            ClipCompleteDataRequestFromX11(client.pCtx, VERR_NO_DATA,
     555                                           pBackend->readData.pReq, NULL, 43);
    531556            if (   pBackend->completeRead.rc != VERR_NO_DATA
    532557                || pBackend->completeRead.cbActual != 43)
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