Changeset 20551 in vbox for trunk/src/VBox
- Timestamp:
- Jun 14, 2009 4:31:50 PM (16 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
TabularUnified trunk/src/VBox/GuestHost/SharedClipboard/x11-clipboard.cpp ¶
r20137 r20551 1131 1131 /** 1132 1132 * 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. 1134 1134 * @returns IPRT status code 1135 * @returns VERR_BUFFER_OVERFLOW if the buffer is not large enough1136 1135 * @param pwcSrc The source Utf16 1137 1136 * @param cwcSrc The number of 16bit elements in @a pwcSrc, not counting 1138 1137 * 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 1144 1141 */ 1145 1142 static int clipUtf16ToWinTxt(RTUTF16 *pwcSrc, size_t cwcSrc, 1146 void *pvBuf, unsigned cbBuf, uint32_t *pcbActual)1147 { 1148 LogFlowFunc(("pwcSrc=%p, cwcSrc=%u, p vBuf=%p, cbBuf=%u", pwcSrc, cwcSrc,1149 p vBuf, cbBuf));1143 PRTUTF16 *ppwszDest, uint32_t *pcbDest) 1144 { 1145 LogFlowFunc(("pwcSrc=%p, cwcSrc=%u, ppwszDest=%p\n", pwcSrc, cwcSrc, 1146 ppwszDest)); 1150 1147 AssertPtrReturn(pwcSrc, VERR_INVALID_POINTER); 1151 AssertPtrReturn(p vBuf, VERR_INVALID_POINTER);1152 if (pcb Actual)1153 *pcb Actual= 0;1154 PRTUTF16 pw cDest = reinterpret_cast<PRTUTF16>(pvBuf);1148 AssertPtrReturn(ppwszDest, VERR_INVALID_POINTER); 1149 if (pcbDest) 1150 *pcbDest = 0; 1151 PRTUTF16 pwszDest = NULL; 1155 1152 size_t cwcDest; 1156 1153 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 }1163 1154 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 } 1166 1160 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); 1172 1172 LogFlowFunc(("returning %Rrc\n", rc)); 1173 if (pcb Actual)1174 LogFlowFunc(("*pcb Actual=%u\n", *pcbActual));1173 if (pcbDest) 1174 LogFlowFunc(("*pcbDest=%u\n", *pcbDest)); 1175 1175 return rc; 1176 1176 } … … 1178 1178 /** 1179 1179 * 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. 1181 1181 * @returns IPRT status code 1182 * @returns VERR_BUFFER_OVERFLOW if the buffer is not large enough1183 1182 * @param pcSrc The source Utf-8 1184 1183 * @param cbSrc The size of the source in bytes, not counting the 1185 1184 * 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 */ 1189 static 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)); 1197 1194 AssertPtrReturn(pcSrc, VERR_INVALID_POINTER); 1198 AssertPtrReturn(p vBuf, VERR_INVALID_POINTER);1199 if (pcb Actual)1200 *pcb Actual= 0;1195 AssertPtrReturn(ppwszDest, VERR_INVALID_POINTER); 1196 if (pcbDest) 1197 *pcbDest = 0; 1201 1198 /* Intermediate conversion to UTF16 */ 1202 1199 size_t cwcTmp; … … 1204 1201 int rc = RTStrToUtf16Ex(pcSrc, cbSrc, &pwcTmp, 0, &cwcTmp); 1205 1202 if (RT_SUCCESS(rc)) 1206 rc = clipUtf16ToWinTxt(pwcTmp, cwcTmp, p vBuf, cbBuf, pcbActual);1203 rc = clipUtf16ToWinTxt(pwcTmp, cwcTmp, ppwszDest, pcbDest); 1207 1204 RTUtf16Free(pwcTmp); 1208 1205 LogFlowFunc(("Returning %Rrc\n", rc)); 1209 if (pcb Actual)1210 LogFlowFunc(("*pcb Actual=%u\n", *pcbActual));1206 if (pcbDest) 1207 LogFlowFunc(("*pcbDest=%u\n", *pcbDest)); 1211 1208 return rc; 1212 1209 } … … 1214 1211 /** 1215 1212 * 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. 1217 1214 * @returns IPRT status code 1218 * @returns VERR_BUFFER_OVERFLOW if the buffer is not large enough1219 1215 * @param widget An Xt widget, necessary because we use Xt/Xlib for the 1220 1216 * conversion … … 1222 1218 * @param cbSrc The size of the source in bytes, not counting the 1223 1219 * 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 1229 1223 */ 1230 1224 static int clipCTextToWinTxt(Widget widget, unsigned char *pcSrc, 1231 unsigned cbSrc, void *pvBuf, unsigned cbBuf,1232 uint32_t *pcb Actual)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)); 1236 1230 AssertReturn(widget, VERR_INVALID_PARAMETER); 1237 1231 AssertPtrReturn(pcSrc, VERR_INVALID_POINTER); 1238 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); 1232 AssertPtrReturn(ppwszDest, VERR_INVALID_POINTER); 1233 if (pcbDest) 1234 *pcbDest = 0; 1239 1235 1240 1236 /* Special case as X*TextProperty* can't seem to handle empty strings. */ 1241 1237 if (cbSrc == 0) 1242 1238 { 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; 1247 1245 return VINF_SUCCESS; 1248 1246 } 1249 1247 1250 if (pcb Actual)1251 *pcb Actual= 0;1248 if (pcbDest) 1249 *pcbDest = 0; 1252 1250 /* Intermediate conversion to Utf8 */ 1253 1251 int rc = VINF_SUCCESS; … … 1274 1272 /* Now convert the UTF8 to UTF16 */ 1275 1273 if (RT_SUCCESS(rc)) 1276 rc = clipUtf8ToWinTxt(*ppcTmp, strlen(*ppcTmp), pvBuf, cbBuf, 1277 pcbActual); 1274 rc = clipUtf8ToWinTxt(*ppcTmp, strlen(*ppcTmp), ppwszDest, pcbDest); 1278 1275 if (ppcTmp != NULL) 1279 1276 XFreeStringList(ppcTmp); 1280 1277 LogFlowFunc(("Returning %Rrc\n", rc)); 1281 if (pcb Actual)1282 LogFlowFunc(("*pcb Actual=%u\n", *pcbActual));1278 if (pcbDest) 1279 LogFlowFunc(("*pcbDest=%u\n", *pcbDest)); 1283 1280 return rc; 1284 1281 } … … 1286 1283 /** 1287 1284 * 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. 1289 1286 * @returns IPRT status code 1290 * @returns VERR_BUFFER_OVERFLOW if the buffer is not large enough1291 1287 * @param pcSrc The source text 1292 1288 * @param cbSrc The size of the source in bytes, not counting the 1293 1289 * 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 */ 1294 static 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)); 1305 1299 AssertPtrReturn(pcSrc, VERR_INVALID_POINTER); 1306 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); 1300 AssertPtrReturn(ppwszDest, VERR_INVALID_POINTER); 1301 PRTUTF16 pwszDest = NULL; 1307 1302 int rc = VINF_SUCCESS; 1308 1303 … … 1315 1310 ++cwcDest; 1316 1311 ++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; 1321 1317 1322 1318 /* And do the convertion, bearing in mind that Latin-1 expands "naturally" … … 1324 1320 if (RT_SUCCESS(rc)) 1325 1321 { 1326 PRTUTF16 pwcDest = (PRTUTF16) pvBuf;1327 1322 for (unsigned i = 0, j = 0; i < cbSrc; ++i, ++j) 1328 1323 if (pcSrc[i] != LINEFEED) 1329 pw cDest[j] = pcSrc[i];1324 pwszDest[j] = pcSrc[i]; 1330 1325 else 1331 1326 { 1332 pw cDest[j] = CARRIAGERETURN;1333 pw cDest[j + 1] = LINEFEED;1327 pwszDest[j] = CARRIAGERETURN; 1328 pwszDest[j + 1] = LINEFEED; 1334 1329 ++j; 1335 1330 } 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); 1339 1338 LogFlowFunc(("Returning %Rrc\n", rc)); 1340 if (pcb Actual)1341 LogFlowFunc(("*pcb Actual=%u\n", *pcbActual));1339 if (pcbDest) 1340 LogFlowFunc(("*pcbDest=%u\n", *pcbDest)); 1342 1341 return rc; 1343 1342 } … … 1347 1346 struct _CLIPREADX11CBREQ 1348 1347 { 1349 /** The buffer to write X11 clipboard data to (valid during a request1350 * for the clipboard contents) */1351 void *mBuffer;1352 /** The size of the buffer to write X11 clipboard data to (valid during1353 * a request for the clipboard contents) */1354 unsigned mSize;1355 1348 /** The format VBox would like the data in */ 1356 1349 uint32_t mFormat; … … 1359 1352 /** The clipboard context this request is associated with */ 1360 1353 CLIPBACKEND *mCtx; 1354 /** The request structure passed in from the backend. */ 1355 CLIPREADCBREQ *mReq; 1361 1356 }; 1362 1357 … … 1375 1370 { 1376 1371 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)); 1381 1374 AssertPtr(pReq->mCtx); 1382 1375 Assert(pReq->mFormat != 0); /* sanity */ … … 1384 1377 CLIPBACKEND *pCtx = pReq->mCtx; 1385 1378 unsigned cbSrc = (*pcLen) * (*piFormat) / 8; 1386 uint32_t cbActual = 0; 1379 void *pvDest = NULL; 1380 uint32_t cbDest = 0; 1387 1381 1388 1382 if (pvSrc == NULL) … … 1398 1392 case CTEXT: 1399 1393 rc = clipCTextToWinTxt(widget, (unsigned char *)pvSrc, cbSrc, 1400 pReq->mBuffer, pReq->mSize, 1401 &cbActual); 1394 (PRTUTF16 *) &pvDest, &cbDest); 1402 1395 break; 1403 1396 case UTF8: … … 1408 1401 0))) 1409 1402 rc = clipUtf8ToWinTxt((const char *)pvSrc, cbSrc, 1410 pReq->mBuffer, pReq->mSize, 1411 &cbActual); 1403 (PRTUTF16 *) &pvDest, &cbDest); 1412 1404 else 1413 1405 rc = clipLatin1ToWinTxt((char *) pvSrc, cbSrc, 1414 pReq->mBuffer, pReq->mSize, 1415 &cbActual); 1406 (PRTUTF16 *) &pvDest, &cbDest); 1416 1407 break; 1417 1408 } … … 1423 1414 rc = VERR_NOT_IMPLEMENTED; 1424 1415 XtFree((char *)pvSrc); 1425 ClipCompleteDataRequestFromX11(pReq->mCtx->pFrontend, rc, cbActual); 1416 ClipCompleteDataRequestFromX11(pReq->mCtx->pFrontend, rc, pReq->mReq, 1417 pvDest, cbDest); 1418 RTMemFree(pvDest); 1426 1419 RTMemFree(pReq); 1427 1420 if (RT_SUCCESS(rc)) … … 1442 1435 CLIPREADX11CBREQ *pReq = (CLIPREADX11CBREQ *)pUserData; 1443 1436 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)); 1446 1438 1447 1439 int rc = VINF_SUCCESS; … … 1477 1469 /* The clipboard callback was never scheduled, so we must signal 1478 1470 * 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); 1480 1473 RTMemFree(pReq); 1481 1474 } … … 1495 1488 * @note We allocate a request structure which must be freed by the worker 1496 1489 */ 1497 int ClipRequestDataFromX11(CLIPBACKEND *pCtx, uint32_t u32Format, void *pv,1498 uint32_t cb)1490 int ClipRequestDataFromX11(CLIPBACKEND *pCtx, uint32_t u32Format, 1491 CLIPREADCBREQ *pReq) 1499 1492 { 1500 1493 /* … … 1504 1497 return VERR_NO_DATA; 1505 1498 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) 1508 1502 rc = VERR_NO_MEMORY; 1509 1503 else 1510 1504 { 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; 1515 1508 /* We use this to schedule a worker function on the event thread. */ 1516 1509 clipQueueToEventThread(pCtx->appContext, vboxClipboardReadX11Worker, 1517 (XtPointer) p Req);1510 (XtPointer) pX11Req); 1518 1511 } 1519 1512 return rc; … … 1950 1943 } 1951 1944 1945 #define MAX_BUF_SIZE 256 1946 1952 1947 static int g_completedRC = VINF_SUCCESS; 1953 static int g_completedActual = 0; 1948 static int g_completedCB = 0; 1949 static CLIPREADCBREQ *g_completedReq = NULL; 1950 static char g_completedBuf[MAX_BUF_SIZE]; 1954 1951 1955 1952 void 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 1967 static void clipGetCompletedRequest(int *prc, char ** ppc, uint32_t *pcb, 1968 CLIPREADCBREQ **ppReq) 1963 1969 { 1964 1970 *prc = g_completedRC; 1965 *pcbActual = g_completedActual; 1971 *ppc = g_completedBuf; 1972 *pcb = g_completedCB; 1973 *ppReq = g_completedReq; 1966 1974 } 1967 1975 #ifdef RT_OS_SOLARIS_10 … … 1984 1992 #endif 1985 1993 1986 #define MAX_BUF_SIZE 256 1987 1988 static bool testStringFromX11(CLIPBACKEND *pCtx, uint32_t cbBuf, 1989 const char *pcszExp, int rcExp) 1994 static bool testStringFromX11(CLIPBACKEND *pCtx, const char *pcszExp, 1995 int rcExp) 1990 1996 { 1991 1997 bool retval = false; 1992 AssertReturn(cbBuf <= MAX_BUF_SIZE, false);1993 1998 if (!clipPollTargets()) 1994 1999 RTPrintf("Failed to poll for targets\n"); … … 1997 2002 else 1998 2003 { 1999 char pc[MAX_BUF_SIZE]; 2004 char *pc; 2005 CLIPREADCBREQ *pReq = (CLIPREADCBREQ *)&pReq, *pReqRet = NULL; 2000 2006 ClipRequestDataFromX11(pCtx, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT, 2001 (void *) pc, cbBuf);2007 pReq); 2002 2008 int rc = VINF_SUCCESS; 2003 2009 uint32_t cbActual = 0; 2004 clipGetCompletedRequest(&rc, & cbActual);2010 clipGetCompletedRequest(&rc, &pc, &cbActual, &pReqRet); 2005 2011 if (rc != rcExp) 2006 2012 RTPrintf("Wrong return code, expected %Rrc, got %Rrc\n", rcExp, 2007 2013 rc); 2014 else if (pReqRet != pReq) 2015 RTPrintf("Wrong returned request data, expected %p, got %p\n", 2016 pReq, pReqRet); 2008 2017 else if (RT_FAILURE(rcExp)) 2009 2018 retval = true; … … 2038 2047 } 2039 2048 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); 2042 2050 return retval; 2043 2051 } 2044 2052 2045 static bool testLatin1FromX11(CLIPBACKEND *pCtx, uint32_t cbBuf,2046 const char *pcszExp,int rcExp)2053 static bool testLatin1FromX11(CLIPBACKEND *pCtx,const char *pcszExp, 2054 int rcExp) 2047 2055 { 2048 2056 bool retval = false; 2049 AssertReturn(cbBuf <= MAX_BUF_SIZE, false);2050 2057 if (!clipPollTargets()) 2051 2058 RTPrintf("Failed to poll for targets\n"); … … 2054 2061 else 2055 2062 { 2056 char pc[MAX_BUF_SIZE]; 2063 char *pc; 2064 CLIPREADCBREQ *pReq = (CLIPREADCBREQ *)&pReq, *pReqRet = NULL; 2057 2065 ClipRequestDataFromX11(pCtx, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT, 2058 (void *) pc, cbBuf);2066 pReq); 2059 2067 int rc = VINF_SUCCESS; 2060 2068 uint32_t cbActual = 0; 2061 clipGetCompletedRequest(&rc, & cbActual);2069 clipGetCompletedRequest(&rc, &pc, &cbActual, &pReqRet); 2062 2070 if (rc != rcExp) 2063 2071 RTPrintf("Wrong return code, expected %Rrc, got %Rrc\n", rcExp, 2064 2072 rc); 2073 else if (pReqRet != pReq) 2074 RTPrintf("Wrong returned request data, expected %p, got %p\n", 2075 pReq, pReqRet); 2065 2076 else if (RT_FAILURE(rcExp)) 2066 2077 retval = true; … … 2091 2102 } 2092 2103 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); 2095 2105 return retval; 2096 2106 } … … 2156 2166 CLIPBACKEND *pCtx = ClipConstructX11(NULL); 2157 2167 unsigned cErrs = 0; 2158 char pc[MAX_BUF_SIZE];2168 char *pc; 2159 2169 uint32_t cbActual; 2170 CLIPREADCBREQ *pReq = (CLIPREADCBREQ *)&pReq, *pReqRet = NULL; 2160 2171 int rc = ClipStartX11(pCtx); 2161 2172 AssertRCReturn(rc, 1); … … 2166 2177 clipSetSelectionValues("UTF8_STRING", XA_STRING, "hello world", 2167 2178 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)) 2180 2180 ++cErrs; 2181 2181 /* With an embedded carriage return */ 2182 2182 clipSetSelectionValues("text/plain;charset=UTF-8", XA_STRING, 2183 2183 "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)) 2186 2185 ++cErrs; 2187 2186 /* An empty string */ 2188 2187 clipSetSelectionValues("text/plain;charset=utf-8", XA_STRING, "", 2189 2188 sizeof(""), 8); 2190 if (!testStringFromX11(pCtx, sizeof("") * 2,"", VINF_SUCCESS))2189 if (!testStringFromX11(pCtx, "", VINF_SUCCESS)) 2191 2190 ++cErrs; 2192 2191 /* With an embedded Utf-8 character. */ … … 2194 2193 "100\xE2\x82\xAC" /* 100 Euro */, 2195 2194 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)) 2198 2196 ++cErrs; 2199 2197 /* A non-zero-terminated string */ 2200 2198 clipSetSelectionValues("TEXT", XA_STRING, 2201 2199 "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)) 2204 2201 ++cErrs; 2205 2202 … … 2209 2206 clipSetSelectionValues("COMPOUND_TEXT", XA_STRING, "hello world", 2210 2207 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)) 2223 2209 ++cErrs; 2224 2210 /* With an embedded carriage return */ 2225 2211 clipSetSelectionValues("COMPOUND_TEXT", XA_STRING, "hello\nworld", 2226 2212 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)) 2229 2214 ++cErrs; 2230 2215 /* An empty string */ 2231 2216 clipSetSelectionValues("COMPOUND_TEXT", XA_STRING, "", 2232 2217 sizeof(""), 8); 2233 if (!testStringFromX11(pCtx, sizeof("") * 2,"", VINF_SUCCESS))2218 if (!testStringFromX11(pCtx, "", VINF_SUCCESS)) 2234 2219 ++cErrs; 2235 2220 /* A non-zero-terminated string */ 2236 2221 clipSetSelectionValues("COMPOUND_TEXT", XA_STRING, 2237 2222 "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)) 2240 2224 ++cErrs; 2241 2225 … … 2245 2229 clipSetSelectionValues("STRING", XA_STRING, "Georges Dupr\xEA", 2246 2230 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)) 2259 2232 ++cErrs; 2260 2233 /* With an embedded carriage return */ 2261 2234 clipSetSelectionValues("TEXT", XA_STRING, "Georges\nDupr\xEA", 2262 2235 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)) 2265 2237 ++cErrs; 2266 2238 /* A non-zero-terminated string */ … … 2268 2240 "Georges Dupr\xEA!", 2269 2241 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)) 2272 2243 ++cErrs; 2273 2244 … … 2277 2248 clipSetSelectionValues("UTF8_STRING", XT_CONVERT_FAIL, "hello world", 2278 2249 sizeof("hello world"), 8); 2279 if (!testStringFromX11(pCtx, 256,"hello world", VERR_TIMEOUT))2250 if (!testStringFromX11(pCtx, "hello world", VERR_TIMEOUT)) 2280 2251 ++cErrs; 2281 2252 … … 2285 2256 0, 8); 2286 2257 ClipRequestDataFromX11(pCtx, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT, 2287 (void *) pc, sizeof(pc));2288 clipGetCompletedRequest(&rc, & cbActual);2258 pReq); 2259 clipGetCompletedRequest(&rc, &pc, &cbActual, &pReqRet); 2289 2260 if (rc != VERR_NO_DATA) 2290 2261 { 2291 2262 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); 2292 2269 ++cErrs; 2293 2270 } … … 2295 2272 /*** request for an invalid VBox format from X11 ***/ 2296 2273 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); 2299 2276 if (rc != VERR_NOT_IMPLEMENTED) 2300 2277 { 2301 2278 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); 2302 2285 ++cErrs; 2303 2286 } … … 2452 2435 2453 2436 void ClipCompleteDataRequestFromX11(VBOXCLIPBOARDCONTEXT *pCtx, int rc, 2454 uint32_t cbActual) 2437 CLIPREADCBREQ *pReq, void *pv, 2438 uint32_t cb) 2455 2439 {} 2456 2440 -
TabularUnified trunk/src/VBox/HostServices/SharedClipboard/x11-clipboard.cpp ¶
r19875 r20551 197 197 } 198 198 199 /** Structure describing a request for clipoard data from the guest. */ 200 struct _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 199 210 /** 200 211 * Called when VBox wants to read the X11 clipboard. … … 210 221 * @param pcbActual Where to write the actual size of the written data 211 222 * @note We always fail or complete asynchronously 212 * @note On success allocates a CLIPREAD X11CBCONTEXTstructure which must be223 * @note On success allocates a CLIPREADCBREQ structure which must be 213 224 * freed in ClipCompleteDataRequestFromX11 when it is called back from 214 225 * the backend code. … … 222 233 pClient, u32Format, pv, cb, pcbActual)); 223 234 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 } 228 248 LogFlowFunc(("returning %Rrc\n", rc)); 229 249 return rc; … … 242 262 */ 243 263 void 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); 247 271 } 248 272 … … 410 434 { 411 435 uint32_t format; 412 void *pv;413 uint32_t cb;414 436 int rc; 437 CLIPREADCBREQ *pReq; 415 438 } readData; 416 439 struct _COMPLETEREAD … … 478 501 479 502 extern int ClipRequestDataFromX11(CLIPBACKEND *pBackend, uint32_t u32Format, 480 void *pv, uint32_t cb)503 CLIPREADCBREQ *pReq) 481 504 { 482 505 pBackend->readData.format = u32Format; 483 pBackend->readData.pv = pv; 484 pBackend->readData.cb = cb; 506 pBackend->readData.pReq = pReq; 485 507 return pBackend->readData.rc; 486 508 } … … 518 540 if ( pBackend->readData.format != 519 541 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) 522 545 { 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); 526 550 ++cErrors; 527 551 } 528 552 else 529 553 { 530 ClipCompleteDataRequestFromX11(client.pCtx, VERR_NO_DATA, 43); 554 ClipCompleteDataRequestFromX11(client.pCtx, VERR_NO_DATA, 555 pBackend->readData.pReq, NULL, 43); 531 556 if ( pBackend->completeRead.rc != VERR_NO_DATA 532 557 || pBackend->completeRead.cbActual != 43)
Note:
See TracChangeset
for help on using the changeset viewer.