VirtualBox

Changeset 62797 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Aug 1, 2016 9:20:08 AM (8 years ago)
Author:
vboxsync
Message:

VBoxClipboard-win.cpp: Counted my way thru s_szFormatSample and cleaned up related code.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxClipboard-win.cpp

    r62793 r62797  
    4242typedef FNREMOVECLIPBOARDFORMATLISTENER *PFNREMOVECLIPBOARDFORMATLISTENER;
    4343
    44 /*Forward declarations*/
    45 int ConvertMimeToCFHTML(const char *source, size_t cb, char **output, size_t *pcch);
    46 int ConvertCFHtmlToMime(const char *source, const uint32_t cch, char **output, size_t *pcch);
    47 bool IsWindowsHTML(const char *source);
     44/*********************************************************************************************************************************
     45*   Internal Functions                                                                                                           *
     46*********************************************************************************************************************************/
     47static int ConvertCFHtmlToMime(const char *pszSource, const uint32_t cch, char **ppszOutput, uint32_t *pch);
     48static int ConvertMimeToCFHTML(const char *pszSource, size_t cb, char **ppszOutput, uint32_t *pcbOutput);
     49static bool IsWindowsHTML(const char *source);
    4850
    4951
     
    205207
    206208
     209/** @todo Someone please explain the protocol wrt overflows...  */
    207210static void vboxClipboardGetData (uint32_t u32Format, const void *pvSrc, uint32_t cbSrc,
    208211                                  void *pvDst, uint32_t cbDst, uint32_t *pcbActualDst)
     
    210213    dprintf (("vboxClipboardGetData.\n"));
    211214
    212     *pcbActualDst = cbSrc;
    213 
    214215    LogFlow(("vboxClipboardGetData cbSrc = %d, cbDst = %d\n", cbSrc, cbDst));
    215216
    216     if (cbSrc > cbDst)
    217     {
    218         /* Do not copy data. The dst buffer is not enough. */
    219         return;
    220     }
    221 
    222     if (u32Format == VBOX_SHARED_CLIPBOARD_FMT_HTML &&
    223                             IsWindowsHTML((const char*)pvSrc))
    224     {
    225         char* buffer = NULL;
    226         size_t cbuf = 0;
    227         ConvertCFHtmlToMime((const char*)pvSrc, cbSrc, (char**)&buffer, &cbuf);
    228         if (cbuf > cbDst)
     217    if (   u32Format == VBOX_SHARED_CLIPBOARD_FMT_HTML
     218        && IsWindowsHTML((const char *)pvSrc))
     219    {
     220        /** @todo r=bird: Why the double conversion? */
     221        char *pszBuf = NULL;
     222        uint32_t cbBuf = 0;
     223        int rc = ConvertCFHtmlToMime((const char*)pvSrc, cbSrc, &pszBuf, &cbBuf);
     224        if (RT_SUCCESS(rc))
     225        {
     226            *pcbActualDst = cbBuf;
     227            if (cbBuf > cbDst)
     228            {
     229                /* Do not copy data. The dst buffer is not enough. */
     230                RTMemFree(pszBuf);
     231                return;
     232            }
     233            memcpy(pvDst, pszBuf, cbBuf);
     234            RTMemFree(pszBuf);
     235        }
     236        else
     237            *pcbActualDst = 0;
     238    }
     239    else
     240    {
     241        *pcbActualDst = cbSrc;
     242
     243        if (cbSrc > cbDst)
    229244        {
    230245            /* Do not copy data. The dst buffer is not enough. */
    231246            return;
    232247        }
    233         memcpy(pvDst, buffer, cbuf);
    234         *pcbActualDst = cbuf;
    235         RTMemFree(buffer);
    236     }
    237     else
    238     {
     248
    239249        memcpy(pvDst, pvSrc, cbSrc);
    240250    }
     
    669679}
    670680
    671 DECLCALLBACK(int) VBoxClipboardThread (RTTHREAD ThreadSelf, void *pInstance)
    672 {
     681DECLCALLBACK(int) VBoxClipboardThread (RTTHREAD hThreadSelf, void *pvUser)
     682{
     683    RT_NOREF2(hThreadSelf, pvUser);
    673684    /* Create a window and make it a clipboard viewer. */
    674685    int rc = VINF_SUCCESS;
     
    778789    if (g_ctx.hwnd)
    779790    {
    780         int rc = PostMessage (g_ctx.hwnd, WM_CLOSE, 0, 0);
     791        PostMessage (g_ctx.hwnd, WM_CLOSE, 0, 0);
    781792    }
    782793
     
    819830void vboxClipboardDisconnect (VBOXCLIPBOARDCLIENTDATA *pClient)
    820831{
     832    RT_NOREF1(pClient);
    821833    Log(("vboxClipboardDisconnect\n"));
    822834
     
    987999    if (cb > 0)
    9881000    {
    989         char* pszResult = NULL;
    990         size_t cch;
    991 
    992         if(u32Format == VBOX_SHARED_CLIPBOARD_FMT_HTML &&
    993             !IsWindowsHTML((const char*)pv))
     1001        char *pszResult = NULL;
     1002
     1003        if (   u32Format == VBOX_SHARED_CLIPBOARD_FMT_HTML
     1004            && !IsWindowsHTML((const char*)pv))
    9941005        {
    9951006            /* check that this is not already CF_HTML */
    996             int rc = ConvertMimeToCFHTML((const char*)pv, cb, &pszResult, &cch);
     1007            uint32_t cbResult;
     1008            int rc = ConvertMimeToCFHTML((const char *)pv, cb, &pszResult, &cbResult);
    9971009            if (RT_SUCCESS(rc))
    9981010            {
    999                 if (pszResult != NULL && cch != 0)
    1000                 {
    1001                     pClient->data.pv = pszResult;
    1002                     pClient->data.cb = cch;
     1011                if (pszResult != NULL && cbResult != 0)
     1012                {
     1013                    pClient->data.pv        = pszResult;
     1014                    pClient->data.cb        = cbResult;
    10031015                    pClient->data.u32Format = u32Format;
    10041016                }
     
    10071019        else
    10081020        {
    1009             pClient->data.pv = RTMemAlloc (cb);
     1021            pClient->data.pv = RTMemDup(pv, cb);
    10101022            if (pClient->data.pv)
    10111023            {
    1012                 memcpy (pClient->data.pv, pv, cb);
    10131024                pClient->data.cb = cb;
    10141025                pClient->data.u32Format = u32Format;
     
    10251036 *
    10261037 * @returns VBox status code
    1027  * @param   pcszSrc     source in CF_HTML format
    1028  * @param   pcszOption  Name of CF_HTML field
    1029  * @param   pcValue     Where to return extracted value of CF_HTML field
     1038 * @param   pszSrc      source in CF_HTML format
     1039 * @param   pszOption   Name of CF_HTML field
     1040 * @param   puValue     Where to return extracted value of CF_HTML field
    10301041 */
    1031 int GetHeaderValue(const char *pcszSrc, const char *pcszOption, size_t *pcValue)
    1032 {
    1033     size_t cOptionLenght = 0;
     1042static int GetHeaderValue(const char *pszSrc, const char *pszOption, uint32_t *puValue)
     1043{
    10341044    int rc = VERR_INVALID_PARAMETER;
    10351045
    1036     Assert(pcszSrc);
    1037     Assert(pcszOption);
    1038 
    1039     char* pcszOptionValue = RTStrStr(pcszSrc, pcszOption);
    1040     if (pcszOptionValue)
    1041     {
    1042         rc = RTStrNLenEx(pcszOption, RTSTR_MAX, &cOptionLenght);
    1043         Assert(cOptionLenght);
    1044         if (RT_SUCCESS(rc))
    1045         {
    1046             int32_t tmpValue;
    1047             rc = RTStrToInt32Ex(pcszOptionValue + cOptionLenght, NULL, 10, &tmpValue);
    1048             if (RT_SUCCESS(rc))
    1049             {
    1050                 *pcValue = tmpValue;
    1051                 rc = VINF_SUCCESS;
    1052             }
    1053         }
     1046    Assert(pszSrc);
     1047    Assert(pszOption);
     1048
     1049    const char *pszOptionValue = RTStrStr(pszSrc, pszOption);
     1050    if (pszOptionValue)
     1051    {
     1052        size_t cchOption = strlen(pszOption);
     1053        Assert(cchOption);
     1054
     1055        rc = RTStrToUInt32Ex(pszOptionValue + cchOption, NULL, 10, puValue);
    10541056    }
    10551057    return rc;
     
    10621064 * @returns @c true if the @source string is in CF_HTML format
    10631065 */
    1064 bool IsWindowsHTML(const char *pcszSource)
    1065 {
    1066     return RTStrStr(pcszSource, "Version:") != NULL
    1067         && RTStrStr(pcszSource, "StartHTML:") != NULL;
     1066static bool IsWindowsHTML(const char *pszSource)
     1067{
     1068    return RTStrStr(pszSource, "Version:") != NULL
     1069        && RTStrStr(pszSource, "StartHTML:") != NULL;
    10681070}
    10691071
     
    10751077 *
    10761078 * @returns VBox status code.
    1077  * @param   pcszSource  The input.
     1079 * @param   pszSource   The input.
    10781080 * @param   cch         The length of the input.
    10791081 * @param   ppszOutput  Where to return the result.  Free using RTMemFree.
    1080  * @param   pcch        Where to the return length of the result (bytes/chars).
     1082 * @param   pcbOutput   Where to the return length of the result (bytes/chars).
    10811083 */
    1082 int ConvertCFHtmlToMime(const char *pcszSource, const uint32_t cch, char **ppszOutput, size_t *pcch)
    1083 {
    1084     char *result = NULL;
    1085 
    1086     Assert(pcszSource);
     1084static int ConvertCFHtmlToMime(const char *pszSource, const uint32_t cch, char **ppszOutput, uint32_t *pcbOutput)
     1085{
     1086    Assert(pszSource);
    10871087    Assert(cch);
    10881088    Assert(ppszOutput);
    1089     Assert(pcch);
    1090 
    1091     size_t cStartOffset, cEndOffset;
    1092     int rc = GetHeaderValue(pcszSource, "StartFragment:", &cStartOffset);
    1093     if (!RT_SUCCESS(rc))
     1089    Assert(pcbOutput);
     1090
     1091    uint32_t offStart;
     1092    int rc = GetHeaderValue(pszSource, "StartFragment:", &offStart);
     1093    if (RT_SUCCESS(rc))
     1094    {
     1095        uint32_t offEnd;
     1096        rc = GetHeaderValue(pszSource, "EndFragment:", &offEnd);
     1097        if (RT_SUCCESS(rc))
     1098        {
     1099            if (   offStart > 0
     1100                && offEnd > 0
     1101                && offEnd > offStart
     1102                && offEnd <= cch)
     1103            {
     1104                uint32_t cchSubStr = offEnd - offStart;
     1105                char *pszResult = (char *)RTMemAlloc(cchSubStr + 1);
     1106                if (pszResult)
     1107                {
     1108                    rc = RTStrCopyEx(pszResult, cchSubStr + 1, pszSource + offStart, cchSubStr);
     1109                    if (RT_SUCCESS(rc))
     1110                    {
     1111                        *ppszOutput = pszResult;
     1112                        *pcbOutput  = (uint32_t)(cchSubStr + 1);
     1113                        rc = VINF_SUCCESS;
     1114                    }
     1115                    else
     1116                    {
     1117                        LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected EndFragment. rc = %Rrc\n", rc));
     1118                        RTMemFree(pszResult);
     1119                    }
     1120                }
     1121                else
     1122                {
     1123                    LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected EndFragment.\n"));
     1124                    rc = VERR_NO_MEMORY;
     1125                }
     1126            }
     1127            else
     1128            {
     1129                LogRelFlowFunc(("Error: CF_HTML out of bounds - offStart=%#x offEnd=%#x cch=%#x\n", offStart, offEnd, cch));
     1130                rc = VERR_INVALID_PARAMETER;
     1131            }
     1132        }
     1133        else
     1134        {
     1135            LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected EndFragment. rc = %Rrc.\n", rc));
     1136            rc = VERR_INVALID_PARAMETER;
     1137        }
     1138    }
     1139    else
    10941140    {
    10951141        LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected StartFragment. rc = %Rrc.\n", rc));
    1096         return VERR_INVALID_PARAMETER;
    1097     }
    1098     rc = GetHeaderValue(pcszSource, "EndFragment:", &cEndOffset);
    1099     if (!RT_SUCCESS(rc))
    1100     {
    1101         LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected EndFragment. rc = %Rrc.\n", rc));
    1102         return VERR_INVALID_PARAMETER;
    1103     }
    1104     if (cStartOffset > 0 && cEndOffset > 0 && cEndOffset > cStartOffset)
    1105     {
    1106         size_t cSubstrlen = cEndOffset - cStartOffset;
    1107         result = (char *)RTMemAlloc(cSubstrlen + 1);
    1108         if (result)
    1109         {
    1110             RT_BZERO(result, cSubstrlen + 1);
    1111             rc = RTStrCopyEx(result, cSubstrlen + 1, pcszSource + cStartOffset, cSubstrlen);
    1112             if (RT_SUCCESS(rc))
    1113             {
    1114                 *ppszOutput = result;
    1115                 *pcch = cSubstrlen + 1;
    1116             }
    1117             else
    1118             {
    1119                 LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected EndFragment. rc = %Rrc\n", rc));
    1120                 return rc;
    1121             }
    1122         }
    1123         else
    1124         {
    1125             LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected EndFragment.\n"));
    1126             return VERR_NO_MEMORY;
    1127         }
    1128     }
    1129 
    1130     return VINF_SUCCESS;
     1142        rc = VERR_INVALID_PARAMETER;
     1143    }
     1144
     1145    return rc;
    11311146}
    11321147
     
    11341149
    11351150/*
    1136  * Converts source Utf16 mime html clipboard data to Utf8 CF_HTML format.
     1151 * Converts source UTF-8 MIME HTML clipboard data to UTF-8 CF_HTML format.
     1152 *
     1153 * This is just encapsulation work, slapping a header on the data.
    11371154 *
    11381155 * It allocates
     
    11451162 *   EndFragment   = Header length + fragment length - 38(ending length)
    11461163 *
    1147  * @param   pcszSource  Source buffer that contains utf-16 string in mime html format
     1164 * @param   pszSource   Source buffer that contains utf-16 string in mime html format
    11481165 * @param   cb          Size of source buffer in bytes
    11491166 * @param   ppszOutput  Where to return the allocated output buffer to put converted UTF-8
    11501167 *                      CF_HTML clipboard data.  This function allocates memory for this.
    1151  * @param   pcch        Where to return the Size of allocated result buffer in bytes/chars.
     1168 * @param   pcbOutput   Where to return the size of allocated result buffer in bytes/chars, including zero terminator
    11521169 *
    11531170 * @note    output buffer should be free using RTMemFree()
    11541171 * @note    Everything inside of fragment can be UTF8. Windows allows it. Everything in header should be Latin1.
    11551172 */
    1156 int ConvertMimeToCFHTML(const char *pcszSource, size_t cb, char **ppszOutput, size_t *pcch)
     1173static int ConvertMimeToCFHTML(const char *pszSource, size_t cb, char **ppszOutput, uint32_t *pcbOutput)
    11571174{
    11581175    Assert(pszOutput);
    1159     Assert(pcch);
    1160     Assert(pcszSource);
     1176    Assert(pcbOutput);
     1177    Assert(pszSource);
    11611178    Assert(cb);
    11621179
    1163     size_t cFragmentLength = 0;
    1164 
    1165     char *pszBuf = (char *)pcszSource;
    1166 
    11671180    /* construct CF_HTML formatted string */
    1168     char* pszResult = NULL;
    1169     int rc = RTStrNLenEx(pszBuf, RTSTR_MAX, &cFragmentLength);
     1181    char *pszResult = NULL;
     1182    size_t cchFragment;
     1183    int rc = RTStrNLenEx(pszSource, cb, &cchFragment);
    11701184    if (!RT_SUCCESS(rc))
    11711185    {
     
    11881202    */
    11891203    static const char s_szFormatSample[] =
    1190         "Version:1.0\r\n"
    1191         "StartHTML:000000101\r\n"
    1192         "EndHTML:%09d\r\n" // END HTML = Header length + fragment lengh
    1193         "StartFragment:000000137\r\n"
    1194         "EndFragment:%09d\r\n"
    1195         "<html>\r\n"
    1196         "<body>\r\n"
    1197         "<!--StartFragment-->%s<!--EndFragment-->\r\n"
    1198         "</body>\r\n"
    1199         "</html>\r\n";
     1204    /*   0:   */ "Version:1.0\r\n"
     1205    /*  13:   */ "StartHTML:000000101\r\n"
     1206    /*  34:   */ "EndHTML:%0000009u\r\n" // END HTML = Header length + fragment length
     1207    /*  53:   */ "StartFragment:000000137\r\n"
     1208    /*  78:   */ "EndFragment:%0000009u\r\n"
     1209    /* 101:   */ "<html>\r\n"
     1210    /* 109:   */ "<body>\r\n"
     1211    /* 117:   */ "<!--StartFragment-->"
     1212    /* 137:   */ "%s"
     1213    /* 137+2: */ "<!--EndFragment-->\r\n"
     1214    /* 157+2: */ "</body>\r\n"
     1215    /* 166+2: */ "</html>\r\n";
     1216    /* 175+2: */
     1217    AssertCompile(sizeof(s_szFormatSample) == 175+2+1);
    12001218
    12011219    /* calculate parameters of CF_HTML header */
    1202     size_t cHeaderLength = (sizeof(s_szFormatSample) - 1) + 8;
    1203     size_t cEndHtml = cHeaderLength + cFragmentLength;
    1204     size_t cEndFragment = cHeaderLength + cFragmentLength - 38;
    1205     pszResult = (char*)RTMemAlloc(cEndHtml + 1);
     1220    size_t cchHeader      = sizeof(s_szFormatSample) - 1;
     1221    size_t offEndHtml     = cchHeader + cchFragment;
     1222    size_t offEndFragment = cchHeader + cchFragment - 38; /* 175-137 = 38 */
     1223    pszResult = (char *)RTMemAlloc(offEndHtml + 1);
    12061224    if (pszResult == NULL)
    12071225    {
     
    12111229
    12121230    /* format result CF_HTML string */
    1213     rc = RTStrPrintf(pszResult, cEndHtml + 1, s_szFormatSample, cEndHtml, cEndFragment, pszBuf);
    1214     if (rc == -1)
    1215     {
    1216         LogRelFlowFunc(("Error: cannot construct CF_HTML. rc = %Rrc.\n"));
    1217         return VERR_CANT_CREATE;
    1218     }
    1219     Assert(cEndHtml == rc);
    1220 
    1221 #ifdef DEBUG
    1222     {
    1223         /*Control calculations. check consistency.*/
    1224         const char pcszStartFragment[] = "<!--StartFragment-->";
    1225         const char pcszEndFragment[] = "<!--EndFragment-->";
    1226 
    1227         /* check 'StartFragment:' value */
    1228         const char* pcszRealStartFragment = RTStrStr(pszResult, pcszStartFragment);
    1229         Assert((pcszRealStartFragment + sizeof(pcszStartFragment) - 1) - pszResult == 137);//141);
    1230 
    1231         /* check 'EndFragment:' value */
    1232         const char* pcszRealEndFragment = RTStrStr(pszResult, pcszEndFragment);
    1233         Assert((pcszRealEndFragment - pszResult) == cEndFragment);
    1234     }
     1231    size_t cchFormatted = RTStrPrintf(pszResult, offEndHtml + 1,
     1232                                      s_szFormatSample, offEndHtml, offEndFragment, pszSource);
     1233    Assert(offEndHtml == cchFormatted); NOREF(cchFormatted);
     1234
     1235#ifdef VBOX_STRICT
     1236    /* Control calculations. check consistency.*/
     1237    static const char s_szStartFragment[] = "<!--StartFragment-->";
     1238    static const char s_szEndFragment[] = "<!--EndFragment-->";
     1239
     1240    /* check 'StartFragment:' value */
     1241    const char *pszRealStartFragment = RTStrStr(pszResult, s_szStartFragment);
     1242    Assert(&pszRealStartFragment[sizeof(s_szStartFragment) - 1] - pszResult == 137);
     1243
     1244    /* check 'EndFragment:' value */
     1245    const char *pszRealEndFragment = RTStrStr(pszResult, s_szEndFragment);
     1246    Assert((pszRealEndFragment - pszResult) == offEndFragment);
    12351247#endif
    12361248
    12371249    *ppszOutput = pszResult;
    1238     *pcch = rc + 1;
     1250    *pcbOutput = (uint32_t)cchFormatted + 1;
     1251    Assert(*pcbOutput == cchFormatted + 1);
    12391252
    12401253    return VINF_SUCCESS;
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