Changeset 100204 in vbox for trunk/src/VBox/HostServices/SharedClipboard
- Timestamp:
- Jun 19, 2023 9:11:37 AM (20 months ago)
- svn:sync-xref-src-repo-rev:
- 157911
- Location:
- trunk/src/VBox/HostServices/SharedClipboard
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-darwin.cpp
r98103 r100204 262 262 * Now, request the data from the guest. 263 263 */ 264 return ShClSvc GuestDataRequest(pClient, fFormats, NULL /* pidEvent */);264 return ShClSvcReadDataFromGuestAsync(pClient, fFormats, NULL /* ppEvent */); 265 265 } 266 266 -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-internal.h
r99951 r100204 186 186 /** Transfer context. */ 187 187 SHCLTRANSFERCTX Ctx; 188 /** Transfers callbacks to use. */ 189 SHCLTRANSFERCALLBACKTABLE Callbacks; 188 190 } SHCLIENTTRANSFERS, *PSHCLIENTTRANSFERS; 189 191 #endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */ … … 302 304 # ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 303 305 int shClSvcTransferModeSet(uint32_t fMode); 304 int shClSvcTransferStart(PSHCLCLIENT pClient, SHCLTRANSFERDIR enmDir, SHCLSOURCE enmSource, PSHCLTRANSFER *ppTransfer); 305 int shClSvcTransferStop(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer); 306 int shClSvcTransferInit(PSHCLCLIENT pClient, SHCLTRANSFERDIR enmDir, SHCLSOURCE enmSource, PSHCLTRANSFER *ppTransfer); 307 int shClSvcTransferStart(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer); 308 int shClSvcTransferStop(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer, bool fWaitForGuest); 306 309 bool shClSvcTransferMsgIsAllowed(uint32_t uMode, uint32_t uMsg); 307 310 void shClSvcClientTransfersReset(PSHCLCLIENT pClient); … … 312 315 * @{ 313 316 */ 314 int ShClSvc GuestDataRequest(PSHCLCLIENT pClient, SHCLFORMATS fFormats, PSHCLEVENT *ppEvent);317 int ShClSvcReadDataFromGuestAsync(PSHCLCLIENT pClient, SHCLFORMATS fFormats, PSHCLEVENT *ppEvent); 315 318 int ShClSvcGuestDataSignal(PSHCLCLIENT pClient, PSHCLCLIENTCMDCTX pCmdCtx, SHCLFORMAT uFormat, void *pvData, uint32_t cbData); 316 319 int ShClSvcHostReportFormats(PSHCLCLIENT pClient, SHCLFORMATS fFormats); … … 493 496 #endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP */ 494 497 495 int shClSvcTransferIfaceRootsGet(PSHCLTXPROVIDERCTX pCtx, PSHCLROOTLIST *ppRootList); 496 498 int shClSvcTransferIfaceRootsGet(PSHCLTXPROVIDERCTX pCtx, PSHCLLIST pRootList); 497 499 int shClSvcTransferIfaceListOpen(PSHCLTXPROVIDERCTX pCtx, PSHCLLISTOPENPARMS pOpenParms, PSHCLLISTHANDLE phList); 498 500 int shClSvcTransferIfaceListClose(PSHCLTXPROVIDERCTX pCtx, SHCLLISTHANDLE hList); -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-transfers.cpp
r99969 r100204 97 97 *********************************************************************************************************************************/ 98 98 99 /** @copydoc SHCLTXPROVIDERIFACE::pfnRoot sGet*/100 DECLCALLBACK(int) shClSvcTransferIfaceRoot sGet(PSHCLTXPROVIDERCTX pCtx, PSHCLROOTLIST *ppRootList)99 /** @copydoc SHCLTXPROVIDERIFACE::pfnRootListRead */ 100 DECLCALLBACK(int) shClSvcTransferIfaceRootListRead(PSHCLTXPROVIDERCTX pCtx) 101 101 { 102 102 LogFlowFuncEnter(); … … 132 132 if (RT_SUCCESS(rc)) 133 133 { 134 PSHCLROOTLISTHDR pSrcRootListHdr = (PSHCLROOTLISTHDR)pPayloadHdr->pvData; 135 Assert(pPayloadHdr->cbData == sizeof(SHCLROOTLISTHDR)); 136 137 LogFlowFunc(("cRoots=%RU32, fRoots=0x%x\n", pSrcRootListHdr->cRoots, pSrcRootListHdr->fRoots)); 138 139 PSHCLROOTLIST pRootList = ShClTransferRootListAlloc(); 140 if (pRootList) 134 PSHCLLISTHDR pRootListHdr = (PSHCLLISTHDR)pPayloadHdr->pvData; 135 Assert(pPayloadHdr->cbData == sizeof(SHCLLISTHDR)); 136 137 LogFlowFunc(("cRoots=%RU32, fFeatures=0x%x\n", pRootListHdr->cEntries, pRootListHdr->fFeatures)); 138 139 for (uint32_t i = 0; i < pRootListHdr->cEntries; i++) 141 140 { 142 if (pSrcRootListHdr->cRoots) 143 { 144 pRootList->paEntries = 145 (PSHCLROOTLISTENTRY)RTMemAllocZ(pSrcRootListHdr->cRoots * sizeof(SHCLROOTLISTENTRY)); 146 147 if (pRootList->paEntries) 148 { 149 for (uint32_t i = 0; i < pSrcRootListHdr->cRoots; i++) 150 { 151 PSHCLCLIENTMSG pMsgEntry = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_ENTRY_READ, 152 VBOX_SHCL_CPARMS_ROOT_LIST_ENTRY_READ_REQ); 153 154 PSHCLEVENT pEvRoot; 155 rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvRoot); 156 if (RT_SUCCESS(rc)) 157 { 158 HGCMSvcSetU64(&pMsgEntry->aParms[0], 159 VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uClientID, 160 pCtx->pTransfer->State.uID, pEvRoot->idEvent)); 161 HGCMSvcSetU32(&pMsgEntry->aParms[1], 0 /* fRoots */); 162 HGCMSvcSetU32(&pMsgEntry->aParms[2], i /* uIndex */); 163 164 shClSvcClientLock(pClient); 165 shClSvcMsgAdd(pClient, pMsgEntry, true /* fAppend */); 166 shClSvcClientUnlock(pClient); 167 168 PSHCLEVENTPAYLOAD pPayloadEntry; 169 rc = ShClEventWait(pEvent, pCtx->pTransfer->uTimeoutMs, &pPayloadEntry); 170 if (RT_FAILURE(rc)) 171 break; 172 173 PSHCLROOTLISTENTRY pSrcRootListEntry = (PSHCLROOTLISTENTRY)pPayloadEntry->pvData; 174 Assert(pPayloadEntry->cbData == sizeof(SHCLROOTLISTENTRY)); 175 176 rc = ShClTransferListEntryCopy(&pRootList->paEntries[i], pSrcRootListEntry); 177 178 ShClPayloadFree(pPayloadEntry); 179 180 ShClEventRelease(pEvRoot); 181 pEvRoot = NULL; 182 } 183 else 184 rc = VERR_SHCLPB_MAX_EVENTS_REACHED; 185 186 if (RT_FAILURE(rc)) 187 break; 188 } 189 } 190 else 191 rc = VERR_NO_MEMORY; 192 } 193 141 PSHCLCLIENTMSG pMsgEntry = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_ENTRY_READ, 142 VBOX_SHCL_CPARMS_ROOT_LIST_ENTRY_READ_REQ); 143 144 PSHCLEVENT pEventRootEntry; 145 rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEventRootEntry); 194 146 if (RT_SUCCESS(rc)) 195 147 { 196 pRootList->Hdr.cRoots = pSrcRootListHdr->cRoots; 197 pRootList->Hdr.fRoots = 0; /** @todo Implement this. */ 198 199 *ppRootList = pRootList; 148 HGCMSvcSetU64(&pMsgEntry->aParms[0], 149 VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uClientID, 150 pCtx->pTransfer->State.uID, pEventRootEntry->idEvent)); 151 HGCMSvcSetU32(&pMsgEntry->aParms[1], 0 /* fFeatures */); 152 HGCMSvcSetU32(&pMsgEntry->aParms[2], i /* uIndex */); 153 154 shClSvcClientLock(pClient); 155 shClSvcMsgAdd(pClient, pMsgEntry, true /* fAppend */); 156 shClSvcClientUnlock(pClient); 157 158 PSHCLEVENTPAYLOAD pPayloadEntry; 159 rc = ShClEventWait(pEventRootEntry, pCtx->pTransfer->uTimeoutMs, &pPayloadEntry); 160 if (RT_FAILURE(rc)) 161 break; 162 163 PSHCLLISTENTRY pRootListEntry = (PSHCLLISTENTRY)pPayloadEntry->pvData; 164 Assert(pPayloadEntry->cbData == sizeof(SHCLLISTENTRY)); 165 166 rc = ShClTransferListAddEntry(&pCtx->pTransfer->lstRoots, pRootListEntry, true /* fAppend */); 167 if (RT_FAILURE(rc)) 168 ShClPayloadFree(pPayloadEntry); 169 /* else don't call ShClPayloadFree() here, as pRootList own the data now. */ 170 pPayloadEntry = NULL; 171 172 ShClEventRelease(pEventRootEntry); 173 pEventRootEntry = NULL; 200 174 } 201 175 else 202 ShClTransferRootListFree(pRootList); 203 204 ShClPayloadFree(pPayloadHdr); 176 { 177 shClSvcMsgFree(pClient, pMsgEntry); 178 rc = VERR_SHCLPB_MAX_EVENTS_REACHED; 179 } 180 181 if (RT_FAILURE(rc)) 182 break; 205 183 } 206 else 207 rc = VERR_NO_MEMORY;184 185 ShClPayloadFree(pPayloadHdr); 208 186 } 209 187 } … … 212 190 } 213 191 else 192 { 193 shClSvcMsgFree(pClient, pMsgHdr); 214 194 rc = VERR_SHCLPB_MAX_EVENTS_REACHED; 195 } 215 196 } 216 197 else … … 246 227 if (RT_SUCCESS(rc)) 247 228 { 229 shClSvcClientLock(pClient); 230 248 231 shClSvcMsgAdd(pClient, pMsg, true /* fAppend */); 249 250 232 rc = shClSvcClientWakeup(pClient); 233 234 shClSvcClientUnlock(pClient); 235 251 236 if (RT_SUCCESS(rc)) 252 237 { … … 274 259 } 275 260 else 261 { 262 shClSvcMsgFree(pClient, pMsg); 276 263 rc = VERR_SHCLPB_MAX_EVENTS_REACHED; 264 } 277 265 } 278 266 else … … 307 295 if (RT_SUCCESS(rc)) 308 296 { 297 shClSvcClientLock(pClient); 298 309 299 shClSvcMsgAdd(pClient, pMsg, true /* fAppend */); 310 311 300 rc = shClSvcClientWakeup(pClient); 301 302 shClSvcClientUnlock(pClient); 303 312 304 if (RT_SUCCESS(rc)) 313 305 { … … 322 314 } 323 315 else 316 { 317 shClSvcMsgFree(pClient, pMsg); 324 318 rc = VERR_SHCLPB_MAX_EVENTS_REACHED; 319 } 325 320 } 326 321 else … … 355 350 HGCMSvcSetU32(&pMsg->aParms[2], 0 /* fFlags */); 356 351 352 shClSvcClientLock(pClient); 353 357 354 shClSvcMsgAdd(pClient, pMsg, true /* fAppend */); 358 359 355 rc = shClSvcClientWakeup(pClient); 356 357 shClSvcClientUnlock(pClient); 358 360 359 if (RT_SUCCESS(rc)) 361 360 { … … 375 374 } 376 375 else 376 { 377 shClSvcMsgFree(pClient, pMsg); 377 378 rc = VERR_SHCLPB_MAX_EVENTS_REACHED; 379 } 378 380 } 379 381 else … … 419 421 HGCMSvcSetU32(&pMsg->aParms[2], 0 /* fInfo */); 420 422 423 shClSvcClientLock(pClient); 424 421 425 shClSvcMsgAdd(pClient, pMsg, true /* fAppend */); 422 423 426 rc = shClSvcClientWakeup(pClient); 427 428 shClSvcClientUnlock(pClient); 429 424 430 if (RT_SUCCESS(rc)) 425 431 { … … 439 445 } 440 446 else 447 { 448 shClSvcMsgFree(pClient, pMsg); 441 449 rc = VERR_SHCLPB_MAX_EVENTS_REACHED; 450 } 442 451 } 443 452 else … … 460 469 461 470 /** @copydoc SHCLTXPROVIDERIFACE::pfnObjOpen */ 462 int shClSvcTransferIfaceObjOpen(PSHCLTXPROVIDERCTX pCtx, PSHCLOBJOPENCREATEPARMS pCreateParms, 463 PSHCLOBJHANDLE phObj) 471 DECLCALLBACK(int) shClSvcTransferIfaceObjOpen(PSHCLTXPROVIDERCTX pCtx, PSHCLOBJOPENCREATEPARMS pCreateParms, PSHCLOBJHANDLE phObj) 464 472 { 465 473 LogFlowFuncEnter(); … … 485 493 pCtx->pTransfer->State.uID, pEvent->idEvent)); 486 494 HGCMSvcSetU64(&pMsg->aParms[1], 0); /* uHandle */ 487 HGCMSvcSetU32(&pMsg->aParms[2], cbPath); 488 HGCMSvcSetPv (&pMsg->aParms[3], pCreateParms->pszPath, cbPath); 489 HGCMSvcSetU32(&pMsg->aParms[4], pCreateParms->fCreate); 495 HGCMSvcSetPv (&pMsg->aParms[2], pCreateParms->pszPath, cbPath); 496 HGCMSvcSetU32(&pMsg->aParms[3], pCreateParms->fCreate); 497 498 shClSvcClientLock(pClient); 490 499 491 500 shClSvcMsgAdd(pClient, pMsg, true /* fAppend */); 492 493 501 rc = shClSvcClientWakeup(pClient); 502 503 shClSvcClientUnlock(pClient); 504 494 505 if (RT_SUCCESS(rc)) 495 506 { … … 516 527 } 517 528 else 529 { 530 shClSvcMsgFree(pClient, pMsg); 518 531 rc = VERR_SHCLPB_MAX_EVENTS_REACHED; 532 } 519 533 } 520 534 else … … 526 540 527 541 /** @copydoc SHCLTXPROVIDERIFACE::pfnObjClose */ 528 intshClSvcTransferIfaceObjClose(PSHCLTXPROVIDERCTX pCtx, SHCLOBJHANDLE hObj)542 DECLCALLBACK(int) shClSvcTransferIfaceObjClose(PSHCLTXPROVIDERCTX pCtx, SHCLOBJHANDLE hObj) 529 543 { 530 544 LogFlowFuncEnter(); … … 547 561 HGCMSvcSetU64(&pMsg->aParms[1], hObj); 548 562 563 shClSvcClientLock(pClient); 564 549 565 shClSvcMsgAdd(pClient, pMsg, true /* fAppend */); 550 551 566 rc = shClSvcClientWakeup(pClient); 567 568 shClSvcClientUnlock(pClient); 569 552 570 if (RT_SUCCESS(rc)) 553 571 { … … 572 590 } 573 591 else 592 { 593 shClSvcMsgFree(pClient, pMsg); 574 594 rc = VERR_SHCLPB_MAX_EVENTS_REACHED; 595 } 575 596 } 576 597 else … … 582 603 583 604 /** @copydoc SHCLTXPROVIDERIFACE::pfnObjRead */ 584 intshClSvcTransferIfaceObjRead(PSHCLTXPROVIDERCTX pCtx, SHCLOBJHANDLE hObj,585 void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbRead)605 DECLCALLBACK(int) shClSvcTransferIfaceObjRead(PSHCLTXPROVIDERCTX pCtx, SHCLOBJHANDLE hObj, 606 void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbRead) 586 607 { 587 608 LogFlowFuncEnter(); … … 606 627 HGCMSvcSetU32(&pMsg->aParms[3], fFlags); 607 628 629 shClSvcClientLock(pClient); 630 608 631 shClSvcMsgAdd(pClient, pMsg, true /* fAppend */); 609 610 632 rc = shClSvcClientWakeup(pClient); 633 634 shClSvcClientUnlock(pClient); 635 611 636 if (RT_SUCCESS(rc)) 612 637 { … … 634 659 } 635 660 else 661 { 662 shClSvcMsgFree(pClient, pMsg); 636 663 rc = VERR_SHCLPB_MAX_EVENTS_REACHED; 664 } 637 665 } 638 666 else … … 644 672 645 673 /** @copydoc SHCLTXPROVIDERIFACE::pfnObjWrite */ 646 intshClSvcTransferIfaceObjWrite(PSHCLTXPROVIDERCTX pCtx, SHCLOBJHANDLE hObj,647 void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbWritten)674 DECLCALLBACK(int) shClSvcTransferIfaceObjWrite(PSHCLTXPROVIDERCTX pCtx, SHCLOBJHANDLE hObj, 675 void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbWritten) 648 676 { 649 677 LogFlowFuncEnter(); … … 668 696 HGCMSvcSetU64(&pMsg->aParms[3], fFlags); 669 697 698 shClSvcClientLock(pClient); 699 670 700 shClSvcMsgAdd(pClient, pMsg, true /* fAppend */); 671 672 701 rc = shClSvcClientWakeup(pClient); 702 703 shClSvcClientUnlock(pClient); 704 673 705 if (RT_SUCCESS(rc)) 674 706 { … … 691 723 } 692 724 else 725 { 726 shClSvcMsgFree(pClient, pMsg); 693 727 rc = VERR_SHCLPB_MAX_EVENTS_REACHED; 728 } 694 729 } 695 730 else … … 883 918 */ 884 919 static int shClSvcTransferGetRootListHdr(uint32_t cParms, VBOXHGCMSVCPARM aParms[], 885 PSHCL ROOTLISTHDR pRootLstHdr)920 PSHCLLISTHDR pRootLstHdr) 886 921 { 887 922 int rc; … … 889 924 if (cParms == VBOX_SHCL_CPARMS_ROOT_LIST_HDR_WRITE) 890 925 { 891 rc = HGCMSvcGetU32(&aParms[1], &pRootLstHdr->f Roots);892 if (RT_SUCCESS(rc)) 893 rc = HGCMSvcGetU 32(&aParms[2], &pRootLstHdr->cRoots);926 rc = HGCMSvcGetU32(&aParms[1], &pRootLstHdr->fFeatures); 927 if (RT_SUCCESS(rc)) 928 rc = HGCMSvcGetU64(&aParms[2], &pRootLstHdr->cEntries); 894 929 } 895 930 else … … 909 944 */ 910 945 static int shClSvcTransferGetRootListEntry(uint32_t cParms, VBOXHGCMSVCPARM aParms[], 911 PSHCL ROOTLISTENTRY pListEntry)946 PSHCLLISTENTRY pListEntry) 912 947 { 913 948 int rc; … … 1047 1082 rc = HGCMSvcGetU32(&aParms[3], &pListHdr->fFeatures); 1048 1083 if (RT_SUCCESS(rc)) 1049 rc = HGCMSvcGetU64(&aParms[4], &pListHdr->c TotalObjects);1084 rc = HGCMSvcGetU64(&aParms[4], &pListHdr->cEntries); 1050 1085 if (RT_SUCCESS(rc)) 1051 1086 rc = HGCMSvcGetU64(&aParms[5], &pListHdr->cbTotalSize); … … 1082 1117 1083 1118 HGCMSvcSetU32(&aParms[3], pListHdr->fFeatures); 1084 HGCMSvcSetU64(&aParms[4], pListHdr->c TotalObjects);1119 HGCMSvcSetU64(&aParms[4], pListHdr->cEntries); 1085 1120 HGCMSvcSetU64(&aParms[5], pListHdr->cbTotalSize); 1086 1121 … … 1190 1225 if (RT_SUCCESS(rc)) 1191 1226 { 1192 uint32_t cb Data;1193 rc = HGCMSvcGetU32(&aParms[2], &cb Data);1227 uint32_t cbToRead; 1228 rc = HGCMSvcGetU32(&aParms[2], &cbToRead); 1194 1229 if (RT_SUCCESS(rc)) 1195 1230 { 1196 1231 rc = HGCMSvcGetPv(&aParms[3], &pDataChunk->pvData, &pDataChunk->cbData); 1197 AssertReturn(cbData == pDataChunk->cbData, VERR_INVALID_PARAMETER); 1198 1199 /** @todo Implement checksum handling. */ 1200 } 1232 if (RT_SUCCESS(rc)) 1233 rc = cbToRead == pDataChunk->cbData ? VINF_SUCCESS : VERR_INVALID_PARAMETER; 1234 } 1235 1236 /** @todo Implement checksum handling. */ 1201 1237 } 1202 1238 } … … 1241 1277 { 1242 1278 case VBOX_SHCL_REPLYMSGTYPE_TRANSFER_STATUS: 1279 { 1280 LogRel(("Shared Clipboard: Guest reported status %s for transfer %RU32\n", 1281 ShClTransferStatusToStr(pReply->u.TransferStatus.uStatus), pTransfer->State.uID)); 1282 1283 switch (pReply->u.TransferStatus.uStatus) 1284 { 1285 case SHCLTRANSFERSTATUS_INITIALIZED: /* Initialized -> Started */ 1286 rc = shClSvcTransferStart(pClient, pTransfer); 1287 break; 1288 1289 case SHCLTRANSFERSTATUS_STARTED: 1290 break; 1291 1292 case SHCLTRANSFERSTATUS_ERROR: 1293 { 1294 LogRel(("Shared Clipboard: Guest reported error %Rrc for transfer %RU32\n", 1295 pReply->rc, pTransfer->State.uID)); 1296 1297 rc = shClSvcTransferStop(pClient, pTransfer, false /* fWaitForGuest */); 1298 break; 1299 } 1300 1301 default: 1302 rc = shClSvcTransferStop(pClient, pTransfer, true /* fWaitForGuest */); 1303 break; 1304 } 1305 1243 1306 RT_FALL_THROUGH(); 1307 } 1244 1308 case VBOX_SHCL_REPLYMSGTYPE_LIST_OPEN: 1245 1309 RT_FALL_THROUGH(); … … 1333 1397 PSHCLTRANSFER pTransfer = NULL; 1334 1398 1399 shClSvcClientLock(pClient); 1400 ASSERT_GUEST_MSG_RETURN(pClient->Pending.uType == 0, ("Already pending! (idClient=%RU32)\n", 1401 pClient->State.uClientID), VERR_RESOURCE_BUSY); 1402 shClSvcClientUnlock(pClient); 1403 1335 1404 switch (u32Function) 1336 1405 { … … 1347 1416 break; 1348 1417 1418 ASSERT_GUEST_RETURN(aParms[0].type == VBOX_HGCM_SVC_PARM_64BIT, VERR_WRONG_PARAMETER_TYPE); 1419 1349 1420 rc = HGCMSvcGetU64(&aParms[0], &uCID); 1350 1421 if (RT_FAILURE(rc)) … … 1381 1452 break; 1382 1453 1454 ASSERT_GUEST_RETURN(aParms[1].type == VBOX_HGCM_SVC_PARM_32BIT, VERR_WRONG_PARAMETER_TYPE); /* Features */ 1455 ASSERT_GUEST_RETURN(aParms[2].type == VBOX_HGCM_SVC_PARM_64BIT, VERR_WRONG_PARAMETER_TYPE); /* # Entries */ 1456 1383 1457 if ( ShClTransferGetSource(pTransfer) == SHCLSOURCE_LOCAL 1384 1458 && ShClTransferGetDir(pTransfer) == SHCLTRANSFERDIR_TO_REMOTE) … … 1388 1462 } 1389 1463 else 1390 {1391 rc = VERR_INVALID_PARAMETER;1392 1464 break; 1393 } 1394 1395 SHCLROOTLISTHDR rootListHdr; 1465 1466 SHCLLISTHDR rootListHdr; 1396 1467 RT_ZERO(rootListHdr); 1397 1468 1398 rootListHdr.cRoots = ShClTransferRootsCount(pTransfer); 1469 rootListHdr.cEntries = ShClTransferRootsCount(pTransfer); 1470 /** @todo BUGBUG What about the features? */ 1399 1471 1400 1472 HGCMSvcSetU64(&aParms[0], 0 /* Context ID */); 1401 HGCMSvcSetU32(&aParms[1], rootListHdr.f Roots);1402 HGCMSvcSetU 32(&aParms[2], rootListHdr.cRoots);1473 HGCMSvcSetU32(&aParms[1], rootListHdr.fFeatures); 1474 HGCMSvcSetU64(&aParms[2], rootListHdr.cEntries); 1403 1475 1404 1476 rc = VINF_SUCCESS; … … 1408 1480 case VBOX_SHCL_GUEST_FN_ROOT_LIST_HDR_WRITE: 1409 1481 { 1410 SHCL ROOTLISTHDR lstHdr;1482 SHCLLISTHDR lstHdr; 1411 1483 rc = shClSvcTransferGetRootListHdr(cParms, aParms, &lstHdr); 1412 1484 if (RT_SUCCESS(rc)) 1413 1485 { 1414 void *pvData = ShClTransfer RootListHdrDup(&lstHdr);1415 uint32_t cbData = sizeof(SHCL ROOTLISTHDR);1486 void *pvData = ShClTransferListHdrDup(&lstHdr); 1487 uint32_t cbData = sizeof(SHCLLISTHDR); 1416 1488 1417 1489 const PSHCLEVENT pEvent = ShClEventSourceGetFromId(&pClient->EventSrc, VBOX_SHCL_CONTEXTID_GET_EVENT(uCID)); … … 1438 1510 break; 1439 1511 1440 /* aParms[1] contains fInfo flags, currently unused. */ 1441 uint32_t uIndex; 1442 rc = HGCMSvcGetU32(&aParms[2], &uIndex); 1443 if (RT_SUCCESS(rc)) 1444 { 1445 SHCLROOTLISTENTRY rootListEntry; 1446 rc = ShClTransferRootsEntry(pTransfer, uIndex, &rootListEntry); 1447 if (RT_SUCCESS(rc)) 1448 { 1449 HGCMSvcSetPv (&aParms[3], rootListEntry.pszName, rootListEntry.cbName); 1450 HGCMSvcSetU32(&aParms[4], rootListEntry.cbInfo); 1451 HGCMSvcSetPv (&aParms[5], rootListEntry.pvInfo, rootListEntry.cbInfo); 1452 } 1453 } 1512 ASSERT_GUEST_RETURN(aParms[1].type == VBOX_HGCM_SVC_PARM_32BIT, VERR_WRONG_PARAMETER_TYPE); /* Info flags */ 1513 ASSERT_GUEST_RETURN(aParms[2].type == VBOX_HGCM_SVC_PARM_64BIT, VERR_WRONG_PARAMETER_TYPE); /* Entry index # */ 1514 ASSERT_GUEST_RETURN(aParms[3].type == VBOX_HGCM_SVC_PARM_PTR, VERR_WRONG_PARAMETER_TYPE); /* Entry name */ 1515 ASSERT_GUEST_RETURN(aParms[4].type == VBOX_HGCM_SVC_PARM_32BIT, VERR_WRONG_PARAMETER_TYPE); /* Info size */ 1516 ASSERT_GUEST_RETURN(aParms[5].type == VBOX_HGCM_SVC_PARM_PTR, VERR_WRONG_PARAMETER_TYPE); /* Info data */ 1517 1518 uint32_t fInfo; 1519 rc = HGCMSvcGetU32(&aParms[1], &fInfo); 1520 AssertRCBreak(rc); 1521 1522 ASSERT_GUEST_RETURN(fInfo & VBOX_SHCL_INFO_F_FSOBJINFO, VERR_WRONG_PARAMETER_TYPE); /* Validate info flags. */ 1523 1524 uint64_t uIdx; 1525 rc = HGCMSvcGetU64(&aParms[2], &uIdx); 1526 AssertRCBreak(rc); 1527 1528 PCSHCLLISTENTRY pEntry = ShClTransferRootsEntryGet(pTransfer, uIdx); 1529 if (pEntry) 1530 { 1531 /* Entry name */ 1532 void *pvDst = aParms[3].u.pointer.addr; 1533 size_t cbDst = aParms[3].u.pointer.size; 1534 memcpy(pvDst, pEntry->pszName, RT_MIN(pEntry->cbName, cbDst)); 1535 1536 /* Info size */ 1537 HGCMSvcSetU32(&aParms[4], pEntry->cbInfo); 1538 1539 /* Info data */ 1540 pvDst = aParms[5].u.pointer.addr; 1541 cbDst = aParms[5].u.pointer.size; 1542 memcpy(pvDst, pEntry->pvInfo, RT_MIN(pEntry->cbInfo, cbDst)); 1543 } 1544 else 1545 rc = VERR_NOT_FOUND; 1546 1454 1547 break; 1455 1548 } … … 1457 1550 case VBOX_SHCL_GUEST_FN_ROOT_LIST_ENTRY_WRITE: 1458 1551 { 1459 SHCL ROOTLISTENTRY lstEntry;1552 SHCLLISTENTRY lstEntry; 1460 1553 rc = shClSvcTransferGetRootListEntry(cParms, aParms, &lstEntry); 1461 1554 if (RT_SUCCESS(rc)) 1462 1555 { 1463 void *pvData = ShClTransfer RootListEntryDup(&lstEntry);1464 uint32_t cbData = sizeof(SHCL ROOTLISTENTRY);1556 void *pvData = ShClTransferListEntryDup(&lstEntry); 1557 uint32_t cbData = sizeof(SHCLLISTENTRY); 1465 1558 1466 1559 const PSHCLEVENT pEvent = ShClEventSourceGetFromId(&pClient->EventSrc, VBOX_SHCL_CONTEXTID_GET_EVENT(uCID)); … … 1658 1751 break; 1659 1752 1753 ASSERT_GUEST_RETURN(aParms[1].type == VBOX_HGCM_SVC_PARM_64BIT, VERR_WRONG_PARAMETER_TYPE); /* Object handle */ 1754 ASSERT_GUEST_RETURN(aParms[2].type == VBOX_HGCM_SVC_PARM_32BIT, VERR_WRONG_PARAMETER_TYPE); /* Bytes to read */ 1755 ASSERT_GUEST_RETURN(aParms[3].type == VBOX_HGCM_SVC_PARM_PTR, VERR_WRONG_PARAMETER_TYPE); /* Data buffer */ 1756 ASSERT_GUEST_RETURN(aParms[4].type == VBOX_HGCM_SVC_PARM_32BIT, VERR_WRONG_PARAMETER_TYPE); /* Checksum data size */ 1757 ASSERT_GUEST_RETURN(aParms[5].type == VBOX_HGCM_SVC_PARM_PTR, VERR_WRONG_PARAMETER_TYPE); /* Checksum data buffer*/ 1758 1660 1759 SHCLOBJHANDLE hObj; 1661 1760 rc = HGCMSvcGetU64(&aParms[1], &hObj); /* Get object handle. */ 1761 AssertRCBreak(rc); 1662 1762 1663 1763 uint32_t cbToRead = 0; 1664 if (RT_SUCCESS(rc))1665 rc = HGCMSvcGetU32(&aParms[2], &cbToRead);1764 rc = HGCMSvcGetU32(&aParms[2], &cbToRead); 1765 AssertRCBreak(rc); 1666 1766 1667 1767 void *pvBuf = NULL; 1668 1768 uint32_t cbBuf = 0; 1669 if (RT_SUCCESS(rc))1670 rc = HGCMSvcGetPv(&aParms[3], &pvBuf, &cbBuf);1769 rc = HGCMSvcGetPv(&aParms[3], &pvBuf, &cbBuf); 1770 AssertRCBreak(rc); 1671 1771 1672 1772 LogFlowFunc(("hObj=%RU64, cbBuf=%RU32, cbToRead=%RU32, rc=%Rrc\n", hObj, cbBuf, cbToRead, rc)); … … 1688 1788 if (RT_SUCCESS(rc)) 1689 1789 { 1690 HGCMSvcSetU32(&aParms[ 3], cbRead);1790 HGCMSvcSetU32(&aParms[2], cbRead); 1691 1791 1692 1792 /** @todo Implement checksum support. */ … … 1699 1799 { 1700 1800 SHCLOBJDATACHUNK dataChunk; 1801 1701 1802 rc = shClSvcTransferGetObjDataChunk(cParms, aParms, &dataChunk); 1702 1803 if (RT_SUCCESS(rc)) … … 1751 1852 switch (u32Function) 1752 1853 { 1753 case VBOX_SHCL_HOST_FN_CANCEL: /** @todo Implement this. */1754 break; 1755 1756 case VBOX_SHCL_HOST_FN_ERROR: /** @todo Implement this. */1854 case VBOX_SHCL_HOST_FN_CANCEL: /** @todo BUGBUG Implement this. */ 1855 break; 1856 1857 case VBOX_SHCL_HOST_FN_ERROR: /** @todo BUGBUG Implement this. */ 1757 1858 break; 1758 1859 … … 1793 1894 * @param ppEvent Where to return the wait event on success. Optional. 1794 1895 * Must be released by the caller with ShClEventRelease(). 1896 * 1897 * @note Caller must enter critical section. 1795 1898 */ 1796 1899 int shClSvcTransferSendStatus(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer, SHCLTRANSFERSTATUS uStatus, … … 1838 1941 rc = VERR_SHCLPB_MAX_EVENTS_REACHED; 1839 1942 1943 if (RT_FAILURE(rc)) 1944 LogRel(("Shared Clipboard: Reporting status %s (%Rrc) for transfer %RU32 to guest failed with %Rrc\n", 1945 ShClTransferStatusToStr(uStatus), rcTransfer, pTransfer->State.uID, rc)); 1946 1840 1947 LogFlowFuncLeaveRC(rc); 1841 1948 return rc; … … 1843 1950 1844 1951 /** 1845 * Starts a new transfer, waiting for acknowledgement by the guest side. 1952 * Cleans up (unregisters and destroys) all transfers not in the 'started' state (anymore). 1953 * 1954 * @param pClient Client to clean up transfers for. 1955 * 1956 * @note Caller needs to take the critical section. 1957 */ 1958 void shClSvcTransferCleanupAllUnused(PSHCLCLIENT pClient) 1959 { 1960 LogFlowFuncEnter(); 1961 1962 PSHCLTRANSFERCTX pTxCtx = &pClient->Transfers.Ctx; 1963 1964 /* Remove all transfers which are not in a running state (e.g. only announced). */ 1965 PSHCLTRANSFER pTransfer, pTransferNext; 1966 RTListForEachSafe(&pTxCtx->List, pTransfer, pTransferNext, SHCLTRANSFER, Node) 1967 { 1968 if (ShClTransferGetStatus(pTransfer) != SHCLTRANSFERSTATUS_STARTED) 1969 { 1970 /* Let the guest know. */ 1971 int rc2 = shClSvcTransferSendStatus(pClient, pTransfer, 1972 SHCLTRANSFERSTATUS_UNINITIALIZED, VINF_SUCCESS, NULL /* ppEvent */); 1973 AssertRC(rc2); 1974 1975 ShClTransferCtxTransferUnregister(pTxCtx, pTransfer->State.uID); 1976 1977 ShClTransferDestroy(pTransfer); 1978 1979 RTMemFree(pTransfer); 1980 pTransfer = NULL; 1981 } 1982 } 1983 } 1984 1985 /** 1986 * Initializes a new transfer and sends the status to the guest. 1846 1987 * 1847 1988 * @note Assumes that the client's critical section is taken. … … 1853 1994 * @param ppTransfer Where to return the created transfer on success. Optional. 1854 1995 */ 1855 int shClSvcTransferStart(PSHCLCLIENT pClient, 1856 SHCLTRANSFERDIR enmDir, SHCLSOURCE enmSource, 1857 PSHCLTRANSFER *ppTransfer) 1858 { 1996 int shClSvcTransferInit(PSHCLCLIENT pClient, 1997 SHCLTRANSFERDIR enmDir, SHCLSOURCE enmSource, 1998 PSHCLTRANSFER *ppTransfer) 1999 { 2000 Assert(RTCritSectIsOwner(&pClient->CritSect)); 2001 1859 2002 AssertPtrReturn(pClient, VERR_INVALID_POINTER); 1860 2003 /* ppTransfer is optional. */ … … 1862 2005 LogFlowFuncEnter(); 1863 2006 2007 shClSvcTransferCleanupAllUnused(pClient); 2008 1864 2009 PSHCLTRANSFERCTX pTxCtx = &pClient->Transfers.Ctx; 1865 2010 1866 ShClTransferCtxCleanup(pTxCtx);1867 1868 2011 int rc; 1869 2012 1870 2013 if (!ShClTransferCtxTransfersMaximumReached(pTxCtx)) 1871 2014 { 1872 LogRel2(("Shared Clipboard: Starting %s transfer ...\n", enmDir == SHCLTRANSFERDIR_FROM_REMOTE ? "read" : "write")); 2015 LogRel2(("Shared Clipboard: Initializing %s transfer ...\n", 2016 enmDir == SHCLTRANSFERDIR_FROM_REMOTE ? "guest -> host" : "host -> guest")); 1873 2017 1874 2018 PSHCLTRANSFER pTransfer; … … 1876 2020 if (RT_SUCCESS(rc)) 1877 2021 { 1878 SHCLTXPROVIDER CREATIONCTX creationCtx;1879 RT_ZERO( creationCtx);2022 SHCLTXPROVIDER Provider; 2023 RT_ZERO(Provider); 1880 2024 1881 2025 /* Assign local provider first and overwrite interface methods below if needed. */ 1882 VBClTransfer QueryIfaceLocal(&creationCtx.Interface);2026 VBClTransferProviderLocalQueryInterface(&Provider); 1883 2027 1884 2028 if (enmDir == SHCLTRANSFERDIR_FROM_REMOTE) /* Guest -> Host. */ 1885 2029 { 1886 creationCtx.Interface.pfnRootsGet = shClSvcTransferIfaceRootsGet;1887 1888 creationCtx.Interface.pfnListOpen = shClSvcTransferIfaceListOpen;1889 creationCtx.Interface.pfnListClose = shClSvcTransferIfaceListClose;1890 creationCtx.Interface.pfnListHdrRead = shClSvcTransferIfaceListHdrRead;1891 creationCtx.Interface.pfnListEntryRead = shClSvcTransferIfaceListEntryRead;1892 1893 creationCtx.Interface.pfnObjOpen = shClSvcTransferIfaceObjOpen;1894 creationCtx.Interface.pfnObjClose = shClSvcTransferIfaceObjClose;1895 creationCtx.Interface.pfnObjRead = shClSvcTransferIfaceObjRead;2030 Provider.Interface.pfnRootListRead = shClSvcTransferIfaceRootListRead; 2031 2032 Provider.Interface.pfnListOpen = shClSvcTransferIfaceListOpen; 2033 Provider.Interface.pfnListClose = shClSvcTransferIfaceListClose; 2034 Provider.Interface.pfnListHdrRead = shClSvcTransferIfaceListHdrRead; 2035 Provider.Interface.pfnListEntryRead = shClSvcTransferIfaceListEntryRead; 2036 2037 Provider.Interface.pfnObjOpen = shClSvcTransferIfaceObjOpen; 2038 Provider.Interface.pfnObjClose = shClSvcTransferIfaceObjClose; 2039 Provider.Interface.pfnObjRead = shClSvcTransferIfaceObjRead; 1896 2040 } 1897 2041 else if (enmDir == SHCLTRANSFERDIR_TO_REMOTE) /* Host -> Guest. */ 1898 2042 { 1899 creationCtx.Interface.pfnListHdrWrite = shClSvcTransferIfaceListHdrWrite;1900 creationCtx.Interface.pfnListEntryWrite = shClSvcTransferIfaceListEntryWrite;1901 creationCtx.Interface.pfnObjWrite = shClSvcTransferIfaceObjWrite;2043 Provider.Interface.pfnListHdrWrite = shClSvcTransferIfaceListHdrWrite; 2044 Provider.Interface.pfnListEntryWrite = shClSvcTransferIfaceListEntryWrite; 2045 Provider.Interface.pfnObjWrite = shClSvcTransferIfaceObjWrite; 1902 2046 } 1903 2047 else 1904 2048 AssertFailed(); 1905 2049 1906 creationCtx.enmSource = pClient->State.enmSource; 1907 creationCtx.pvUser = pClient; 1908 1909 rc = ShClTransferSetProviderIface(pTransfer, &creationCtx); 1910 if (RT_SUCCESS(rc)) 1911 { 2050 Provider.enmSource = pClient->State.enmSource; 2051 Provider.pvUser = pClient; 2052 2053 rc = ShClTransferSetProvider(pTransfer, &Provider); 2054 if (RT_SUCCESS(rc)) 2055 { 2056 ShClTransferSetCallbacks(pTransfer, &pClient->Transfers.Callbacks); 2057 1912 2058 rc = ShClTransferInit(pTransfer, enmDir, enmSource); 1913 2059 if (RT_SUCCESS(rc)) … … 1920 2066 if (RT_SUCCESS(rc)) 1921 2067 { 1922 if (RT_SUCCESS(rc)) 1923 rc = ShClTransferStart(pTransfer); 1924 1925 if (RT_SUCCESS(rc)) 1926 { 1927 PSHCLEVENT pEvent; 1928 rc = shClSvcTransferSendStatus(pClient, pTransfer, 1929 SHCLTRANSFERSTATUS_INITIALIZED, VINF_SUCCESS, &pEvent); 1930 if (RT_SUCCESS(rc)) 1931 { 1932 LogRel2(("Shared Clipboard: Waiting for start of transfer %RU32 on guest ...\n", 1933 pTransfer->State.uID)); 1934 1935 /* Leave the client's critical section before waiting. */ 1936 RTCritSectLeave(&pClient->CritSect); 1937 1938 PSHCLEVENTPAYLOAD pPayload = NULL; 1939 rc = ShClEventWait(pEvent, pTransfer->uTimeoutMs, &pPayload); 1940 if (RT_SUCCESS(rc)) 1941 { 1942 Assert(pPayload->cbData == sizeof(SHCLREPLY)); 1943 PSHCLREPLY pReply = (PSHCLREPLY)pPayload->pvData; 1944 AssertPtr(pReply); 1945 1946 Assert(pReply->uType == VBOX_SHCL_REPLYMSGTYPE_TRANSFER_STATUS); 1947 1948 if (pReply->u.TransferStatus.uStatus == SHCLTRANSFERSTATUS_STARTED) 1949 { 1950 LogRel2(("Shared Clipboard: Started transfer %RU32 on guest\n", pTransfer->State.uID)); 1951 } 1952 else 1953 LogRel(("Shared Clipboard: Guest reported status %s (error %Rrc) while starting transfer %RU32\n", 1954 ShClTransferStatusToStr(pReply->u.TransferStatus.uStatus), 1955 pReply->rc, pTransfer->State.uID)); 1956 1957 rc = pReply->rc; /* Set guest rc. */ 1958 } 1959 else 1960 { 1961 if (rc == VERR_NOT_SUPPORTED) 1962 LogRelMax(3, ("Shared Clipboard: File transfers are not supported by the installed Guest Additions.\n")); 1963 else 1964 LogRel(("Shared Clipboard: Unable to start transfer %RU32 on guest, rc=%Rrc\n", 1965 pTransfer->State.uID, rc)); 1966 } 1967 1968 ShClPayloadFree(pPayload); 1969 ShClEventRelease(pEvent); 1970 1971 /* Re-enter the client's critical section again. */ 1972 RTCritSectEnter(&pClient->CritSect); 1973 } 1974 } 2068 /* Tell the guest that we've initialized the transfer locally. */ 2069 rc = shClSvcTransferSendStatus(pClient, pTransfer, 2070 SHCLTRANSFERSTATUS_INITIALIZED, VINF_SUCCESS, NULL /* ppEvent */); 1975 2071 } 1976 2072 } … … 2007 2103 2008 2104 /** 2009 * St ops (and destroys)a transfer, communicating the status to the guest side.2105 * Starts a transfer, communicating the status to the guest side. 2010 2106 * 2011 2107 * @returns VBox status code. … … 2013 2109 * @param pTransfer Transfer to stop. 2014 2110 */ 2015 int shClSvcTransferStop(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer) 2016 { 2111 int shClSvcTransferStart(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer) 2112 { 2113 LogRel2(("Shared Clipboard: Starting transfer %RU32 ...\n", pTransfer->State.uID)); 2114 2115 shClSvcClientLock(pClient); 2116 2117 int rc = ShClTransferStart(pTransfer); 2118 2119 /* Let the guest know in any case 2120 * (so that it can tear down the transfer on error as well). */ 2121 int rc2 = shClSvcTransferSendStatus(pClient, pTransfer, 2122 RT_SUCCESS(rc) ? SHCLTRANSFERSTATUS_STARTED : SHCLTRANSFERSTATUS_ERROR, rc, NULL /* ppEvent */); 2123 if (RT_SUCCESS(rc)) 2124 rc = rc2; 2125 2126 shClSvcClientUnlock(pClient); 2127 return rc; 2128 } 2129 2130 /** 2131 * Stops (and destroys) a transfer, communicating the status to the guest side. 2132 * 2133 * @returns VBox status code. 2134 * @param pClient Client that owns the transfer. 2135 * @param pTransfer Transfer to stop. The pointer will be invalid on success. 2136 * @param fWaitForGuest Set to \c true to wait for acknowledgement from guest, or \c false to skip waiting. 2137 */ 2138 int shClSvcTransferStop(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer, bool fWaitForGuest) 2139 { 2140 LogRel2(("Shared Clipboard: Stopping transfer %RU32 ...\n", pTransfer->State.uID)); 2141 2142 shClSvcClientLock(pClient); 2143 2017 2144 PSHCLEVENT pEvent; 2018 2145 int rc = shClSvcTransferSendStatus(pClient, pTransfer, 2019 2146 SHCLTRANSFERSTATUS_STOPPED, VINF_SUCCESS, &pEvent); 2020 if (RT_SUCCESS(rc)) 2147 if ( RT_SUCCESS(rc) 2148 && fWaitForGuest) 2021 2149 { 2022 2150 LogRel2(("Shared Clipboard: Waiting for stop of transfer %RU32 on guest ...\n", pTransfer->State.uID)); 2023 2151 2152 shClSvcClientUnlock(pClient); 2153 2024 2154 rc = ShClEventWait(pEvent, pTransfer->uTimeoutMs, NULL /* ppPayload */); 2025 2155 if (RT_SUCCESS(rc)) … … 2027 2157 2028 2158 ShClEventRelease(pEvent); 2159 2160 shClSvcClientLock(pClient); 2029 2161 } 2030 2162 … … 2043 2175 } 2044 2176 2177 if (RT_SUCCESS(rc)) 2178 rc = rc2; 2179 2180 if (RT_FAILURE(rc)) 2181 LogRel(("Shared Clipboard: Stopping transfer %RU32 failed with rc=%Rrc\n", 2182 pTransfer->State.uID, rc)); 2183 2184 shClSvcClientUnlock(pClient); 2185 2045 2186 LogFlowFuncLeaveRC(rc); 2046 2187 return rc; -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-win.cpp
r99967 r100204 68 68 { 69 69 /** Handle for window message handling thread. */ 70 RTTHREAD hThread;70 RTTHREAD hThread; 71 71 /** Structure for keeping and communicating with service client. */ 72 PSHCLCLIENT pClient;72 PSHCLCLIENT pClient; 73 73 /** Windows-specific context data. */ 74 SHCLWINCTX Win;74 SHCLWINCTX Win; 75 75 }; 76 76 … … 93 93 * (specified in @a pcbActualDst output parameter). 94 94 * @param u32Format VBox clipboard format (VBOX_SHCL_FMT_XXX) of copied data. 95 * VBOX_SHCL_FMT_NONE returns 0 data. 95 96 * @param pvSrc Pointer to host clipboard data. 96 97 * @param cbSrc Size (in bytes) of actual clipboard data to copy. … … 102 103 * function returns VINF_BUFFER_OVERFLOW. 103 104 */ 104 static int vboxClipboardSvcWinDataGet( uint32_tu32Format, const void *pvSrc, uint32_t cbSrc,105 static int vboxClipboardSvcWinDataGet(SHCLFORMAT u32Format, const void *pvSrc, uint32_t cbSrc, 105 106 void *pvDst, uint32_t cbDst, uint32_t *pcbActualDst) 106 107 { 107 AssertPtrReturn(pvSrc, VERR_INVALID_POINTER);108 AssertReturn (cbSrc, VERR_INVALID_PARAMETER);109 AssertPtrReturn(pvDst, VERR_INVALID_POINTER);110 AssertReturn (cbDst, VERR_INVALID_PARAMETER);111 108 AssertPtrReturn(pcbActualDst, VERR_INVALID_POINTER); 109 if (u32Format == VBOX_SHCL_FMT_NONE) 110 { 111 *pcbActualDst = 0; 112 return VINF_SUCCESS; 113 } 114 115 AssertPtrReturn(pvSrc, VERR_INVALID_POINTER); 116 AssertReturn (cbSrc, VERR_INVALID_PARAMETER); 117 AssertPtrReturn(pvDst, VERR_INVALID_POINTER); 118 AssertReturn (cbDst, VERR_INVALID_PARAMETER); 112 119 113 120 LogFlowFunc(("cbSrc = %d, cbDst = %d\n", cbSrc, cbDst)); … … 152 159 } 153 160 154 static int vboxClipboardSvcWinDataRead(PSHCLCONTEXT pCtx, UINT uFormat, void **ppvData, uint32_t *pcbData) 155 { 156 SHCLFORMAT fFormat = SharedClipboardWinClipboardFormatToVBox(uFormat); 157 LogFlowFunc(("uFormat=%u -> uFmt=0x%x\n", uFormat, fFormat)); 158 159 if (fFormat == VBOX_SHCL_FMT_NONE) 160 { 161 LogRel2(("Shared Clipboard: Windows format %u not supported, ignoring\n", uFormat)); 162 return VERR_NOT_SUPPORTED; 163 } 161 /** 162 * Worker for a reading clipboard from the guest. 163 */ 164 static int vboxClipboardSvcWinReadDataFromGuestWorker(PSHCLCONTEXT pCtx, SHCLFORMAT uFmt, void **ppvData, uint32_t *pcbData) 165 { 166 LogFlowFunc(("uFmt=%#x\n", uFmt)); 167 168 int rc; 164 169 165 170 PSHCLEVENT pEvent; 166 int rc = ShClSvcGuestDataRequest(pCtx->pClient, fFormat, &pEvent);171 rc = ShClSvcReadDataFromGuestAsync(pCtx->pClient, uFmt, &pEvent); 167 172 if (RT_SUCCESS(rc)) 168 173 { … … 171 176 if (RT_SUCCESS(rc)) 172 177 { 173 *ppvData = pPayload ? pPayload->pvData : NULL; 174 *pcbData = pPayload ? pPayload->cbData : 0; 178 if (ppvData) 179 *ppvData = pPayload ? pPayload->pvData : NULL; 180 if (pcbData) 181 *pcbData = pPayload ? pPayload->cbData : 0; 175 182 } 176 183 … … 183 190 LogFlowFuncLeaveRC(rc); 184 191 return rc; 192 } 193 194 static int vboxClipboardSvcWinReadDataFromGuest(PSHCLCONTEXT pCtx, UINT uWinFormat, void **ppvData, uint32_t *pcbData) 195 { 196 SHCLFORMAT uVBoxFmt = SharedClipboardWinClipboardFormatToVBox(uWinFormat); 197 if (uVBoxFmt == VBOX_SHCL_FMT_NONE) 198 { 199 LogRel2(("Shared Clipboard: Windows format %u not supported, ignoring\n", uWinFormat)); 200 return VERR_NOT_SUPPORTED; 201 } 202 203 int rc = vboxClipboardSvcWinReadDataFromGuestWorker(pCtx, uVBoxFmt, ppvData, pcbData); 204 205 LogFlowFuncLeaveRC(rc); 206 return rc; 207 } 208 209 /** 210 * @copydoc SHCLCALLBACKS::pfnOnRequestDataFromSource 211 * 212 * Called from the IDataObject implementation to request data from the guest. 213 * 214 * @thread Windows event thread. 215 */ 216 static DECLCALLBACK(int) vboxClipboardSvcWinRequestDataFromSourceCallback(PSHCLCONTEXT pCtx, 217 SHCLFORMAT uFmt, void **ppv, uint32_t *pcb, void *pvUser) 218 { 219 RT_NOREF(pvUser); 220 221 LogFlowFuncEnter(); 222 223 int rc = vboxClipboardSvcWinReadDataFromGuestWorker(pCtx, uFmt, ppv, pcb); 224 225 LogFlowFuncLeaveRC(rc); 226 227 return rc; 228 } 229 230 /** 231 * @copydoc SHCLTRANSFERCALLBACKTABLE::pfnOnStart 232 * 233 * Called on transfer start to notify the "in-flight" IDataObject about a started transfer. 234 * 235 * @thread Service main thread. 236 */ 237 static DECLCALLBACK(void) vboxClipboardSvcWinTransferStartedCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx) 238 { 239 PSHCLCONTEXT pCtx = (PSHCLCONTEXT)pCbCtx->pvUser; 240 AssertPtr(pCtx); 241 242 PSHCLTRANSFER pTransfer = pCbCtx->pTransfer; 243 AssertPtr(pTransfer); 244 245 const SHCLTRANSFERDIR enmDir = ShClTransferGetDir(pTransfer); 246 247 int rc = VINF_SUCCESS; 248 249 LogFlowFunc(("pCtx=%p, idTransfer=%RU32, enmDir=%RU32\n", pCtx, ShClTransferGetID(pTransfer), enmDir)); 250 251 /* The host wants to transfer data from the guest. */ 252 if (enmDir == SHCLTRANSFERDIR_FROM_REMOTE) 253 { 254 rc = RTCritSectEnter(&pCtx->Win.CritSect); 255 if (RT_SUCCESS(rc)) 256 { 257 SharedClipboardWinDataObject *pObj = pCtx->Win.pDataObjInFlight; 258 AssertPtrReturnVoid(pObj); 259 rc = pObj->SetAndStartTransfer(pTransfer); 260 261 pCtx->Win.pDataObjInFlight = NULL; /* Hand off to Windows. */ 262 263 int rc2 = RTCritSectLeave(&pCtx->Win.CritSect); 264 AssertRC(rc2); 265 } 266 } 267 268 if (RT_FAILURE(rc)) 269 LogRel(("Shared Clipboard: Starting transfer failed, rc=%Rrc\n", rc)); 270 271 LogFlowFunc(("LEAVE: idTransfer=%RU32, rc=%Rrc\n", ShClTransferGetID(pTransfer), rc)); 185 272 } 186 273 … … 295 382 void *pvData = NULL; 296 383 uint32_t cbData = 0; 297 int rc = vboxClipboardSvcWin DataRead(pCtx, uFormat, &pvData, &cbData);384 int rc = vboxClipboardSvcWinReadDataFromGuest(pCtx, uFormat, &pvData, &cbData); 298 385 if ( RT_SUCCESS(rc) 299 386 && pvData … … 343 430 } 344 431 345 case SHCL_WIN_WM_REPORT_FORMATS: 432 case SHCL_WIN_WM_REPORT_FORMATS: /* Guest reported clipboard formats. */ 346 433 { 347 434 /* Announce available formats. Do not insert data -- will be inserted in WM_RENDERFORMAT (or via IDataObject). */ … … 349 436 LogFunc(("SHCL_WIN_WM_REPORT_FORMATS: fFormats=%#xn", fFormats)); 350 437 438 int rc = SharedClipboardWinClearAndAnnounceFormats(pWinCtx, fFormats, hWnd); 351 439 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 352 if (fFormats & VBOX_SHCL_FMT_URI_LIST) 353 { 354 PSHCLTRANSFER pTransfer; 355 int rc = shClSvcTransferStart(pCtx->pClient, 356 SHCLTRANSFERDIR_FROM_REMOTE, SHCLSOURCE_REMOTE, 357 &pTransfer); 358 if (RT_SUCCESS(rc)) 359 { 360 /* Create the IDataObject implementation the host OS needs and assign 361 * the newly created transfer to this object. */ 362 rc = SharedClipboardWinTransferCreate(&pCtx->Win, pTransfer); 363 364 /* Note: The actual requesting + retrieving of data will be done in the IDataObject implementation 365 (ClipboardDataObjectImpl::GetData()). */ 366 } 367 else 368 LogRel(("Shared Clipboard: Initializing read transfer failed with %Rrc\n", rc)); 369 } 370 else 371 { 440 if ( RT_SUCCESS(rc) 441 && fFormats & VBOX_SHCL_FMT_URI_LIST) 442 { 443 /* 444 * The host requested data from the guest as URI list. 445 * 446 * This means on Windows we 447 * - need to first create an own IDataObject and push it on the clipboard 448 * - register a transfer locally so that we have a valid ID for it 449 * 450 * That way Windows will recognize that there is a data transfer "in flight". 451 * 452 * As soon as the user requests to "paste" the data (transfer), the IDataObject will try to read data via 453 * the pfnOnRequestDataFromSource callback. 454 */ 455 SHCLCALLBACKS Callbacks; 456 RT_ZERO(Callbacks); 457 Callbacks.pfnOnRequestDataFromSource = vboxClipboardSvcWinRequestDataFromSourceCallback; 458 459 rc = SharedClipboardWinTransferCreateAndSetDataObject(pWinCtx, pCtx, &Callbacks); 460 } 372 461 #endif 373 int rc = SharedClipboardWinClearAndAnnounceFormats(pWinCtx, fFormats, hWnd); 374 if (RT_FAILURE(rc)) 375 LogRel(("Shared Clipboard: Reporting clipboard formats %#x to Windows host failed with %Rrc\n", fFormats, rc)); 376 377 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 378 } 379 #endif 462 if (RT_FAILURE(rc)) 463 LogRel(("Shared Clipboard: Reporting clipboard formats %#x to Windows host failed with %Rrc\n", fFormats, rc)); 464 380 465 LogFunc(("SHCL_WIN_WM_REPORT_FORMATS: lastErr=%ld\n", GetLastError())); 381 466 break; … … 605 690 else 606 691 LogRel(("Shared Clipboard: Initialized OLE\n")); 607 #endif 692 #endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */ 608 693 609 694 return VINF_SUCCESS; … … 635 720 { 636 721 rc = RTThreadCreate(&pCtx->hThread, vboxClipboardSvcWinThread, pCtx /* pvUser */, _64K /* Stack size */, 637 RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "S HCLIP");722 RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "ShClWin"); 638 723 if (RT_SUCCESS(rc)) 639 724 { … … 645 730 pClient->State.pCtx = pCtx; 646 731 pClient->State.pCtx->pClient = pClient; 732 733 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 734 /* 735 * Init transfer callbacks. 736 */ 737 RT_ZERO(pClient->Transfers.Callbacks); 738 pClient->Transfers.Callbacks.pfnOnStarted = vboxClipboardSvcWinTransferStartedCallback; 739 740 pClient->Transfers.Callbacks.pvUser = pCtx; /* Assign context as user-provided callback data. */ 741 pClient->Transfers.Callbacks.cbUser = sizeof(SHCLCONTEXT); 742 #endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */ 647 743 } 648 744 else … … 718 814 * The guest announced formats. Forward to the window thread. 719 815 */ 720 PostMessage(pCtx->Win.hWnd, SHCL_WIN_WM_REPORT_FORMATS, 721 0 /* wParam */, fFormats /* lParam */); 722 816 PostMessage(pCtx->Win.hWnd, SHCL_WIN_WM_REPORT_FORMATS, 0 /* wParam */, fFormats /* lParam */); 723 817 724 818 LogFlowFuncLeaveRC(VINF_SUCCESS); … … 821 915 else if (uFmt & VBOX_SHCL_FMT_URI_LIST) 822 916 { 823 AssertFailed(); /** @todo */ 917 hClip = hClip = GetClipboardData(CF_HDROP); 918 if (hClip) 919 { 920 HDROP hDrop = (HDROP)GlobalLock(hClip); 921 if (hDrop) 922 { 923 char *pszList = NULL; 924 uint32_t cbList; 925 rc = SharedClipboardWinTransferDropFilesToStringList((DROPFILES *)hDrop, &pszList, &cbList); 926 927 GlobalUnlock(hClip); 928 929 if (RT_SUCCESS(rc)) 930 { 931 if (cbList <= cbData) 932 { 933 memcpy(pvData, pszList, cbList); 934 *pcbActual = cbList; 935 } 936 937 RTStrFree(pszList); 938 } 939 } 940 else 941 LogRel(("Shared Clipboard: Unable to lock clipboard data, last error: %ld\n", GetLastError())); 942 } 943 else 944 LogRel(("Shared Clipboard: Unable to retrieve clipboard data from clipboard (CF_HDROP), last error: %ld\n", 945 GetLastError())); 824 946 } 825 947 #endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */ … … 827 949 } 828 950 829 if (hClip == NULL) /* Empty data is not fatal. */830 {831 /* Reply with empty data. */832 vboxClipboardSvcWinDataGet(0, NULL, 0, pvData, cbData, pcbActual);833 }834 835 951 if (RT_FAILURE(rc)) 836 952 LogRel(("Shared Clipboard: Error reading host clipboard data in format %#x from Windows, rc=%Rrc\n", uFmt, rc)); … … 882 998 const PSHCLWINCTX pWinCtx = &pClient->State.pCtx->Win; 883 999 884 int rc = SharedClipboardWin GetRoots(pWinCtx, pTransfer);1000 int rc = SharedClipboardWinTransferGetRootsFromClipboard(pWinCtx, pTransfer); 885 1001 886 1002 LogFlowFuncLeaveRC(rc); -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-x11.cpp
r100018 r100204 44 44 #include <iprt/errcore.h> 45 45 46 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP 47 # include <VBox/GuestHost/SharedClipboard-transfers.h> 48 #endif 49 46 50 #include "VBoxSharedClipboardSvc-internal.h" 47 51 … … 74 78 * Prototypes * 75 79 *********************************************************************************************************************************/ 76 static DECLCALLBACK(int) shClReportFormatsCallback(PSHCLCONTEXT pCtx, uint32_t fFormats, void *pvUser); 77 static DECLCALLBACK(int) shClSendDataToDestCallback(PSHCLCONTEXT pCtx, void *pv, uint32_t cb, void *pvUser); 78 static DECLCALLBACK(int) shClRequestDataFromSourceCallback(PSHCLCONTEXT pCtx, SHCLFORMAT uFmt, void **ppv, uint32_t *pcb, void *pvUser); 80 static DECLCALLBACK(int) shClSvcX11ReportFormatsCallback(PSHCLCONTEXT pCtx, uint32_t fFormats, void *pvUser); 81 static DECLCALLBACK(int) shClSvcX11RequestDataFromSourceCallback(PSHCLCONTEXT pCtx, SHCLFORMAT uFmt, void **ppv, uint32_t *pcb, void *pvUser); 79 82 80 83 … … 91 94 RT_ZERO(pBackend->Callbacks); 92 95 /* Use internal callbacks by default. */ 93 pBackend->Callbacks.pfnReportFormats = shClReportFormatsCallback; 94 pBackend->Callbacks.pfnOnRequestDataFromSource = shClRequestDataFromSourceCallback; 95 pBackend->Callbacks.pfnOnSendDataToDest = shClSendDataToDestCallback; 96 pBackend->Callbacks.pfnReportFormats = shClSvcX11ReportFormatsCallback; 97 pBackend->Callbacks.pfnOnRequestDataFromSource = shClSvcX11RequestDataFromSourceCallback; 96 98 97 99 return VINF_SUCCESS; … … 112 114 113 115 SET_FN_IF_NOT_NULL(ReportFormats); 114 SET_FN_IF_NOT_NULL(OnClipboardRead);115 SET_FN_IF_NOT_NULL(OnClipboardWrite);116 116 SET_FN_IF_NOT_NULL(OnRequestDataFromSource); 117 SET_FN_IF_NOT_NULL(OnSendDataToDest);118 117 119 118 #undef SET_FN_IF_NOT_NULL … … 190 189 } 191 190 192 /* 193 * Shut down the shared clipboard service and "disconnect" the guest.191 /** 192 * Shuts down the shared clipboard service and "disconnect" the guest. 194 193 * Note! Host glue code 195 194 */ … … 225 224 } 226 225 226 /** 227 * Reports clipboard formats to the host clipboard. 228 */ 227 229 int ShClBackendReportFormats(PSHCLBACKEND pBackend, PSHCLCLIENT pClient, SHCLFORMATS fFormats) 228 230 { 229 231 RT_NOREF(pBackend); 230 232 231 int rc = ShClX11ReportFormatsToX11(&pClient->State.pCtx->X11, fFormats); 232 233 LogFlowFuncLeaveRC(rc); 234 return rc; 235 } 236 237 /** Structure describing a request for clipoard data from the guest. */ 238 struct CLIPREADCBREQ 239 { 240 /** User-supplied data pointer, based on the request type. */ 241 void *pv; 242 /** The size (in bytes) of the the user-supplied pointer in pv. */ 243 uint32_t cb; 244 /** The actual size of the data written. */ 245 uint32_t *pcbActual; 246 /** The request's event ID. */ 247 SHCLEVENTID idEvent; 248 }; 249 250 /** 233 int rc = ShClX11ReportFormatsToX11Async(&pClient->State.pCtx->X11, fFormats); 234 235 LogFlowFuncLeaveRC(rc); 236 return rc; 237 } 238 239 /** 240 * Reads data from the host clipboard. 241 * 242 * Schedules a request to the X11 event thread. 243 * 251 244 * @note We always fail or complete asynchronously. 252 * @note On success allocates a CLIPREADCBREQ structure which must be253 * freed in ClipCompleteDataRequestFromX11 when it is called back from254 * the backend code.255 245 */ 256 246 int ShClBackendReadData(PSHCLBACKEND pBackend, PSHCLCLIENT pClient, PSHCLCLIENTCMDCTX pCmdCtx, SHCLFORMAT uFormat, … … 269 259 pClient, uFormat, pvData, cbData, pcbActual)); 270 260 271 int rc; 272 273 CLIPREADCBREQ *pReq = (CLIPREADCBREQ *)RTMemAllocZ(sizeof(CLIPREADCBREQ)); 274 if (pReq) 275 { 276 PSHCLEVENT pEvent; 277 rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvent); 261 PSHCLEVENT pEvent; 262 int rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvent); 263 if (RT_SUCCESS(rc)) 264 { 265 rc = ShClX11ReadDataFromX11Async(&pClient->State.pCtx->X11, uFormat, cbData, pEvent); 278 266 if (RT_SUCCESS(rc)) 279 267 { 280 pReq->pv = pvData; 281 pReq->cb = cbData; 282 pReq->pcbActual = pcbActual; 283 pReq->idEvent = pEvent->idEvent; 284 285 /* Note: ShClX11ReadDataFromX11() will consume pReq on success. */ 286 rc = ShClX11ReadDataFromX11(&pClient->State.pCtx->X11, uFormat, pReq); 268 PSHCLEVENTPAYLOAD pPayload; 269 rc = ShClEventWait(pEvent, SHCL_TIMEOUT_DEFAULT_MS, &pPayload); 287 270 if (RT_SUCCESS(rc)) 288 271 { 289 PSHCLEVENTPAYLOAD pPayload; 290 rc = ShClEventWait(pEvent, SHCL_TIMEOUT_DEFAULT_MS, &pPayload); 291 if (RT_SUCCESS(rc)) 272 if (pPayload) 292 273 { 293 if (pPayload) 294 { 295 memcpy(pvData, pPayload->pvData, RT_MIN(cbData, pPayload->cbData)); 296 297 *pcbActual = (uint32_t)pPayload->cbData; 298 299 ShClPayloadFree(pPayload); 300 } 301 else /* No payload given; could happen on invalid / not-expected formats. */ 302 *pcbActual = 0; 274 Assert(pPayload->cbData == sizeof(SHCLX11RESPONSE)); 275 PSHCLX11RESPONSE pResp = (PSHCLX11RESPONSE)pPayload->pvData; 276 277 size_t const cbToCopy = RT_MIN(cbData, pPayload->cbData); 278 if (cbToCopy) /* memcpy doesn't like 0 byte inputs. */ 279 memcpy(pvData, pResp->Read.pvData, RT_MIN(cbData, pPayload->cbData)); 280 281 LogRel2(("Shared Clipboard: Read %RU32 bytes host X11 clipboard data\n", pResp->Read.cbData)); 282 283 *pcbActual = pResp->Read.cbData; 284 285 RTMemFree(pResp->Read.pvData); 286 pResp->Read.cbData = 0; 287 288 ShClPayloadFree(pPayload); 303 289 } 290 else /* No payload given; could happen on invalid / not-expected formats. */ 291 *pcbActual = 0; 304 292 } 305 306 ShClEventRelease(pEvent); 307 } 308 309 if (RT_FAILURE(rc)) 310 RTMemFree(pReq); 311 } 312 else 313 rc = VERR_NO_MEMORY; 293 } 294 295 ShClEventRelease(pEvent); 296 } 314 297 315 298 if (RT_FAILURE(rc)) … … 320 303 } 321 304 322 int ShClBackendWriteData(PSHCLBACKEND pBackend, PSHCLCLIENT pClient, PSHCLCLIENTCMDCTX pCmdCtx, SHCLFORMAT uFormat, void *pvData, uint32_t cbData) 305 int ShClBackendWriteData(PSHCLBACKEND pBackend, PSHCLCLIENT pClient, PSHCLCLIENTCMDCTX pCmdCtx, 306 SHCLFORMAT uFormat, void *pvData, uint32_t cbData) 323 307 { 324 308 RT_NOREF(pBackend, pClient, pCmdCtx, uFormat, pvData, cbData); … … 332 316 } 333 317 334 /** @copydoc SHCLCALLBACKS::pfnReportFormats */ 335 static DECLCALLBACK(int) shClReportFormatsCallback(PSHCLCONTEXT pCtx, uint32_t fFormats, void *pvUser) 318 /** 319 * @copydoc SHCLCALLBACKS::pfnReportFormats 320 * 321 * Reports clipboard formats to the guest. 322 */ 323 static DECLCALLBACK(int) shClSvcX11ReportFormatsCallback(PSHCLCONTEXT pCtx, uint32_t fFormats, void *pvUser) 336 324 { 337 325 RT_NOREF(pvUser); … … 362 350 } 363 351 364 /** @copydoc SHCLCALLBACKS::pfnOnSendDataToDest */ 365 static DECLCALLBACK(int) shClSendDataToDestCallback(PSHCLCONTEXT pCtx, void *pv, uint32_t cb, void *pvUser) 366 { 367 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 368 AssertPtrReturn(pvUser, VERR_INVALID_POINTER); 369 370 PSHCLX11READDATAREQ pData = (PSHCLX11READDATAREQ)pvUser; 371 CLIPREADCBREQ *pReq = pData->pReq; 372 373 LogFlowFunc(("rcCompletion=%Rrc, pReq=%p, pv=%p, cb=%RU32, idEvent=%RU32\n", 374 pData->rcCompletion, pReq, pv, cb, pReq->idEvent)); 375 376 if (pReq->idEvent != NIL_SHCLEVENTID) 377 { 378 int rc2; 379 380 PSHCLEVENTPAYLOAD pPayload = NULL; 381 if ( RT_SUCCESS(pData->rcCompletion) 382 && pv 383 && cb) 384 { 385 rc2 = ShClPayloadAlloc(pReq->idEvent, pv, cb, &pPayload); 386 AssertRC(rc2); 387 } 388 389 rc2 = RTCritSectEnter(&pCtx->pClient->CritSect); 390 if (RT_SUCCESS(rc2)) 391 { 392 const PSHCLEVENT pEvent = ShClEventSourceGetFromId(&pCtx->pClient->EventSrc, pReq->idEvent); 393 if (pEvent) 394 rc2 = ShClEventSignal(pEvent, pPayload); 395 396 RTCritSectLeave(&pCtx->pClient->CritSect); 397 398 if (RT_SUCCESS(rc2)) 399 pPayload = NULL; 400 } 401 402 if (pPayload) 403 ShClPayloadFree(pPayload); 404 } 405 406 if (pReq) 407 RTMemFree(pReq); 408 409 LogRel2(("Shared Clipboard: Reading X11 clipboard data from host completed with %Rrc\n", pData->rcCompletion)); 410 411 return VINF_SUCCESS; 412 } 413 414 /** @copydoc SHCLCALLBACKS::pfnOnRequestDataFromSource */ 415 static DECLCALLBACK(int) shClRequestDataFromSourceCallback(PSHCLCONTEXT pCtx, SHCLFORMAT uFmt, void **ppv, uint32_t *pcb, void *pvUser) 352 /** 353 * @copydoc SHCLCALLBACKS::pfnOnRequestDataFromSource 354 * 355 * Requests clipboard data from the guest. 356 * 357 * @thread Called from X11 event thread. 358 */ 359 static DECLCALLBACK(int) shClSvcX11RequestDataFromSourceCallback(PSHCLCONTEXT pCtx, 360 SHCLFORMAT uFmt, void **ppv, uint32_t *pcb, void *pvUser) 416 361 { 417 362 RT_NOREF(pvUser); … … 426 371 } 427 372 428 PSHCLCLIENT pClient = pCtx->pClient;429 AssertPtr(pClient);430 431 RTCritSectEnter(&pClient->CritSect);432 433 373 int rc = VINF_SUCCESS; 434 374 435 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 375 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP 436 376 /* 437 377 * Note: We always return a generic URI list here. … … 441 381 if (uFmt == VBOX_SHCL_FMT_URI_LIST) 442 382 { 443 PSHCLTRANSFER pTransfer; 444 rc = shClSvcTransferStart(pCtx->pClient, 445 SHCLTRANSFERDIR_FROM_REMOTE, SHCLSOURCE_REMOTE, 446 &pTransfer); 447 if (RT_SUCCESS(rc)) 448 { 449 450 } 451 else 452 LogRel(("Shared Clipboard: Initializing read transfer from guest failed with %Rrc\n", rc)); 383 PSHCLTRANSFER pTransfer = ShClTransferHttpServerGetTransferFirst(&pCtx->X11.HttpCtx.HttpServer); 384 if (pTransfer) 385 { 386 if (RT_SUCCESS(rc)) 387 rc = ShClTransferRootListRead(pTransfer); 388 } 389 390 /** @todo BUGBUG IMPLEMENT THIS! */ 453 391 454 392 *ppv = NULL; … … 461 399 if (RT_SUCCESS(rc)) 462 400 { 463 /* Request data from the guest . */401 /* Request data from the guest and for data to arrive. */ 464 402 PSHCLEVENT pEvent; 465 rc = ShClSvc GuestDataRequest(pCtx->pClient, uFmt, &pEvent);403 rc = ShClSvcReadDataFromGuestAsync(pCtx->pClient, uFmt, &pEvent); 466 404 if (RT_SUCCESS(rc)) 467 405 { 468 RTCritSectLeave(&pClient->CritSect);469 470 406 PSHCLEVENTPAYLOAD pPayload; 471 407 rc = ShClEventWait(pEvent, SHCL_TIMEOUT_DEFAULT_MS, &pPayload); … … 484 420 } 485 421 486 RTCritSectEnter(&pClient->CritSect);487 488 422 ShClEventRelease(pEvent); 489 423 } 490 424 } 491 492 RTCritSectLeave(&pClient->CritSect);493 425 494 426 if (RT_FAILURE(rc)) … … 507 439 /* We only need to start the HTTP server (and register the transfer to it) when we actually receive data from the guest. */ 508 440 if (ShClTransferGetDir(pTransfer) == SHCLTRANSFERDIR_FROM_REMOTE) 509 return ShCl HttpTransferRegisterAndMaybeStart(&pClient->State.pCtx->X11.HttpCtx, pTransfer);441 return ShClTransferHttpServerMaybeStart(&pClient->State.pCtx->X11.HttpCtx); 510 442 #else 511 443 RT_NOREF(pClient, pTransfer); … … 520 452 /* See comment in ShClBackendTransferCreate(). */ 521 453 if (ShClTransferGetDir(pTransfer) == SHCLTRANSFERDIR_FROM_REMOTE) 522 return ShCl HttpTransferUnregisterAndMaybeStop(&pClient->State.pCtx->X11.HttpCtx, pTransfer);454 return ShClTransferHttpServerMaybeStop(&pClient->State.pCtx->X11.HttpCtx); 523 455 #else 524 456 RT_NOREF(pClient, pTransfer); … … 537 469 if (RT_SUCCESS(rc)) 538 470 { 539 CLIPREADCBREQ *pReq = (CLIPREADCBREQ *)RTMemAllocZ(sizeof(CLIPREADCBREQ));540 if ( pReq)541 { 542 pReq->idEvent = pEvent->idEvent;543 544 rc = ShCl X11ReadDataFromX11(&pClient->State.pCtx->X11, VBOX_SHCL_FMT_URI_LIST, pReq);471 rc = ShClX11ReadDataFromX11Async(&pClient->State.pCtx->X11, VBOX_SHCL_FMT_URI_LIST, UINT32_MAX, pEvent); 472 if (RT_SUCCESS(rc)) 473 { 474 /* X supplies the data asynchronously, so we need to wait for data to arrive first. */ 475 PSHCLEVENTPAYLOAD pPayload; 476 rc = ShClEventWait(pEvent, SHCL_TIMEOUT_DEFAULT_MS, &pPayload); 545 477 if (RT_SUCCESS(rc)) 546 478 { 547 /* X supplies the data asynchronously, so we need to wait for data to arrive first. */ 548 PSHCLEVENTPAYLOAD pPayload; 549 rc = ShClEventWait(pEvent, SHCL_TIMEOUT_DEFAULT_MS, &pPayload); 550 if (RT_SUCCESS(rc)) 479 if (pPayload) 551 480 { 552 if (pPayload) 553 { 554 rc = ShClTransferRootsSet(pTransfer, 555 (char *)pPayload->pvData, pPayload->cbData + 1 /* Include termination */); 556 } 557 else 558 rc = VERR_NO_DATA; /* No payload. */ 481 Assert(pPayload->cbData == sizeof(SHCLX11RESPONSE)); 482 AssertPtr(pPayload->pvData); 483 PSHCLX11RESPONSE pResp = (PSHCLX11RESPONSE)pPayload->pvData; 484 485 rc = ShClTransferRootsInitFromStringList(pTransfer, 486 (char *)pResp->Read.pvData, pResp->Read.cbData + 1 /* Include zero terminator */); 487 if (RT_SUCCESS(rc)) 488 rc = ShClTransferRootListRead(pTransfer); 489 490 if (RT_SUCCESS(rc)) 491 LogRel2(("Shared Clipboard: Host reported %RU64 X11 root entries for transfer to guest\n", ShClTransferRootsCount(pTransfer))); 492 493 RTMemFree(pResp->Read.pvData); 494 pResp->Read.cbData = 0; 495 496 ShClPayloadFree(pPayload); 497 pPayload = NULL; 559 498 } 499 else 500 rc = VERR_NO_DATA; /* No payload. */ 560 501 } 561 502 } 562 else563 rc = VERR_NO_MEMORY;564 503 565 504 ShClEventRelease(pEvent); -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc.cpp
r100017 r100204 552 552 553 553 RTListAppend(&pClient->MsgQueue, &pMsg->ListEntry); 554 return shClSvcClientWakeup(pClient); 554 return shClSvcClientWakeup(pClient); /** @todo r=andy Remove message if waking up failed? */ 555 555 } 556 556 … … 1173 1173 * @returns VBox status code. 1174 1174 * @retval VINF_NO_CHANGE if the client is not in pending mode. 1175 *1176 1175 * @param pClient Client to wake up. 1177 * @note Caller must enter pClient->CritSect. 1176 * 1177 * @note Caller must enter critical section. 1178 1178 */ 1179 1179 int shClSvcClientWakeup(PSHCLCLIENT pClient) … … 1225 1225 * @param pClient Client to request to read data form. 1226 1226 * @param fFormats The formats being requested, OR'ed together (VBOX_SHCL_FMT_XXX). 1227 * @param ppEvent Where to return the event for waiting for new data on success. Optional. 1228 * Must be released by the caller with ShClEventRelease(). 1229 */ 1230 int ShClSvcGuestDataRequest(PSHCLCLIENT pClient, SHCLFORMATS fFormats, PSHCLEVENT *ppEvent) 1227 * @param ppEvent Where to return the event for waiting for new data on success. 1228 * Must be released by the caller with ShClEventRelease(). Optional. 1229 * 1230 * @thread On X11: Called from the X11 event thread. 1231 * @thread On Windows: Called from the Windows event thread. 1232 * 1233 * @note This will locally initialize a transfer if VBOX_SHCL_FMT_URI_LIST is being requested from the guest. 1234 */ 1235 int ShClSvcReadDataFromGuestAsync(PSHCLCLIENT pClient, SHCLFORMATS fFormats, PSHCLEVENT *ppEvent) 1231 1236 { 1232 1237 AssertPtrReturn(pClient, VERR_INVALID_POINTER); … … 1248 1253 else if (fFormats & VBOX_SHCL_FMT_HTML) 1249 1254 fFormat = VBOX_SHCL_FMT_HTML; 1255 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 1256 else if (fFormats & VBOX_SHCL_FMT_URI_LIST) 1257 fFormat = VBOX_SHCL_FMT_URI_LIST; 1258 #endif 1250 1259 else 1251 1260 AssertMsgFailedBreak(("%#x\n", fFormats)); … … 1269 1278 if (pMsg) 1270 1279 { 1271 /* 1272 * Enter the critical section and generate an event. 1273 */ 1274 RTCritSectEnter(&pClient->CritSect); 1280 shClSvcClientLock(pClient); 1275 1281 1276 1282 PSHCLEVENT pEvent; … … 1316 1322 1317 1323 shClSvcMsgAdd(pClient, pMsg, true /* fAppend */); 1318 1319 /* Return event handle to the caller if requested. */ 1324 /* Wake up the client to let it know that there are new messages. */ 1325 shClSvcClientWakeup(pClient); 1326 1327 /* Return event to caller. */ 1320 1328 if (ppEvent) 1321 {1322 1329 *ppEvent = pEvent; 1323 }1324 1325 shClSvcClientWakeup(pClient);1326 1330 } 1327 1331 1332 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 1333 /* 1334 * When the host wants to read URI data from the guest: 1335 * - Initialize a transfer locally. 1336 * - Request URI data from the guest; this tells the guest to initialize a transfer on the guest side. 1337 * - Start the transfer locally once we receive the transfer STARTED status from the guest via VBOX_SHCL_GUEST_FN_REPLY. 1338 */ 1339 if ( RT_SUCCESS(rc) 1340 && fFormat == VBOX_SHCL_FMT_URI_LIST) 1341 { 1342 rc = shClSvcTransferInit(pClient, SHCLTRANSFERDIR_FROM_REMOTE, SHCLSOURCE_REMOTE, 1343 NULL /* pTransfer */); 1344 if (RT_SUCCESS(rc)) 1345 rc = shClSvcSetSource(pClient, SHCLSOURCE_REMOTE); 1346 1347 if (RT_FAILURE(rc)) 1348 LogRel(("Shared Clipboard: Initializing guest -> host transfer failed with %Rrc\n", rc)); 1349 } 1350 #endif 1328 1351 /* Remove event from list if caller did not request event handle or in case 1329 1352 * of failure (in this case caller should not release event). */ … … 1332 1355 { 1333 1356 ShClEventRelease(pEvent); 1357 pEvent = NULL; 1334 1358 } 1335 1359 } … … 1337 1361 rc = VERR_SHCLPB_MAX_EVENTS_REACHED; 1338 1362 1339 RTCritSectLeave(&pClient->CritSect);1340 1341 1363 if (RT_FAILURE(rc)) 1342 1364 shClSvcMsgFree(pClient, pMsg); 1365 1366 shClSvcClientUnlock(pClient); 1343 1367 } 1344 1368 else … … 1350 1374 1351 1375 if (RT_FAILURE(rc)) 1352 LogRel(("Shared Clipboard: Requesting data in formats %#x from guest failed with %Rrc\n", fFormats, rc));1376 LogRel(("Shared Clipboard: Requesting guest clipboard data failed with %Rrc\n", rc)); 1353 1377 1354 1378 LogFlowFuncLeaveRC(rc); … … 1367 1391 * @param cbData Size (in bytes) of clipboard data received. 1368 1392 * This can be zero. 1393 * 1394 * @thread Backend thread. 1369 1395 */ 1370 1396 int ShClSvcGuestDataSignal(PSHCLCLIENT pClient, PSHCLCLIENTCMDCTX pCmdCtx, SHCLFORMAT uFormat, void *pvData, uint32_t cbData) … … 1414 1440 1415 1441 /** 1416 * Reports available VBoxclipboard formats to the guest.1442 * Reports clipboard formats to the guest. 1417 1443 * 1418 1444 * @note Host backend callers must check if it's active (use … … 1424 1450 * @param fFormats The formats to report (VBOX_SHCL_FMT_XXX), zero 1425 1451 * is okay (empty the clipboard). 1452 * 1453 * @thread Backend thread. 1426 1454 */ 1427 1455 int ShClSvcHostReportFormats(PSHCLCLIENT pClient, SHCLFORMATS fFormats) 1428 1456 { 1457 LogFlowFuncEnter(); 1458 1429 1459 /* 1430 1460 * Check if the service mode allows this operation and whether the guest is … … 1479 1509 1480 1510 RTCritSectEnter(&pClient->CritSect); 1481 shClSvcMsgAddAndWakeupClient(pClient, pMsg);1511 rc = shClSvcMsgAddAndWakeupClient(pClient, pMsg); 1482 1512 RTCritSectLeave(&pClient->CritSect); 1483 1484 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS1485 /* Create a transfer locally and also tell the guest to create a transfer on the guest side. */1486 if ( !fSkipTransfers1487 && fFormats & VBOX_SHCL_FMT_URI_LIST) /* Only start a transfer if we supply an URI list. */1488 {1489 rc = shClSvcTransferStart(pClient, SHCLTRANSFERDIR_TO_REMOTE, SHCLSOURCE_LOCAL,1490 NULL /* pTransfer */);1491 if (RT_SUCCESS(rc))1492 rc = shClSvcSetSource(pClient, SHCLSOURCE_LOCAL);1493 1494 if (RT_FAILURE(rc))1495 LogRel(("Shared Clipboard: Initializing host write transfer failed with %Rrc\n", rc));1496 }1497 else1498 #endif1499 rc = VINF_SUCCESS;1500 1513 } 1501 1514 else … … 1749 1762 else 1750 1763 LogRel(("Shared Clipboard: Reading host clipboard data failed with %Rrc\n", rc)); 1764 1765 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 1766 /* 1767 * When we receive a read request for URI data: 1768 * - Initialize a transfer locally. 1769 * - Tell the guest to initialize a transfer on the guest side. 1770 * - Start the transfer locally once we receive the transfer STARTED status from the guest via VBOX_SHCL_GUEST_FN_REPLY. 1771 */ 1772 if (uFormat == VBOX_SHCL_FMT_URI_LIST) /* Only init a transfer if we supply an URI list. */ 1773 { 1774 shClSvcClientLock(pClient); 1775 1776 rc = shClSvcTransferInit(pClient, SHCLTRANSFERDIR_TO_REMOTE, SHCLSOURCE_LOCAL, 1777 NULL /* pTransfer */); 1778 if (RT_SUCCESS(rc)) 1779 rc = shClSvcSetSource(pClient, SHCLSOURCE_LOCAL); 1780 1781 if (RT_FAILURE(rc)) 1782 LogRel(("Shared Clipboard: Initializing host -> guest transfer failed with %Rrc\n", rc)); 1783 1784 shClSvcClientUnlock(pClient); 1785 } 1786 #endif 1751 1787 } 1752 1788 … … 1976 2012 int rc = VINF_SUCCESS; 1977 2013 1978 if (ShClSvcLock()) 1979 { 1980 pClient->State.enmSource = enmSource; 1981 1982 LogFlowFunc(("Source of client %RU32 is now %RU32\n", pClient->State.uClientID, pClient->State.enmSource)); 1983 1984 ShClSvcUnlock(); 1985 } 2014 pClient->State.enmSource = enmSource; 2015 2016 LogFlowFunc(("Source of client %RU32 is now %RU32\n", pClient->State.uClientID, pClient->State.enmSource)); 1986 2017 1987 2018 LogFlowFuncLeaveRC(rc); … … 2725 2756 /* The service extension wants read data from the guest. */ 2726 2757 case VBOX_CLIPBOARD_EXT_FN_DATA_READ: 2727 rc = ShClSvcGuestDataRequest(pClient, u32Format, NULL /* pidEvent */); 2758 { 2759 PSHCLEVENT pEvent; 2760 rc = ShClSvcReadDataFromGuestAsync(pClient, u32Format, &pEvent); 2761 if (RT_SUCCESS(rc)) 2762 { 2763 PSHCLEVENTPAYLOAD pPayload; 2764 rc = ShClEventWait(pEvent, SHCL_TIMEOUT_DEFAULT_MS, &pPayload); 2765 if (RT_SUCCESS(rc)) 2766 { 2767 if (pPayload) 2768 { 2769 memcpy(pvData, pPayload->pvData, RT_MIN(cbData, pPayload->cbData)); 2770 /** @todo r=andy How is this supposed to work wrt returning number of bytes read? */ 2771 2772 ShClPayloadFree(pPayload); 2773 pPayload = NULL; 2774 } 2775 else 2776 { 2777 pvData = NULL; 2778 } 2779 } 2780 2781 ShClEventRelease(pEvent); 2782 } 2728 2783 break; 2784 } 2785 2786 /** @todo BUGBUG Why no VBOX_CLIPBOARD_EXT_FN_DATA_WRITE here? */ 2729 2787 2730 2788 default: -
trunk/src/VBox/HostServices/SharedClipboard/testcase/Makefile.kmk
r100011 r100204 78 78 $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/clipboard-transfers.cpp \ 79 79 $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/clipboard-transfers-provider-local.cpp 80 tstClipboardMockHGCM_SOURCES.win += \ 81 $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardDataObjectImpl-win.cpp \ 82 $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardEnumFormatEtcImpl-win.cpp \ 83 $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardStreamImpl-win.cpp 80 84 endif 81 85 -
trunk/src/VBox/HostServices/SharedClipboard/testcase/tstClipboardServiceHost.cpp
r99968 r100204 140 140 static void testMsgAddReadData(PSHCLCLIENT pClient, SHCLFORMATS fFormats) 141 141 { 142 int rc = ShClSvc GuestDataRequest(pClient, fFormats, NULL /* pidEvent */);142 int rc = ShClSvcReadDataFromGuestAsync(pClient, fFormats, NULL /* ppEvent */); 143 143 RTTESTI_CHECK_RC_OK(rc); 144 144 } -
trunk/src/VBox/HostServices/SharedClipboard/testcase/tstClipboardTransfers.cpp
r98103 r100204 215 215 RTTESTI_CHECK_RC_OK(rc); 216 216 217 SHCLTXPROVIDER Provider; 218 RTTESTI_CHECK(VBClTransferProviderLocalQueryInterface(&Provider) != NULL); 219 RTTESTI_CHECK_RC_OK(ShClTransferSetProvider(pTransfer, &Provider)); 220 217 221 char szTestTransferRootsSetDir[RTPATH_MAX]; 218 222 rc = testCreateTempDir(hTest, "testTransferRootsSet", szTestTransferRootsSetDir, sizeof(szTestTransferRootsSetDir)); … … 227 231 RTTESTI_CHECK_RC_OK_RETV(rc); 228 232 229 rc = ShClTransferRoots Set(pTransfer, pszRoots, strlen(pszRoots) + 1);233 rc = ShClTransferRootsInitFromStringList(pTransfer, pszRoots, strlen(pszRoots) + 1); 230 234 RTTESTI_CHECK_RC(rc, rcExpected); 231 235 … … 243 247 PSHCLTRANSFER pTransfer; 244 248 int rc = ShClTransferCreate(&pTransfer); 249 RTTESTI_CHECK_RC_OK(rc); 250 251 SHCLTXPROVIDER Provider; 252 VBClTransferProviderLocalQueryInterface(&Provider); 253 254 rc = ShClTransferSetProvider(pTransfer, &Provider); 245 255 RTTESTI_CHECK_RC_OK(rc); 246 256 … … 262 272 RTTESTI_CHECK_RC_OK_RETV(rc); 263 273 264 rc = ShClTransferRoots Set(pTransfer, pszRoots, strlen(pszRoots) + 1);274 rc = ShClTransferRootsInitFromStringList(pTransfer, pszRoots, strlen(pszRoots) + 1); 265 275 RTTESTI_CHECK_RC_OK(rc); 266 276 … … 303 313 rc = ShClTransferDestroy(pTransfer); 304 314 RTTESTI_CHECK_RC_OK(rc); 315 rc = ShClTransferDestroy(pTransfer); /* Second time, intentional. */ 316 RTTESTI_CHECK_RC_OK(rc); 317 318 PSHCLLIST pList = ShClTransferListAlloc(); 319 RTTESTI_CHECK(pList != NULL); 320 rc = ShClTransferCreate(&pTransfer); 321 RTTESTI_CHECK_RC_OK(rc); 322 ShClTransferListFree(pList); 323 pList = NULL; 324 ShClTransferListFree(pList); /* Second time, intentional. */ 325 326 SHCLLISTENTRY Entry; 327 RTTESTI_CHECK_RC_OK(ShClTransferListEntryInit(&Entry)); 328 ShClTransferListEntryDestroy(&Entry); 329 ShClTransferListEntryDestroy(&Entry); /* Second time, intentional. */ 305 330 } 306 331 … … 387 412 return RTTestSummaryAndDestroy(hTest); 388 413 } 389
Note:
See TracChangeset
for help on using the changeset viewer.