VirtualBox

Ignore:
Timestamp:
Aug 19, 2020 9:12:33 AM (4 years ago)
Author:
vboxsync
Message:

Shared Clipboard/X11: Major cleanup for string conversion functions. Not fully tested yet.

Location:
trunk/src/VBox/GuestHost/SharedClipboard
Files:
2 edited

Legend:

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

    r83621 r85828  
    2525#include <iprt/path.h>
    2626#include <iprt/rand.h>
     27#include <iprt/utf16.h>
    2728
    2829#include <iprt/errcore.h>
     
    457458}
    458459
    459 /** @todo Delinuxify the code (*Lin* -> *Host*); use AssertLogRel*. */
    460 
    461 int ShClUtf16GetWinSize(PCRTUTF16 pcwszSrc, size_t cwSrc, size_t *pcwDest)
    462 {
    463     size_t cwDest, i;
    464 
    465     LogFlowFunc(("pcwszSrc=%.*ls, cwSrc=%u\n", cwSrc, pcwszSrc, cwSrc));
    466     AssertLogRelMsgReturn(pcwszSrc != NULL, ("vboxClipboardUtf16GetWinSize: received a null Utf16 string, returning VERR_INVALID_PARAMETER\n"), VERR_INVALID_PARAMETER);
    467     if (cwSrc == 0)
    468     {
    469         *pcwDest = 0;
    470         LogFlowFunc(("empty source string, returning\n"));
     460int ShClUtf16LenUtf8(PCRTUTF16 pcwszSrc, size_t cwcSrc, size_t *pchLen)
     461{
     462    AssertPtrReturn(pcwszSrc, VERR_INVALID_POINTER);
     463    AssertPtrReturn(pchLen, VERR_INVALID_POINTER);
     464
     465    size_t chLen = 0;
     466    int rc = RTUtf16CalcUtf8LenEx(pcwszSrc, cwcSrc, &chLen);
     467    if (RT_SUCCESS(rc))
     468        *pchLen = chLen + 1; /* Include terminator. */
     469    return rc;
     470}
     471
     472int ShClConvUtf16CRLFToUtf8LF(PRTUTF16 pwszSrc, size_t cwcSrc,
     473                              char *pszBuf, size_t cbBuf, size_t *pcbLen)
     474{
     475    AssertPtrReturn(pwszSrc, VERR_INVALID_POINTER);
     476    AssertReturn   (cwcSrc,  VERR_INVALID_PARAMETER);
     477    AssertPtrReturn(pszBuf,  VERR_INVALID_POINTER);
     478    AssertPtrReturn(pcbLen,  VERR_INVALID_POINTER);
     479
     480    int rc;
     481
     482    PRTUTF16 pwszTmp = NULL;
     483    size_t   cchTmp  = 0;
     484
     485    size_t   cbLen = 0;
     486
     487    /* How long will the converted text be? */
     488    rc = ShClUtf16CRLFLenUtf8(pwszSrc, cwcSrc, &cchTmp);
     489    if (RT_SUCCESS(rc))
     490    {
     491        if (cchTmp)
     492        {
     493            pwszTmp = (PRTUTF16)RTMemAlloc(cchTmp * sizeof(RTUTF16));
     494            if (pwszTmp)
     495            {
     496                rc = ShClConvUtf16CRLFToLF(pwszSrc, cwcSrc, pwszTmp, cchTmp);
     497                if (RT_SUCCESS(rc))
     498                    rc = RTUtf16ToUtf8Ex(pwszTmp + 1, cchTmp - 1, &pszBuf, cbBuf, &cbLen);
     499
     500                RTMemFree(reinterpret_cast<void *>(pwszTmp));
     501            }
     502            else
     503                rc = VERR_NO_MEMORY;
     504        }
     505        else
     506            rc = VERR_NO_DATA;
     507    }
     508
     509    if (RT_SUCCESS(rc))
     510    {
     511        *pcbLen = cbLen + 1 /* Include terminator */;
     512    }
     513
     514    LogFlowFuncLeaveRC(rc);
     515    return rc;
     516}
     517
     518int ShClConvUtf16LFToCRLFA(RTUTF16 *pwcSrc, size_t cwcSrc,
     519                           PRTUTF16 *ppwszDst, size_t *pcwDst)
     520{
     521    AssertPtrReturn(pwcSrc, VERR_INVALID_POINTER);
     522    AssertReturn(cwcSrc, VERR_INVALID_PARAMETER);
     523    AssertPtrReturn(ppwszDst, VERR_INVALID_POINTER);
     524    AssertPtrReturn(pcwDst, VERR_INVALID_POINTER);
     525
     526    PRTUTF16 pwszDst = NULL;
     527    size_t   cchDst;
     528
     529    int rc = ShClUtf16LFLenUtf8(pwcSrc, cwcSrc, &cchDst);
     530    if (RT_SUCCESS(rc))
     531    {
     532        Assert(cchDst);
     533        pwszDst = (PRTUTF16)RTMemAlloc(cchDst * sizeof(RTUTF16));
     534        if (pwszDst)
     535        {
     536            rc = ShClConvUtf16LFToCRLF(pwcSrc, cwcSrc, pwszDst, cchDst);
     537        }
     538        else
     539            rc = VERR_NO_MEMORY;
     540    }
     541
     542    if (RT_SUCCESS(rc))
     543    {
     544        *ppwszDst = pwszDst;
     545        *pcwDst   = cchDst;
     546    }
     547    else
     548        RTMemFree(pwszDst);
     549
     550    LogFlowFuncLeaveRC(rc);
     551    return rc;
     552}
     553
     554int ShClConvUtf8LFToUtf16CRLF(const char *pcSrc, unsigned cbSrc,
     555                              PRTUTF16 *ppwszDst, size_t *pcwDst)
     556{
     557    AssertPtrReturn(pcSrc, VERR_INVALID_POINTER);
     558    AssertReturn(cbSrc, VERR_INVALID_PARAMETER);
     559    AssertPtrReturn(ppwszDst, VERR_INVALID_POINTER);
     560    AssertPtrReturn(pcwDst, VERR_INVALID_POINTER);
     561
     562    /* Intermediate conversion to UTF-16. */
     563    size_t   cwcTmp;
     564    PRTUTF16 pwcTmp = NULL;
     565    int rc = RTStrToUtf16Ex(pcSrc, cbSrc, &pwcTmp, 0, &cwcTmp);
     566    if (RT_SUCCESS(rc))
     567    {
     568        rc = ShClConvUtf16LFToCRLFA(pwcTmp, cwcTmp, ppwszDst, pcwDst);
     569        RTUtf16Free(pwcTmp);
     570    }
     571
     572    LogFlowFuncLeaveRC(rc);
     573    return rc;
     574}
     575
     576int ShClConvLatin1LFToUtf16CRLF(const char *pcSrc, unsigned cbSrc,
     577                                PRTUTF16 *ppwszDst, size_t *pcwDst)
     578{
     579    AssertPtrReturn(pcSrc, VERR_INVALID_POINTER);
     580    AssertReturn(cbSrc, VERR_INVALID_PARAMETER);
     581    AssertPtrReturn(ppwszDst, VERR_INVALID_POINTER);
     582    AssertPtrReturn(pcwDst, VERR_INVALID_POINTER);
     583
     584    int rc = VINF_SUCCESS;
     585
     586    PRTUTF16 pwszDst = NULL;
     587
     588    /* Calculate the space needed. */
     589    unsigned cbDst = 0;
     590    for (unsigned i = 0; i < cbSrc && pcSrc[i] != '\0'; ++i)
     591    {
     592        if (pcSrc[i] == VBOX_SHCL_LINEFEED)
     593            cbDst += sizeof(RTUTF16);
     594        else
     595            ++cbDst;
     596    }
     597
     598    ++cbDst; /* Leave space for the terminator. */
     599
     600    pwszDst = (PRTUTF16)RTMemAlloc(cbDst * sizeof(RTUTF16));
     601    if (!pwszDst)
     602        rc = VERR_NO_MEMORY;
     603
     604    /* Do the conversion, bearing in mind that Latin-1 expands "naturally" to UTF-16. */
     605    if (RT_SUCCESS(rc))
     606    {
     607        for (unsigned i = 0, j = 0; i < cbSrc; ++i, ++j)
     608        {
     609            if (pcSrc[i] != VBOX_SHCL_LINEFEED)
     610                pwszDst[j] = pcSrc[i];
     611            else
     612            {
     613                pwszDst[j]     = VBOX_SHCL_CARRIAGERETURN;
     614                pwszDst[j + 1] = VBOX_SHCL_LINEFEED;
     615                ++j;
     616            }
     617        }
     618
     619        pwszDst[cbDst - 1] = '\0';  /* Make sure we are zero-terminated. */
     620    }
     621
     622    if (RT_SUCCESS(rc))
     623    {
     624        *ppwszDst = pwszDst;
     625        *pcwDst   = cbDst * sizeof(RTUTF16);
     626    }
     627    else
     628        RTMemFree(pwszDst);
     629
     630    LogFlowFuncLeaveRC(rc);
     631    return rc;
     632}
     633
     634int ShClConvUtf16ToUtf8HTML(RTUTF16 *pwcSrc, size_t cwSrc, char **ppszDst, size_t *pcbDst)
     635{
     636    AssertPtrReturn(pwcSrc,  VERR_INVALID_POINTER);
     637    AssertReturn   (cwSrc,   VERR_INVALID_PARAMETER);
     638    AssertPtrReturn(ppszDst, VERR_INVALID_POINTER);
     639    AssertPtrReturn(pcbDst,  VERR_INVALID_POINTER);
     640
     641    int rc;
     642
     643    size_t   cwTmp = cwSrc;
     644    RTUTF16 *pwTmp = pwcSrc;
     645
     646    char  *pchDst = NULL;
     647    size_t cbDst  = 0;
     648
     649    size_t i = 0;
     650    while (i < cwTmp)
     651    {
     652        /* Find  zero symbol (end of string). */
     653        for (; i < cwTmp && pwcSrc[i] != 0; i++)
     654            ;
     655
     656        /* Convert found string. */
     657        char  *psz = NULL;
     658        size_t cch = 0;
     659        rc = RTUtf16ToUtf8Ex(pwTmp, cwTmp, &psz, pwTmp - pwcSrc, &cch);
     660        if (RT_FAILURE(rc))
     661            break;
     662
     663        /* Append new substring. */
     664        char *pchNew = (char *)RTMemRealloc(pchDst, cbDst + cch + 1);
     665        if (!pchNew)
     666        {
     667            RTStrFree(psz);
     668            rc = VERR_NO_MEMORY;
     669            break;
     670        }
     671
     672        pchDst = pchNew;
     673        memcpy(pchDst + cbDst, psz, cch + 1);
     674
     675        RTStrFree(psz);
     676
     677        cbDst += cch + 1;
     678
     679        /* Skip zero symbols. */
     680        for (; i < cwTmp && pwcSrc[i] == 0; i++)
     681            ;
     682
     683        /* Remember start of string. */
     684        pwTmp += i;
     685    }
     686
     687    if (RT_SUCCESS(rc))
     688    {
     689        *ppszDst = pchDst;
     690        *pcbDst  = cbDst;
     691
    471692        return VINF_SUCCESS;
    472693    }
    473 /** @todo convert the remainder of the Assert stuff to AssertLogRel. */
    474     /* We only take little endian Utf16 */
    475     if (pcwszSrc[0] == VBOX_SHCL_UTF16BEMARKER)
    476     {
    477         LogRel(("Shared Clipboard: vboxClipboardUtf16GetWinSize: received a big endian Utf16 string, returning VERR_INVALID_PARAMETER\n"));
    478         AssertReturn(pcwszSrc[0] != VBOX_SHCL_UTF16BEMARKER, VERR_INVALID_PARAMETER);
    479     }
    480     cwDest = 0;
     694
     695    RTMemFree(pchDst);
     696
     697    LogFlowFuncLeaveRC(rc);
     698    return rc;
     699}
     700
     701int ShClUtf16LFLenUtf8(PCRTUTF16 pcwszSrc, size_t cwSrc, size_t *pchLen)
     702{
     703    AssertPtrReturn(pcwszSrc, VERR_INVALID_POINTER);
     704    AssertReturn(cwSrc, VERR_INVALID_PARAMETER);
     705    AssertPtrReturn(pchLen, VERR_INVALID_POINTER);
     706
     707    AssertMsgReturn(pcwszSrc[0] != VBOX_SHCL_UTF16BEMARKER,
     708                    ("Big endian UTF-16 not supported yet\n"), VERR_NOT_SUPPORTED);
     709
     710    size_t cLen = 0;
     711
     712    /* Don't copy the endian marker. */
     713    size_t i = pcwszSrc[0] == VBOX_SHCL_UTF16LEMARKER ? 1 : 0;
     714
    481715    /* Calculate the size of the destination text string. */
    482716    /* Is this Utf16 or Utf16-LE? */
    483     for (i = (pcwszSrc[0] == VBOX_SHCL_UTF16LEMARKER ? 1 : 0); i < cwSrc; ++i, ++cwDest)
     717    for (; i < cwSrc; ++i, ++cLen)
    484718    {
    485719        /* Check for a single line feed */
    486720        if (pcwszSrc[i] == VBOX_SHCL_LINEFEED)
    487             ++cwDest;
     721            ++cLen;
    488722#ifdef RT_OS_DARWIN
    489723        /* Check for a single carriage return (MacOS) */
    490724        if (pcwszSrc[i] == VBOX_SHCL_CARRIAGERETURN)
    491             ++cwDest;
     725            ++cLen;
    492726#endif
    493727        if (pcwszSrc[i] == 0)
     
    497731        }
    498732    }
    499     /* Count the terminating null byte. */
    500     ++cwDest;
    501     LogFlowFunc(("returning VINF_SUCCESS, %d 16bit words\n", cwDest));
    502     *pcwDest = cwDest;
     733
     734    /* Add terminator. */
     735    ++cLen;
     736
     737    *pchLen = cLen;
     738
     739    LogFlowFuncLeaveRC(VINF_SUCCESS);
    503740    return VINF_SUCCESS;
    504741}
    505742
    506 int ShClUtf16LinToWin(PCRTUTF16 pcwszSrc, size_t cwSrc, PRTUTF16 pu16Dest, size_t cwDest)
    507 {
    508     size_t i, j;
    509     LogFlowFunc(("pcwszSrc=%.*ls, cwSrc=%u\n", cwSrc, pcwszSrc, cwSrc));
    510     if (!VALID_PTR(pcwszSrc) || !VALID_PTR(pu16Dest))
    511     {
    512         LogRel(("Shared Clipboard: vboxClipboardUtf16LinToWin: received an invalid pointer, returning VERR_INVALID_PARAMETER\n"));
    513         AssertReturn(VALID_PTR(pcwszSrc) && VALID_PTR(pu16Dest), VERR_INVALID_PARAMETER);
    514     }
    515     if (cwSrc == 0)
    516     {
    517         if (cwDest == 0)
    518         {
    519             LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
    520             return VERR_BUFFER_OVERFLOW;
    521         }
    522         pu16Dest[0] = 0;
    523         LogFlowFunc(("empty source string, returning\n"));
    524         return VINF_SUCCESS;
    525     }
    526     /* We only take little endian Utf16 */
    527     if (pcwszSrc[0] == VBOX_SHCL_UTF16BEMARKER)
    528     {
    529         LogRel(("Shared Clipboard: vboxClipboardUtf16LinToWin: received a big endian Utf16 string, returning VERR_INVALID_PARAMETER\n"));
    530         AssertReturn(pcwszSrc[0] != VBOX_SHCL_UTF16BEMARKER, VERR_INVALID_PARAMETER);
    531     }
     743int ShClUtf16CRLFLenUtf8(PCRTUTF16 pcwszSrc, size_t cwSrc, size_t *pchLen)
     744{
     745    AssertPtrReturn(pcwszSrc, VERR_INVALID_POINTER);
     746    AssertReturn(cwSrc, VERR_INVALID_PARAMETER);
     747    AssertPtrReturn(pchLen, VERR_INVALID_POINTER);
     748
     749    AssertMsgReturn(pcwszSrc[0] != VBOX_SHCL_UTF16BEMARKER,
     750                    ("Big endian UTF-16 not supported yet\n"), VERR_NOT_SUPPORTED);
     751
     752    size_t cLen = 0;
     753
     754    /* Calculate the size of the destination text string. */
     755    /* Is this Utf16 or Utf16-LE? */
     756    if (pcwszSrc[0] == VBOX_SHCL_UTF16LEMARKER)
     757        cLen = 0;
     758    else
     759        cLen = 1;
     760
     761    for (size_t i = 0; i < cwSrc; ++i, ++cLen)
     762    {
     763        if (   (i + 1 < cwSrc)
     764            && (pcwszSrc[i]     == VBOX_SHCL_CARRIAGERETURN)
     765            && (pcwszSrc[i + 1] == VBOX_SHCL_LINEFEED))
     766        {
     767            ++i;
     768        }
     769        if (pcwszSrc[i] == 0)
     770            break;
     771    }
     772
     773    /* Add terminating zero. */
     774    ++cLen;
     775
     776    *pchLen = cLen;
     777
     778    LogFlowFuncLeaveRC(VINF_SUCCESS);
     779    return VINF_SUCCESS;
     780}
     781
     782int ShClConvUtf16LFToCRLF(PCRTUTF16 pcwszSrc, size_t cwSrc, PRTUTF16 pu16Dst, size_t cwDst)
     783{
     784    AssertPtrReturn(pcwszSrc, VERR_INVALID_POINTER);
     785    AssertReturn(cwSrc, VERR_INVALID_PARAMETER);
     786    AssertPtrReturn(pu16Dst, VERR_INVALID_POINTER);
     787    AssertReturn(cwDst, VERR_INVALID_PARAMETER);
     788
     789    AssertMsgReturn(pcwszSrc[0] != VBOX_SHCL_UTF16BEMARKER,
     790                    ("Big endian UTF-16 not supported yet\n"), VERR_NOT_SUPPORTED);
     791
     792    int rc = VINF_SUCCESS;
     793
    532794    /* Don't copy the endian marker. */
    533     for (i = (pcwszSrc[0] == VBOX_SHCL_UTF16LEMARKER ? 1 : 0), j = 0; i < cwSrc; ++i, ++j)
     795    size_t i = pcwszSrc[0] == VBOX_SHCL_UTF16LEMARKER ? 1 : 0;
     796    size_t j = 0;
     797
     798    for (; i < cwSrc; ++i, ++j)
    534799    {
    535800        /* Don't copy the null byte, as we add it below. */
    536801        if (pcwszSrc[i] == 0)
    537802            break;
    538         if (j == cwDest)
    539         {
    540             LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
    541             return VERR_BUFFER_OVERFLOW;
    542         }
     803
     804        /* Not enough space in destination? */
     805        if (j == cwDst)
     806        {
     807            rc = VERR_BUFFER_OVERFLOW;
     808            break;
     809        }
     810
    543811        if (pcwszSrc[i] == VBOX_SHCL_LINEFEED)
    544812        {
    545             pu16Dest[j] = VBOX_SHCL_CARRIAGERETURN;
     813            pu16Dst[j] = VBOX_SHCL_CARRIAGERETURN;
    546814            ++j;
    547             if (j == cwDest)
     815
     816            /* Not enough space in destination? */
     817            if (j == cwDst)
    548818            {
    549                 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
    550                 return VERR_BUFFER_OVERFLOW;
     819                rc = VERR_BUFFER_OVERFLOW;
     820                break;
    551821            }
    552822        }
     
    555825        else if (pcwszSrc[i] == VBOX_SHCL_CARRIAGERETURN)
    556826        {
    557             /* set cr */
    558             pu16Dest[j] = VBOX_SHCL_CARRIAGERETURN;
     827            /* Set CR.r */
     828            pu16Dst[j] = VBOX_SHCL_CARRIAGERETURN;
    559829            ++j;
    560             if (j == cwDest)
     830
     831            /* Not enough space in destination? */
     832            if (j == cwDst)
    561833            {
    562                 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
    563                 return VERR_BUFFER_OVERFLOW;
     834                rc = VERR_BUFFER_OVERFLOW;
     835                break;
    564836            }
    565             /* add the lf */
    566             pu16Dest[j] = VBOX_SHCL_LINEFEED;
     837
     838            /* Add line feed. */
     839            pu16Dst[j] = VBOX_SHCL_LINEFEED;
    567840            continue;
    568841        }
    569842#endif
    570         pu16Dest[j] = pcwszSrc[i];
    571     }
    572     /* Add the trailing null. */
    573     if (j == cwDest)
    574     {
    575         LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
     843        pu16Dst[j] = pcwszSrc[i];
     844    }
     845
     846    if (j == cwDst)
     847        rc = VERR_BUFFER_OVERFLOW;
     848
     849    if (RT_SUCCESS(rc))
     850    {
     851        /* Add terminator. */
     852        pu16Dst[j] = 0;
     853    }
     854
     855    LogFlowFuncLeaveRC(rc);
     856    return rc;
     857}
     858
     859int ShClConvUtf16CRLFToLF(PCRTUTF16 pcwszSrc, size_t cwSrc, PRTUTF16 pu16Dst, size_t cwDst)
     860{
     861    AssertPtrReturn(pcwszSrc, VERR_INVALID_POINTER);
     862    AssertReturn(cwSrc, VERR_INVALID_PARAMETER);
     863    AssertPtrReturn(pu16Dst, VERR_INVALID_POINTER);
     864    AssertReturn(cwDst, VERR_INVALID_PARAMETER);
     865
     866    AssertMsgReturn(pcwszSrc[0] != VBOX_SHCL_UTF16BEMARKER,
     867                    ("Big endian UTF-16 not supported yet\n"), VERR_NOT_SUPPORTED);
     868
     869    /* Prepend the Utf16 byte order marker if it is missing. */
     870    size_t cwDstPos;
     871    if (pcwszSrc[0] == VBOX_SHCL_UTF16LEMARKER)
     872    {
     873        cwDstPos = 0;
     874    }
     875    else
     876    {
     877        pu16Dst[0] = VBOX_SHCL_UTF16LEMARKER;
     878        cwDstPos = 1;
     879    }
     880
     881    for (size_t i = 0; i < cwSrc; ++i, ++cwDstPos)
     882    {
     883        if (pcwszSrc[i] == 0)
     884            break;
     885
     886        if (cwDstPos == cwDst)
     887            return VERR_BUFFER_OVERFLOW;
     888
     889        if (   (i + 1 < cwSrc)
     890            && (pcwszSrc[i]     == VBOX_SHCL_CARRIAGERETURN)
     891            && (pcwszSrc[i + 1] == VBOX_SHCL_LINEFEED))
     892        {
     893            ++i;
     894        }
     895
     896        pu16Dst[cwDstPos] = pcwszSrc[i];
     897    }
     898
     899    if (cwDstPos == cwDst)
    576900        return VERR_BUFFER_OVERFLOW;
    577     }
    578     pu16Dest[j] = 0;
    579     LogFlowFunc(("rc=VINF_SUCCESS, pu16Dest=%ls\n", pu16Dest));
     901
     902    /* Add terminating zero. */
     903    pu16Dst[cwDstPos] = 0;
     904
     905    LogFlowFuncLeaveRC(VINF_SUCCESS);
    580906    return VINF_SUCCESS;
    581907}
    582908
    583 int ShClUtf16GetLinSize(PCRTUTF16 pcwszSrc, size_t cwSrc, size_t *pcwDest)
    584 {
    585     size_t cwDest;
    586 
    587     LogFlowFunc(("pcwszSrc=%.*ls, cwSrc=%u\n", cwSrc, pcwszSrc, cwSrc));
    588     if (!VALID_PTR(pcwszSrc))
    589     {
    590         LogRel(("Shared Clipboard: vboxClipboardUtf16GetLinSize: received an invalid Utf16 string, returning VERR_INVALID_PARAMETER\n"));
    591         AssertReturn(VALID_PTR(pcwszSrc), VERR_INVALID_PARAMETER);
    592     }
    593     if (cwSrc == 0)
    594     {
    595         LogFlowFunc(("empty source string, returning VINF_SUCCESS\n"));
    596         *pcwDest = 0;
    597         return VINF_SUCCESS;
    598     }
    599     /* We only take little endian Utf16 */
    600     if (pcwszSrc[0] == VBOX_SHCL_UTF16BEMARKER)
    601     {
    602         LogRel(("Shared Clipboard: vboxClipboardUtf16GetLinSize: received a big endian Utf16 string, returning VERR_INVALID_PARAMETER\n"));
    603         AssertReturn(pcwszSrc[0] != VBOX_SHCL_UTF16BEMARKER, VERR_INVALID_PARAMETER);
    604     }
    605     /* Calculate the size of the destination text string. */
    606     /* Is this Utf16 or Utf16-LE? */
    607     if (pcwszSrc[0] == VBOX_SHCL_UTF16LEMARKER)
    608         cwDest = 0;
    609     else
    610         cwDest = 1;
    611     for (size_t i = 0; i < cwSrc; ++i, ++cwDest)
    612     {
    613         if (   (i + 1 < cwSrc)
    614             && (pcwszSrc[i] == VBOX_SHCL_CARRIAGERETURN)
    615             && (pcwszSrc[i + 1] == VBOX_SHCL_LINEFEED))
    616         {
    617             ++i;
    618         }
    619         if (pcwszSrc[i] == 0)
    620         {
    621             break;
    622         }
    623     }
    624     /* Terminating zero */
    625     ++cwDest;
    626     LogFlowFunc(("returning %d\n", cwDest));
    627     *pcwDest = cwDest;
    628     return VINF_SUCCESS;
    629 }
    630 
    631 int ShClUtf16WinToLin(PCRTUTF16 pcwszSrc, size_t cwSrc, PRTUTF16 pu16Dest, size_t cwDest)
    632 {
    633     size_t cwDestPos;
    634 
    635     LogFlowFunc(("pcwszSrc=%.*ls, cwSrc=%u, pu16Dest=%p, cwDest=%u\n",
    636                  cwSrc, pcwszSrc, cwSrc, pu16Dest, cwDest));
    637     /* A buffer of size 0 may not be an error, but it is not a good idea either. */
    638     Assert(cwDest > 0);
    639     if (!VALID_PTR(pcwszSrc) || !VALID_PTR(pu16Dest))
    640     {
    641         LogRel(("Shared Clipboard: vboxClipboardUtf16WinToLin: received an invalid pointer, returning VERR_INVALID_PARAMETER\n"));
    642         AssertReturn(VALID_PTR(pcwszSrc) && VALID_PTR(pu16Dest), VERR_INVALID_PARAMETER);
    643     }
    644     /* We only take little endian Utf16 */
    645     if (pcwszSrc[0] == VBOX_SHCL_UTF16BEMARKER)
    646     {
    647         LogRel(("Shared Clipboard: vboxClipboardUtf16WinToLin: received a big endian Utf16 string, returning VERR_INVALID_PARAMETER\n"));
    648         AssertMsgFailedReturn(("received a big endian string\n"), VERR_INVALID_PARAMETER);
    649     }
    650     if (cwDest == 0)
    651     {
    652         LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
    653         return VERR_BUFFER_OVERFLOW;
    654     }
    655     if (cwSrc == 0)
    656     {
    657         pu16Dest[0] = 0;
    658         LogFlowFunc(("received empty string.  Returning VINF_SUCCESS\n"));
    659         return VINF_SUCCESS;
    660     }
    661     /* Prepend the Utf16 byte order marker if it is missing. */
    662     if (pcwszSrc[0] == VBOX_SHCL_UTF16LEMARKER)
    663     {
    664         cwDestPos = 0;
    665     }
    666     else
    667     {
    668         pu16Dest[0] = VBOX_SHCL_UTF16LEMARKER;
    669         cwDestPos = 1;
    670     }
    671     for (size_t i = 0; i < cwSrc; ++i, ++cwDestPos)
    672     {
    673         if (pcwszSrc[i] == 0)
    674         {
    675             break;
    676         }
    677         if (cwDestPos == cwDest)
    678         {
    679             LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
    680             return VERR_BUFFER_OVERFLOW;
    681         }
    682         if (   (i + 1 < cwSrc)
    683             && (pcwszSrc[i] == VBOX_SHCL_CARRIAGERETURN)
    684             && (pcwszSrc[i + 1] == VBOX_SHCL_LINEFEED))
    685         {
    686             ++i;
    687         }
    688         pu16Dest[cwDestPos] = pcwszSrc[i];
    689     }
    690     /* Terminating zero */
    691     if (cwDestPos == cwDest)
    692     {
    693         LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
    694         return VERR_BUFFER_OVERFLOW;
    695     }
    696     pu16Dest[cwDestPos] = 0;
    697     LogFlowFunc(("set string %ls.  Returning\n", pu16Dest + 1));
    698     return VINF_SUCCESS;
    699 }
    700 
    701909int ShClDibToBmp(const void *pvSrc, size_t cbSrc, void **ppvDest, size_t *pcbDest)
    702910{
    703     size_t        cb            = sizeof(BMFILEHEADER) + cbSrc;
    704     PBMFILEHEADER pFileHeader   = NULL;
    705     void         *pvDest        = NULL;
    706     size_t        offPixel      = 0;
    707 
    708     AssertPtrReturn(pvSrc,   VERR_INVALID_PARAMETER);
    709     AssertPtrReturn(ppvDest, VERR_INVALID_PARAMETER);
    710     AssertPtrReturn(pcbDest, VERR_INVALID_PARAMETER);
     911    AssertPtrReturn(pvSrc,   VERR_INVALID_POINTER);
     912    AssertReturn(cbSrc,      VERR_INVALID_PARAMETER);
     913    AssertPtrReturn(ppvDest, VERR_INVALID_POINTER);
     914    AssertPtrReturn(pcbDest, VERR_INVALID_POINTER);
    711915
    712916    PBMINFOHEADER pBitmapInfoHeader = (PBMINFOHEADER)pvSrc;
     
    716920        || RT_LE2H_U32(pBitmapInfoHeader->uSize) != sizeof(BMINFOHEADER))
    717921    {
    718         Log(("vboxClipboardDibToBmp: invalid or unsupported bitmap data\n"));
    719922        return VERR_INVALID_PARAMETER;
    720923    }
    721924
    722     offPixel = sizeof(BMFILEHEADER)
    723                 + RT_LE2H_U32(pBitmapInfoHeader->uSize)
    724                 + RT_LE2H_U32(pBitmapInfoHeader->uClrUsed) * sizeof(uint32_t);
     925    size_t offPixel = sizeof(BMFILEHEADER)
     926                    + RT_LE2H_U32(pBitmapInfoHeader->uSize)
     927                    + RT_LE2H_U32(pBitmapInfoHeader->uClrUsed) * sizeof(uint32_t);
    725928    if (cbSrc < offPixel)
    726     {
    727         Log(("vboxClipboardDibToBmp: invalid bitmap data\n"));
    728929        return VERR_INVALID_PARAMETER;
    729     }
    730 
    731     pvDest = RTMemAlloc(cb);
     930
     931    size_t cbDst = sizeof(BMFILEHEADER) + cbSrc;
     932
     933    void *pvDest = RTMemAlloc(cbDst);
    732934    if (!pvDest)
    733     {
    734         Log(("writeToPasteboard: cannot allocate memory for bitmap\n"));
    735935        return VERR_NO_MEMORY;
    736     }
    737 
    738     pFileHeader = (PBMFILEHEADER)pvDest;
     936
     937    PBMFILEHEADER pFileHeader = (PBMFILEHEADER)pvDest;
     938
    739939    pFileHeader->uType        = BITMAPHEADERMAGIC;
    740     pFileHeader->uSize        = (uint32_t)RT_H2LE_U32(cb);
     940    pFileHeader->uSize        = (uint32_t)RT_H2LE_U32(cbDst);
    741941    pFileHeader->uReserved1   = pFileHeader->uReserved2 = 0;
    742942    pFileHeader->uOffBits     = (uint32_t)RT_H2LE_U32(offPixel);
     943
    743944    memcpy((uint8_t *)pvDest + sizeof(BMFILEHEADER), pvSrc, cbSrc);
     945
    744946    *ppvDest = pvDest;
    745     *pcbDest = cb;
     947    *pcbDest = cbDst;
     948
     949    LogFlowFuncLeaveRC(VINF_SUCCESS);
    746950    return VINF_SUCCESS;
    747951}
     
    749953int ShClBmpGetDib(const void *pvSrc, size_t cbSrc, const void **ppvDest, size_t *pcbDest)
    750954{
    751     AssertPtrReturn(pvSrc,   VERR_INVALID_PARAMETER);
    752     AssertPtrReturn(ppvDest, VERR_INVALID_PARAMETER);
    753     AssertPtrReturn(pcbDest, VERR_INVALID_PARAMETER);
     955    AssertPtrReturn(pvSrc,   VERR_INVALID_POINTER);
     956    AssertReturn(cbSrc,      VERR_INVALID_PARAMETER);
     957    AssertPtrReturn(ppvDest, VERR_INVALID_POINTER);
     958    AssertPtrReturn(pcbDest, VERR_INVALID_POINTER);
    754959
    755960    PBMFILEHEADER pFileHeader = (PBMFILEHEADER)pvSrc;
     
    758963        || RT_LE2H_U32(pFileHeader->uSize) != cbSrc)
    759964    {
    760         Log(("vboxClipboardBmpGetDib: invalid bitmap data\n"));
    761965        return VERR_INVALID_PARAMETER;
    762966    }
     
    764968    *ppvDest = ((uint8_t *)pvSrc) + sizeof(BMFILEHEADER);
    765969    *pcbDest = cbSrc - sizeof(BMFILEHEADER);
     970
    766971    return VINF_SUCCESS;
    767972}
  • trunk/src/VBox/GuestHost/SharedClipboard/clipboard-x11.cpp

    r85799 r85828  
    707707
    708708    Atom *pAtoms = (Atom *)pValue;
    709     unsigned i, j;
    710709
    711710    LogFlowFunc(("pValue=%p, *pcLen=%u, *atomType=%d%s\n",
    712711                 pValue, *pcLen, *atomType, *atomType == XT_CONVERT_FAIL ? " (XT_CONVERT_FAIL)" : ""));
    713712
     713    unsigned cFormats = *pcLen;
     714
     715    LogRel2(("Shared Clipboard: %u formats were found\n", cFormats));
     716
    714717    SHCLX11FMTIDX *pFormats = NULL;
    715     if (   *pcLen
     718    if (   cFormats
    716719        && pValue
    717720        && (*atomType != XT_CONVERT_FAIL /* time out */))
    718721    {
    719        pFormats = (SHCLX11FMTIDX *)RTMemAllocZ(*pcLen * sizeof(SHCLX11FMTIDX));
     722        /* Allocated array to hold the format indices. */
     723        pFormats = (SHCLX11FMTIDX *)RTMemAllocZ(cFormats * sizeof(SHCLX11FMTIDX));
    720724    }
    721725
     
    723727    if (pValue)
    724728    {
    725         for (i = 0; i < *pcLen; ++i)
     729        for (unsigned i = 0; i < cFormats; ++i)
    726730        {
    727731            if (pAtoms[i])
     
    739743    if (pFormats)
    740744    {
    741         for (i = 0; i < *pcLen; ++i)
    742         {
    743             for (j = 0; j < RT_ELEMENTS(g_aFormats); ++j)
     745        for (unsigned i = 0; i < cFormats; ++i)
     746        {
     747            for (unsigned j = 0; j < RT_ELEMENTS(g_aFormats); ++j)
    744748            {
    745749                Atom target = XInternAtom(XtDisplay(widget),
     
    748752                    pFormats[i] = j;
    749753            }
    750 #if defined(DEBUG) && !defined(TESTCASE)
    751             LogRel2(("%s: reporting format %d (%s)\n", __FUNCTION__,
    752                      pFormats[i], g_aFormats[pFormats[i]].pcszAtom));
     754#if !defined(TESTCASE)
     755            if (pFormats[i] != SHCLX11FMT_INVALID)
     756                LogRel2(("Shared Clipboard: Reporting format '%s'\n", g_aFormats[pFormats[i]].pcszAtom));
    753757#endif
    754758        }
     
    757761        LogFunc(("Reporting empty targets (none reported or allocation failure)\n"));
    758762
    759     clipUpdateX11Targets(pCtx, pFormats, *pcLen);
     763    clipUpdateX11Targets(pCtx, pFormats, cFormats);
    760764    RTMemFree(pFormats);
    761765
     
    13071311
    13081312/**
    1309  * Calculates a buffer size large enough to hold the source Windows format
    1310  * text converted into Unix Utf8, including the null terminator.
    1311  *
    1312  * @returns VBox status code.
    1313  * @param  pwsz                 The source text in UCS-2 with Windows EOLs.
    1314  * @param  cwc                  The size in USC-2 elements of the source text, with or
    1315  *                              without the terminator.
    1316  * @param  pcbActual            Where to store the buffer size needed.
    1317  */
    1318 static int clipWinTxtBufSizeForUtf8(PRTUTF16 pwsz, size_t cwc,
    1319                                     size_t *pcbActual)
    1320 {
    1321     size_t cbRet = 0;
    1322     int rc = RTUtf16CalcUtf8LenEx(pwsz, cwc, &cbRet);
    1323     if (RT_SUCCESS(rc))
    1324         *pcbActual = cbRet + 1;  /* null terminator */
    1325     return rc;
    1326 }
    1327 
    1328 /**
    1329  * Converts text from Windows format (UCS-2 with CRLF line endings) to standard UTF-8.
    1330  *
    1331  * @returns VBox status code.
    1332  * @param  pwszSrc              The text to be converted.
    1333  * @param  cbSrc                The length of @a pwszSrc in bytes.
    1334  * @param  pszBuf               Where to write the converted string.
    1335  * @param  cbBuf                The size of the buffer pointed to by @a pszBuf.
    1336  * @param  pcbActual            Where to store the size of the converted string.
    1337  *                              optional.
    1338  */
    1339 static int clipWinTxtToUtf8(PRTUTF16 pwszSrc, size_t cbSrc, char *pszBuf,
    1340                             size_t cbBuf, size_t *pcbActual)
    1341 {
    1342     PRTUTF16 pwszTmp = NULL;
    1343     size_t cwSrc = cbSrc / 2, cwTmp = 0, cbDest = 0;
    1344     int rc = VINF_SUCCESS;
    1345 
    1346     LogFlowFunc (("pwszSrc=%.*ls, cbSrc=%u\n", cbSrc, pwszSrc, cbSrc));
    1347     /* How long will the converted text be? */
    1348     AssertPtr(pwszSrc);
    1349     AssertPtr(pszBuf);
    1350     rc = ShClUtf16GetLinSize(pwszSrc, cwSrc, &cwTmp);
    1351     if (RT_SUCCESS(rc) && cwTmp == 0)
    1352         rc = VERR_NO_DATA;
    1353     if (RT_SUCCESS(rc))
    1354         pwszTmp = (PRTUTF16)RTMemAlloc(cwTmp * 2);
    1355     if (!pwszTmp)
    1356         rc = VERR_NO_MEMORY;
    1357     /* Convert the text. */
    1358     if (RT_SUCCESS(rc))
    1359         rc = ShClUtf16WinToLin(pwszSrc, cwSrc, pwszTmp, cwTmp);
    1360     if (RT_SUCCESS(rc))
    1361     {
    1362         /* Convert the UTF-16 string to Utf8. */
    1363         rc = RTUtf16ToUtf8Ex(pwszTmp + 1, cwTmp - 1, &pszBuf, cbBuf,
    1364                              &cbDest);
    1365     }
    1366     RTMemFree(reinterpret_cast<void *>(pwszTmp));
    1367     if (pcbActual)
    1368         *pcbActual = cbDest + 1;
    1369 
    1370     if (RT_SUCCESS(rc))
    1371         LogFlowFunc (("converted string is %.*s. Returning.\n", cbDest, pszBuf));
    1372 
    1373     LogFlowFuncLeaveRC(rc);
    1374     return rc;
    1375 }
    1376 
    1377 /**
    1378  * Satisfies a request from X11 to convert the clipboard text to UTF-8.  We
    1379  * return null-terminated text, but can cope with non-null-terminated input.
    1380  *
    1381  * @returns VBox status code.
     1313 * Satisfies a request from X11 to convert the clipboard text to UTF-8 LF.
     1314 *
     1315 * @returns VBox status code. VERR_NO_DATA if no data was converted.
    13821316 * @param  pDisplay             An X11 display structure, needed for conversions
    13831317 *                              performed by Xlib.
     
    13951329 *                              data we are returning.
    13961330 */
    1397 static int clipWinTxtToUtf8ForX11CB(Display *pDisplay, PRTUTF16 pwszSrc,
    1398                                     size_t cbSrc, Atom *atomTarget,
    1399                                     Atom *atomTypeReturn,
    1400                                     XtPointer *pValReturn,
    1401                                     unsigned long *pcLenReturn,
    1402                                     int *piFormatReturn)
    1403 {
    1404     RT_NOREF(pDisplay, pcLenReturn);
     1331static int clipUtf16CRLFToUtf8LF(Display *pDisplay, PRTUTF16 pwszSrc,
     1332                                 size_t cbSrc, Atom *atomTarget,
     1333                                 Atom *atomTypeReturn,
     1334                                 XtPointer *pValReturn,
     1335                                 unsigned long *pcLenReturn,
     1336                                 int *piFormatReturn)
     1337{
     1338    RT_NOREF(pDisplay);
     1339
     1340    const size_t cwcSrc = cbSrc / sizeof(RTUTF16);
     1341    if (!cwcSrc)
     1342        return VERR_NO_DATA;
    14051343
    14061344    /* This may slightly overestimate the space needed. */
    1407     size_t cbDest = 0;
    1408     int rc = clipWinTxtBufSizeForUtf8(pwszSrc, cbSrc / 2, &cbDest);
     1345    size_t chDst = 0;
     1346    int rc = ShClUtf16LenUtf8(pwszSrc, cwcSrc, &chDst);
    14091347    if (RT_SUCCESS(rc))
    14101348    {
    1411         char  *pszDest  = (char *)XtMalloc(cbDest);
     1349        char  *pszDest  = (char *)XtMalloc(chDst);
    14121350        size_t cbActual = 0;
    14131351        if (pszDest)
    14141352        {
    1415             rc = clipWinTxtToUtf8(pwszSrc, cbSrc, pszDest, cbDest, &cbActual);
     1353            rc = ShClConvUtf16CRLFToUtf8LF(pwszSrc, cwcSrc, pszDest, chDst, &cbActual);
    14161354        }
    14171355        else
     
    14211359        {
    14221360            *atomTypeReturn = *atomTarget;
    1423             *pValReturn = (XtPointer)pszDest;
    1424             *pcLenReturn = cbActual;
     1361            *pValReturn     = (XtPointer)pszDest;
     1362            *pcLenReturn    = cbActual;
    14251363            *piFormatReturn = 8;
    14261364        }
    14271365    }
     1366
     1367    LogFlowFuncLeaveRC(rc);
    14281368    return rc;
    14291369}
     
    15271467            rc = VERR_NO_DATA;
    15281468        if (RT_SUCCESS(rc) && ((clipFormat == SHCLX11FMT_UTF8) || (clipFormat == SHCLX11FMT_TEXT)))
    1529             rc = clipWinTxtToUtf8ForX11CB(XtDisplay(pCtx->pWidget),
    1530                                           (PRTUTF16)pv, cb, atomTarget,
    1531                                           atomTypeReturn, pValReturn,
    1532                                           pcLenReturn, piFormatReturn);
     1469            rc = clipUtf16CRLFToUtf8LF(XtDisplay(pCtx->pWidget),
     1470                                       (PRTUTF16)pv, cb, atomTarget,
     1471                                       atomTypeReturn, pValReturn,
     1472                                       pcLenReturn, piFormatReturn);
    15331473        if (RT_SUCCESS(rc))
    15341474            clipTrimTrailingNul(*(XtPointer *)pValReturn, pcLenReturn, clipFormat);
     
    17691709
    17701710/**
    1771  * Massages generic UTF-16 with CR end-of-lines into the format Windows expects
    1772  * and return the result in a RTMemAlloc allocated buffer.
    1773  *
    1774  * @returns VBox status code.
    1775  * @param  pwcSrc               The source as UTF-16.
    1776  * @param  cwcSrc               The number of 16bit elements in @a pwcSrc, not counting
    1777  *                              the terminating zero.
    1778  * @param  ppwszDest            Where to store the buffer address.
    1779  * @param  pcbDest              On success, where to store the number of bytes written.
    1780  *                              Undefined otherwise.  Optional.
    1781  */
    1782 static int clipUtf16ToWinTxt(RTUTF16 *pwcSrc, size_t cwcSrc,
    1783                              PRTUTF16 *ppwszDest, uint32_t *pcbDest)
    1784 {
    1785     AssertPtrReturn(pwcSrc, VERR_INVALID_POINTER);
    1786     AssertPtrReturn(ppwszDest, VERR_INVALID_POINTER);
    1787 
    1788     LogFlowFunc(("pwcSrc=%p, cwcSrc=%u, ppwszDest=%p\n", pwcSrc, cwcSrc, ppwszDest));
    1789 
    1790     if (pcbDest)
    1791         *pcbDest = 0;
    1792 
    1793     PRTUTF16 pwszDest = NULL;
    1794     size_t   cwcDest;
    1795     int rc = ShClUtf16GetWinSize(pwcSrc, cwcSrc + 1, &cwcDest);
    1796     if (RT_SUCCESS(rc))
    1797     {
    1798         pwszDest = (PRTUTF16)RTMemAlloc(cwcDest * sizeof(RTUTF16));
    1799         if (!pwszDest)
    1800             rc = VERR_NO_MEMORY;
    1801     }
    1802 
    1803     if (RT_SUCCESS(rc))
    1804         rc = ShClUtf16LinToWin(pwcSrc, cwcSrc + 1, pwszDest, cwcDest);
    1805 
    1806     if (RT_SUCCESS(rc))
    1807     {
    1808         LogFlowFunc(("Converted string is %.*ls\n", cwcDest, pwszDest));
    1809 
    1810         *ppwszDest = pwszDest;
    1811 
    1812         if (pcbDest)
    1813             *pcbDest = cwcDest * sizeof(RTUTF16);
    1814     }
    1815     else
    1816         RTMemFree(pwszDest);
    1817 
    1818     LogFlowFuncLeaveRC(rc);
    1819     return rc;
    1820 }
    1821 
    1822 /**
    1823  * Converts UTF-8 text with CR end-of-lines into UTF-16 as Windows expects it
    1824  * and return the result in a RTMemAlloc allocated buffer.
    1825  *
    1826  * @returns VBox status code.
    1827  * @param  pcSrc                The source UTF-8.
    1828  * @param  cbSrc                The size of the source in bytes, not counting the
    1829  *                              terminating zero.
    1830  * @param  ppwszDest            Where to store the buffer address.
    1831  * @param  pcbDest              On success, where to store the number of bytes written.
    1832  *                              Undefined otherwise.  Optional.
    1833  */
    1834 static int clipUtf8ToWinTxt(const char *pcSrc, unsigned cbSrc,
    1835                             PRTUTF16 *ppwszDest, uint32_t *pcbDest)
    1836 {
    1837     AssertPtrReturn(pcSrc, VERR_INVALID_POINTER);
    1838     AssertPtrReturn(ppwszDest, VERR_INVALID_POINTER);
    1839 
    1840     LogFlowFunc(("pcSrc=%p, cbSrc=%u, ppwszDest=%p\n", pcSrc, cbSrc, ppwszDest));
    1841 
    1842     if (pcbDest)
    1843         *pcbDest = 0;
    1844 
    1845     /* Intermediate conversion to UTF-16. */
    1846     size_t   cwcTmp;
    1847     PRTUTF16 pwcTmp = NULL;
    1848     int rc = RTStrToUtf16Ex(pcSrc, cbSrc, &pwcTmp, 0, &cwcTmp);
    1849     if (RT_SUCCESS(rc))
    1850         rc = clipUtf16ToWinTxt(pwcTmp, cwcTmp, ppwszDest, pcbDest);
    1851 
    1852     RTUtf16Free(pwcTmp);
    1853 
    1854     LogFlowFuncLeaveRC(rc);
    1855     return rc;
    1856 }
    1857 
    1858 /**
    1859  * Converts Latin-1 text with CR end-of-lines into UTF-16 as Windows expects
    1860  * it and return the result in a RTMemAlloc allocated buffer.
    1861  *
    1862  * @returns VBox status code.
    1863  * @param  pcSrc                The source text.
    1864  * @param  cbSrc                The size of the source in bytes, not counting the
    1865  *                              terminating zero.
    1866  * @param  ppwszDest            Where to store the buffer address.
    1867  * @param  pcbDest              On success, where to store the number of bytes written.
    1868  *                              Undefined otherwise.  Optional.
    1869  */
    1870 static int clipLatin1ToWinTxt(char *pcSrc, unsigned cbSrc,
    1871                               PRTUTF16 *ppwszDest, uint32_t *pcbDest)
    1872 {
    1873     AssertPtrReturn(pcSrc, VERR_INVALID_POINTER);
    1874     AssertPtrReturn(ppwszDest, VERR_INVALID_POINTER);
    1875 
    1876     LogFlowFunc(("pcSrc=%.*s, cbSrc=%u, ppwszDest=%p\n", cbSrc, (char *) pcSrc, cbSrc, ppwszDest));
    1877 
    1878     PRTUTF16 pwszDest = NULL;
    1879     int rc = VINF_SUCCESS;
    1880 
    1881     /* Calculate the space needed. */
    1882     unsigned cwcDest = 0;
    1883     for (unsigned i = 0; i < cbSrc && pcSrc[i] != '\0'; ++i)
    1884     {
    1885         if (pcSrc[i] == VBOX_SHCL_LINEFEED)
    1886             cwcDest += 2;
    1887         else
    1888             ++cwcDest;
    1889     }
    1890 
    1891     ++cwcDest;  /* Leave space for the terminator. */
    1892 
    1893     if (pcbDest)
    1894         *pcbDest = cwcDest * sizeof(RTUTF16);
    1895 
    1896     pwszDest = (PRTUTF16) RTMemAlloc(cwcDest * sizeof(RTUTF16));
    1897     if (!pwszDest)
    1898         rc = VERR_NO_MEMORY;
    1899 
    1900     /* And do the conversion, bearing in mind that Latin-1 expands "naturally"
    1901      * to UTF-16. */
    1902     if (RT_SUCCESS(rc))
    1903     {
    1904         for (unsigned i = 0, j = 0; i < cbSrc; ++i, ++j)
    1905         {
    1906             if (pcSrc[i] != VBOX_SHCL_LINEFEED)
    1907                 pwszDest[j] = pcSrc[i];
    1908             else
    1909             {
    1910                 pwszDest[j] = VBOX_SHCL_CARRIAGERETURN;
    1911                 pwszDest[j + 1] = VBOX_SHCL_LINEFEED;
    1912                 ++j;
    1913             }
    1914         }
    1915 
    1916         pwszDest[cwcDest - 1] = '\0';  /* Make sure we are zero-terminated. */
    1917 
    1918         LogFlowFunc(("Converted text is %.*ls\n", cwcDest, pwszDest));
    1919     }
    1920 
    1921     if (RT_SUCCESS(rc))
    1922     {
    1923         *ppwszDest = pwszDest;
    1924     }
    1925     else
    1926         RTMemFree(pwszDest);
    1927 
    1928     LogFlowFuncLeaveRC(rc);
    1929     return rc;
    1930 }
    1931 
    1932 /**
    1933 * Converts UTF-16 text into UTF-8 as Windows expects
    1934 * it and return the result in a RTMemAlloc allocated buffer.
    1935 *
    1936 * @returns VBox status code.
    1937 * @param  pcSrc                 The source text.
    1938 * @param  cbSrc                 The size of the source in bytes, not counting the
    1939 *                               terminating zero.
    1940 * @param  ppwszDest             Where to store the buffer address.
    1941 * @param  pcbDest               On success, where to store the number of bytes written.
    1942 *                               Undefined otherwise.  Optional.
    1943 */
    1944 static int clipUTF16ToWinHTML(RTUTF16 *pwcBuf, size_t cb, char **ppszOut, uint32_t *pcOut)
    1945 {
    1946     AssertPtrReturn(pwcBuf,  VERR_INVALID_POINTER);
    1947     AssertReturn   (cb,      VERR_INVALID_PARAMETER);
    1948     AssertPtrReturn(ppszOut, VERR_INVALID_POINTER);
    1949     AssertPtrReturn(pcOut,   VERR_INVALID_POINTER);
    1950 
    1951     if (cb % 2)
    1952         return VERR_INVALID_PARAMETER;
    1953 
    1954     size_t cwc = cb / 2;
    1955     size_t i = 0;
    1956     RTUTF16 *pwc = pwcBuf;
    1957     char *pchRes = NULL;
    1958     size_t cRes = 0;
    1959     LogFlowFunc(("src= %ls cb=%d i=%i, %x %x\n", pwcBuf, cb, i, ppszOut, pcOut));
    1960     while (i < cwc)
    1961     {
    1962         /* find  zero symbol (end of string) */
    1963         for (; i < cwc && pwcBuf[i] != 0; i++)
    1964             ;
    1965         LogFlowFunc(("skipped nulls i=%d cwc=%d\n", i, cwc));
    1966 
    1967         /* convert found string */
    1968         char *psz = NULL;
    1969         size_t cch = 0;
    1970         int rc = RTUtf16ToUtf8Ex(pwc, cwc, &psz, pwc - pwcBuf, &cch);
    1971         LogFlowFunc(("utf16toutf8 src= %ls res=%s i=%i\n", pwc, psz, i));
    1972         if (RT_FAILURE(rc))
    1973         {
    1974             RTMemFree(pchRes);
    1975             return rc;
    1976         }
    1977 
    1978         /* append new substring */
    1979         char *pchNew = (char *)RTMemRealloc(pchRes, cRes + cch + 1);
    1980         if (!pchNew)
    1981         {
    1982             RTMemFree(pchRes);
    1983             RTStrFree(psz);
    1984             return VERR_NO_MEMORY;
    1985         }
    1986         pchRes = pchNew;
    1987         memcpy(pchRes + cRes, psz, cch + 1);
    1988         LogFlowFunc(("Temp result res=%s\n", pchRes + cRes));
    1989 
    1990         /* remove temporary buffer */
    1991         RTStrFree(psz);
    1992         cRes += cch + 1;
    1993         /* skip zero symbols */
    1994         for (; i < cwc && pwcBuf[i] == 0; i++)
    1995             ;
    1996         /* remember start of string */
    1997         pwc += i;
    1998     }
    1999     *ppszOut = pchRes;
    2000     *pcOut = cRes;
    2001 
    2002     return VINF_SUCCESS;
    2003 }
    2004 
    2005 /**
    20061711 * Converts the data obtained from the X11 clipboard to the required format,
    20071712 * place it in the buffer supplied and signal that data has arrived.
     
    20241729    int rc = VINF_SUCCESS;
    20251730
    2026     void    *pvDst = NULL;
    2027     uint32_t cbDst = 0;
     1731    void  *pvDst = NULL;
     1732    size_t cbDst = 0;
    20281733
    20291734    if (pvSrc == NULL)
     
    20411746            case SHCLX11FMT_TEXT:
    20421747            {
    2043                 /* If we are given broken UTF-8, we treat it as Latin1. */ /** @todo Is this acceptable? */
     1748                size_t cwDst;
     1749
     1750                /* If we are given broken UTF-8, we treat it as Latin1. */ /** @todo BUGBUG Is this acceptable? */
    20441751                if (RT_SUCCESS(RTStrValidateEncodingEx((char *)pvSrc, cbSrc, 0)))
     1752                    rc = ShClConvUtf8LFToUtf16CRLF((const char *)pvSrc, cbSrc,
     1753                                                   (PRTUTF16 *)&pvDst, &cwDst);
     1754                else
     1755                    rc = ShClConvLatin1LFToUtf16CRLF((char *)pvSrc, cbSrc,
     1756                                                     (PRTUTF16 *)&pvDst, &cbDst);
     1757                if (RT_SUCCESS(rc))
    20451758                {
    2046                     rc = clipUtf8ToWinTxt((const char *)pvSrc, cbSrc,
    2047                                           (PRTUTF16 *)&pvDst, &cbDst);
    2048                 }
    2049                 else
    2050                 {
    2051                     rc = clipLatin1ToWinTxt((char *)pvSrc, cbSrc,
    2052                                             (PRTUTF16 *)&pvDst, &cbDst);
     1759                    AssertBreakStmt(cwDst, rc = VERR_INVALID_PARAMETER);
     1760                    cbDst = cwDst * sizeof(RTUTF16); /* Convert RTUTF16 units to bytes. */
    20531761                }
    20541762                break;
     
    21131821                 * Some applications sends data in UTF-16, some in UTF-8,
    21141822                 * without indication it in MIME.
    2115                  * But in case of UTF-16, at least an OpenOffice adds Byte Order Mark - 0xfeff
    2116                  * at start of clipboard data.
     1823                 *
     1824                 * In case of UTF-16, at least [Open|Libre] Office adds an byte order mark (0xfeff)
     1825                 * at the start of the clipboard data.
    21171826                 */
    21181827                if (   cbSrc >= sizeof(RTUTF16)
    2119                     && *(PRTUTF16)pvSrc == 0xfeff)
     1828                    && *(PRTUTF16)pvSrc == VBOX_SHCL_UTF16LEMARKER)
    21201829                {
    2121                     LogFlowFunc((" \n"));
    2122                     rc = clipUTF16ToWinHTML((RTUTF16 *)pvSrc, cbSrc,
    2123                                             (char**)&pvDst, &cbDst);
     1830                    rc = ShClConvUtf16ToUtf8HTML((PRTUTF16)pvSrc, cbSrc / sizeof(RTUTF16), (char**)&pvDst, &cbDst);
     1831                    if (RT_SUCCESS(rc))
     1832                    {
     1833                        LogFlowFunc(("UTF-16 Unicode source (%u bytes):\n%ls\n\n", cbSrc, pvSrc));
     1834                        LogFlowFunc(("Byte Order Mark = %hx", ((PRTUTF16)pvSrc)[0]));
     1835                        LogFlowFunc(("UTF-8 Unicode dest (%u bytes):\n%s\n\n", cbDst, pvDst));
     1836                    }
     1837                    else
     1838                        LogRel(("Shared Clipboard: Converting UTF-16 Unicode failed with %Rrc\n", rc));
    21241839                }
    2125                 else
     1840                else /* Raw data. */
    21261841                {
    21271842                   pvDst = RTMemAlloc(cbSrc);
     
    21381853                }
    21391854
    2140                 LogFlowFunc(("Source unicode %ls, cbSrc = %d\n, Byte Order Mark = %hx", pvSrc, cbSrc, ((PRTUTF16)pvSrc)[0]));
    2141                 LogFlowFunc(("converted to win unicode %s, cbDest = %d, rc = %Rrc\n", pvDst, cbDst, rc));
    21421855                rc = VINF_SUCCESS;
    21431856                break;
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