Changeset 62797 in vbox for trunk/src/VBox
- Timestamp:
- Aug 1, 2016 9:20:08 AM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostServices/SharedClipboard/VBoxClipboard-win.cpp
r62793 r62797 42 42 typedef FNREMOVECLIPBOARDFORMATLISTENER *PFNREMOVECLIPBOARDFORMATLISTENER; 43 43 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 *********************************************************************************************************************************/ 47 static int ConvertCFHtmlToMime(const char *pszSource, const uint32_t cch, char **ppszOutput, uint32_t *pch); 48 static int ConvertMimeToCFHTML(const char *pszSource, size_t cb, char **ppszOutput, uint32_t *pcbOutput); 49 static bool IsWindowsHTML(const char *source); 48 50 49 51 … … 205 207 206 208 209 /** @todo Someone please explain the protocol wrt overflows... */ 207 210 static void vboxClipboardGetData (uint32_t u32Format, const void *pvSrc, uint32_t cbSrc, 208 211 void *pvDst, uint32_t cbDst, uint32_t *pcbActualDst) … … 210 213 dprintf (("vboxClipboardGetData.\n")); 211 214 212 *pcbActualDst = cbSrc;213 214 215 LogFlow(("vboxClipboardGetData cbSrc = %d, cbDst = %d\n", cbSrc, cbDst)); 215 216 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) 229 244 { 230 245 /* Do not copy data. The dst buffer is not enough. */ 231 246 return; 232 247 } 233 memcpy(pvDst, buffer, cbuf); 234 *pcbActualDst = cbuf; 235 RTMemFree(buffer); 236 } 237 else 238 { 248 239 249 memcpy(pvDst, pvSrc, cbSrc); 240 250 } … … 669 679 } 670 680 671 DECLCALLBACK(int) VBoxClipboardThread (RTTHREAD ThreadSelf, void *pInstance) 672 { 681 DECLCALLBACK(int) VBoxClipboardThread (RTTHREAD hThreadSelf, void *pvUser) 682 { 683 RT_NOREF2(hThreadSelf, pvUser); 673 684 /* Create a window and make it a clipboard viewer. */ 674 685 int rc = VINF_SUCCESS; … … 778 789 if (g_ctx.hwnd) 779 790 { 780 int rc =PostMessage (g_ctx.hwnd, WM_CLOSE, 0, 0);791 PostMessage (g_ctx.hwnd, WM_CLOSE, 0, 0); 781 792 } 782 793 … … 819 830 void vboxClipboardDisconnect (VBOXCLIPBOARDCLIENTDATA *pClient) 820 831 { 832 RT_NOREF1(pClient); 821 833 Log(("vboxClipboardDisconnect\n")); 822 834 … … 987 999 if (cb > 0) 988 1000 { 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)) 994 1005 { 995 1006 /* 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); 997 1009 if (RT_SUCCESS(rc)) 998 1010 { 999 if (pszResult != NULL && c ch!= 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; 1003 1015 pClient->data.u32Format = u32Format; 1004 1016 } … … 1007 1019 else 1008 1020 { 1009 pClient->data.pv = RTMem Alloc (cb);1021 pClient->data.pv = RTMemDup(pv, cb); 1010 1022 if (pClient->data.pv) 1011 1023 { 1012 memcpy (pClient->data.pv, pv, cb);1013 1024 pClient->data.cb = cb; 1014 1025 pClient->data.u32Format = u32Format; … … 1025 1036 * 1026 1037 * @returns VBox status code 1027 * @param p cszSrcsource in CF_HTML format1028 * @param p cszOptionName of CF_HTML field1029 * @param p cValue Where to return extracted value of CF_HTML field1038 * @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 1030 1041 */ 1031 int GetHeaderValue(const char *pcszSrc, const char *pcszOption, size_t *pcValue) 1032 { 1033 size_t cOptionLenght = 0; 1042 static int GetHeaderValue(const char *pszSrc, const char *pszOption, uint32_t *puValue) 1043 { 1034 1044 int rc = VERR_INVALID_PARAMETER; 1035 1045 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); 1054 1056 } 1055 1057 return rc; … … 1062 1064 * @returns @c true if the @source string is in CF_HTML format 1063 1065 */ 1064 bool IsWindowsHTML(const char *pcszSource)1065 { 1066 return RTStrStr(p cszSource, "Version:") != NULL1067 && RTStrStr(p cszSource, "StartHTML:") != NULL;1066 static bool IsWindowsHTML(const char *pszSource) 1067 { 1068 return RTStrStr(pszSource, "Version:") != NULL 1069 && RTStrStr(pszSource, "StartHTML:") != NULL; 1068 1070 } 1069 1071 … … 1075 1077 * 1076 1078 * @returns VBox status code. 1077 * @param p cszSourceThe input.1079 * @param pszSource The input. 1078 1080 * @param cch The length of the input. 1079 1081 * @param ppszOutput Where to return the result. Free using RTMemFree. 1080 * @param pc chWhere to the return length of the result (bytes/chars).1082 * @param pcbOutput Where to the return length of the result (bytes/chars). 1081 1083 */ 1082 int ConvertCFHtmlToMime(const char *pcszSource, const uint32_t cch, char **ppszOutput, size_t *pcch) 1083 { 1084 char *result = NULL; 1085 1086 Assert(pcszSource); 1084 static int ConvertCFHtmlToMime(const char *pszSource, const uint32_t cch, char **ppszOutput, uint32_t *pcbOutput) 1085 { 1086 Assert(pszSource); 1087 1087 Assert(cch); 1088 1088 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 1094 1140 { 1095 1141 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; 1131 1146 } 1132 1147 … … 1134 1149 1135 1150 /* 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. 1137 1154 * 1138 1155 * It allocates … … 1145 1162 * EndFragment = Header length + fragment length - 38(ending length) 1146 1163 * 1147 * @param p cszSourceSource buffer that contains utf-16 string in mime html format1164 * @param pszSource Source buffer that contains utf-16 string in mime html format 1148 1165 * @param cb Size of source buffer in bytes 1149 1166 * @param ppszOutput Where to return the allocated output buffer to put converted UTF-8 1150 1167 * CF_HTML clipboard data. This function allocates memory for this. 1151 * @param pc ch 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 1152 1169 * 1153 1170 * @note output buffer should be free using RTMemFree() 1154 1171 * @note Everything inside of fragment can be UTF8. Windows allows it. Everything in header should be Latin1. 1155 1172 */ 1156 int ConvertMimeToCFHTML(const char *pcszSource, size_t cb, char **ppszOutput, size_t *pcch)1173 static int ConvertMimeToCFHTML(const char *pszSource, size_t cb, char **ppszOutput, uint32_t *pcbOutput) 1157 1174 { 1158 1175 Assert(pszOutput); 1159 Assert(pc ch);1160 Assert(p cszSource);1176 Assert(pcbOutput); 1177 Assert(pszSource); 1161 1178 Assert(cb); 1162 1179 1163 size_t cFragmentLength = 0;1164 1165 char *pszBuf = (char *)pcszSource;1166 1167 1180 /* 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); 1170 1184 if (!RT_SUCCESS(rc)) 1171 1185 { … … 1188 1202 */ 1189 1203 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); 1200 1218 1201 1219 /* calculate parameters of CF_HTML header */ 1202 size_t c HeaderLength = (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); 1206 1224 if (pszResult == NULL) 1207 1225 { … … 1211 1229 1212 1230 /* 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); 1235 1247 #endif 1236 1248 1237 1249 *ppszOutput = pszResult; 1238 *pcch = rc + 1; 1250 *pcbOutput = (uint32_t)cchFormatted + 1; 1251 Assert(*pcbOutput == cchFormatted + 1); 1239 1252 1240 1253 return VINF_SUCCESS;
Note:
See TracChangeset
for help on using the changeset viewer.