Changeset 100367 in vbox for trunk/src/VBox/HostServices/SharedClipboard
- Timestamp:
- Jul 4, 2023 4:23:18 PM (20 months ago)
- svn:sync-xref-src-repo-rev:
- 158104
- Location:
- trunk/src/VBox/HostServices/SharedClipboard
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-internal.h
r100205 r100367 282 282 extern SHCLEXTSTATE g_ExtState; 283 283 284 int shClSvcSetSource(PSHCLCLIENT pClient, SHCLSOURCE enmSource);285 286 284 void shClSvcMsgQueueReset(PSHCLCLIENT pClient); 287 285 PSHCLCLIENTMSG shClSvcMsgAlloc(PSHCLCLIENT pClient, uint32_t uMsg, uint32_t cParms); … … 302 300 int shClSvcClientWakeup(PSHCLCLIENT pClient); 303 301 304 # ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS305 int shClSvcTransferModeSet(uint32_t fMode);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);309 bool shClSvcTransferMsgIsAllowed(uint32_t uMode, uint32_t uMsg);310 void shClSvcClientTransfersReset(PSHCLCLIENT pClient);311 #endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */312 313 302 /** @name Service functions, accessible by the backends. 314 303 * Locking is between the (host) service thread and the platform-dependent (window) thread. … … 316 305 */ 317 306 int ShClSvcReadDataFromGuestAsync(PSHCLCLIENT pClient, SHCLFORMATS fFormats, PSHCLEVENT *ppEvent); 307 int ShClSvcReadDataFromGuest(PSHCLCLIENT pClient, SHCLFORMAT uFmt, void **ppv, uint32_t *pcb); 318 308 int ShClSvcGuestDataSignal(PSHCLCLIENT pClient, PSHCLCLIENTCMDCTX pCmdCtx, SHCLFORMAT uFormat, void *pvData, uint32_t cbData); 319 309 int ShClSvcHostReportFormats(PSHCLCLIENT pClient, SHCLFORMATS fFormats); … … 451 441 */ 452 442 /** 453 * Called after a transfer got created.443 * Called before a transfer gets destroyed. 454 444 * 455 445 * @returns VBox status code. 456 446 * @param pBackend Shared Clipboard backend to use. 457 447 * @param pClient Shared Clipboard client context. 458 * @param pTransfer Shared Clipboard transfer created.459 */ 460 int ShClBackendTransfer Create(PSHCLBACKEND pBackend, PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer);461 /** 462 * Called before a transfer gets destroyed.448 * @param pTransfer Shared Clipboard transfer to destroy. 449 */ 450 int ShClBackendTransferDestroy(PSHCLBACKEND pBackend, PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer); 451 /** 452 * Called after a transfer status got processed. 463 453 * 464 454 * @returns VBox status code. 465 455 * @param pBackend Shared Clipboard backend to use. 466 456 * @param pClient Shared Clipboard client context. 467 * @param pTransfer Shared Clipboard transfer to destroy. 468 */ 469 int ShClBackendTransferDestroy(PSHCLBACKEND pBackend, PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer); 470 /** 471 * Called when getting (determining) the transfer roots on the host side. 457 * @param pTransfer Shared Clipboard transfer to process status for. 458 * @param enmSource Transfer source which issues the reply. 459 * @param enmStatus Transfer status. 460 * @param rcStatus Status code (IPRT-style). Depends on \a enmStatus set. 461 */ 462 int ShClBackendTransferHandleStatusReply(PSHCLBACKEND pBackend, PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer, SHCLSOURCE enmSource, SHCLTRANSFERSTATUS enmStatus, int rcStatus); 463 /** 464 * Called when the guest wants to read the transfer roots. 472 465 * 473 466 * @returns VBox status code. … … 476 469 * @param pTransfer Shared Clipboard transfer to get roots for. 477 470 */ 478 int ShClBackendTransfer GetRoots(PSHCLBACKEND pBackend, PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer);471 int ShClBackendTransferHGRootListRead(PSHCLBACKEND pBackend, PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer); 479 472 /** @} */ 480 473 #endif … … 497 490 498 491 int shClSvcTransferIfaceRootsGet(PSHCLTXPROVIDERCTX pCtx, PSHCLLIST pRootList); 499 int shClSvcTransferIface ListOpen(PSHCLTXPROVIDERCTX pCtx, PSHCLLISTOPENPARMS pOpenParms, PSHCLLISTHANDLE phList);500 int shClSvcTransferIface ListClose(PSHCLTXPROVIDERCTX pCtx, SHCLLISTHANDLE hList);501 int shClSvcTransferIface ListHdrRead(PSHCLTXPROVIDERCTX pCtx, SHCLLISTHANDLE hList, PSHCLLISTHDR pListHdr);502 int shClSvcTransferIface ListHdrWrite(PSHCLTXPROVIDERCTX pCtx, SHCLLISTHANDLE hList, PSHCLLISTHDR pListHdr);503 int shClSvcTransferIface ListEntryRead(PSHCLTXPROVIDERCTX pCtx, SHCLLISTHANDLE hList, PSHCLLISTENTRY pListEntry);504 int shClSvcTransferIface ListEntryWrite(PSHCLTXPROVIDERCTX pCtx, SHCLLISTHANDLE hList, PSHCLLISTENTRY pListEntry);505 506 int shClSvcTransferIface ObjOpen(PSHCLTXPROVIDERCTX pCtx, PSHCLOBJOPENCREATEPARMS pCreateParms,492 int shClSvcTransferIfaceGHListOpen(PSHCLTXPROVIDERCTX pCtx, PSHCLLISTOPENPARMS pOpenParms, PSHCLLISTHANDLE phList); 493 int shClSvcTransferIfaceGHListClose(PSHCLTXPROVIDERCTX pCtx, SHCLLISTHANDLE hList); 494 int shClSvcTransferIfaceGHListHdrRead(PSHCLTXPROVIDERCTX pCtx, SHCLLISTHANDLE hList, PSHCLLISTHDR pListHdr); 495 int shClSvcTransferIfaceHGListHdrWrite(PSHCLTXPROVIDERCTX pCtx, SHCLLISTHANDLE hList, PSHCLLISTHDR pListHdr); 496 int shClSvcTransferIfaceGHListEntryRead(PSHCLTXPROVIDERCTX pCtx, SHCLLISTHANDLE hList, PSHCLLISTENTRY pListEntry); 497 int shClSvcTransferIfaceHGListEntryWrite(PSHCLTXPROVIDERCTX pCtx, SHCLLISTHANDLE hList, PSHCLLISTENTRY pListEntry); 498 499 int shClSvcTransferIfaceGHObjOpen(PSHCLTXPROVIDERCTX pCtx, PSHCLOBJOPENCREATEPARMS pCreateParms, 507 500 PSHCLOBJHANDLE phObj); 508 int shClSvcTransferIface ObjClose(PSHCLTXPROVIDERCTX pCtx, SHCLOBJHANDLE hObj);509 int shClSvcTransferIface ObjRead(PSHCLTXPROVIDERCTX pCtx, SHCLOBJHANDLE hObj,501 int shClSvcTransferIfaceGHObjClose(PSHCLTXPROVIDERCTX pCtx, SHCLOBJHANDLE hObj); 502 int shClSvcTransferIfaceGHObjRead(PSHCLTXPROVIDERCTX pCtx, SHCLOBJHANDLE hObj, 510 503 void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbRead); 511 int shClSvcTransferIface ObjWrite(PSHCLTXPROVIDERCTX pCtx, SHCLOBJHANDLE hObj,504 int shClSvcTransferIfaceHGObjWrite(PSHCLTXPROVIDERCTX pCtx, SHCLOBJHANDLE hObj, 512 505 void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbWritten); 513 506 /** @} */ -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-transfers.cpp
r100291 r100367 61 61 * Prototypes * 62 62 *********************************************************************************************************************************/ 63 static int shClSvcTransferSetListOpen(uint32_t cParms, VBOXHGCMSVCPARM aParms[], 64 uint64_t idCtx, PSHCLLISTOPENPARMS pOpenParms); 65 static int shClSvcTransferSetListClose(uint32_t cParms, VBOXHGCMSVCPARM aParms[], 66 uint64_t idCtx, SHCLLISTHANDLE hList); 67 68 69 /********************************************************************************************************************************* 70 * Provider implementation * 71 *********************************************************************************************************************************/ 72 73 /** 74 * Resets all transfers of a Shared Clipboard client. 75 * 76 * @param pClient Client to reset transfers for. 77 */ 78 void shClSvcClientTransfersReset(PSHCLCLIENT pClient) 63 static int shClSvcTransferSendStatusAsyncInternal(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer, SHCLTRANSFERSTATUS uStatus, int rcTransfer, PSHCLEVENT *ppEvent); 64 static int shClSvcTransferSetListOpen(uint32_t cParms, VBOXHGCMSVCPARM aParms[], uint64_t idCtx, PSHCLLISTOPENPARMS pOpenParms); 65 static int shClSvcTransferSetListClose(uint32_t cParms, VBOXHGCMSVCPARM aParms[], uint64_t idCtx, SHCLLISTHANDLE hList); 66 67 68 /** 69 * Destroys all transfers of a Shared Clipboard client. 70 * 71 * @param pClient Client to destroy transfers for. 72 */ 73 void shClSvcTransferDestroyAll(PSHCLCLIENT pClient) 79 74 { 80 75 if (!pClient) … … 83 78 LogFlowFuncEnter(); 84 79 85 /* Make sure to let the backend know that all transfers are getting destroyed. */ 80 /* Unregister and destroy all transfers. 81 * Also make sure to let the backend know that all transfers are getting destroyed. */ 86 82 uint32_t uIdx = 0; 87 83 PSHCLTRANSFER pTransfer; 88 84 while ((pTransfer = ShClTransferCtxGetTransferByIndex(&pClient->Transfers.Ctx, uIdx++))) 89 ShClBackendTransferDestroy(pClient->pBackend, pClient, pTransfer); 90 91 ShClTransferCtxDestroy(&pClient->Transfers.Ctx); 85 ShClSvcTransferDestroy(pClient, pTransfer); 86 } 87 88 /** 89 * Reads a root list header from the guest, asynchronous version. 90 * 91 * @returns VBox status code. 92 * @param pClient Client to read from. 93 * @param idTransfer Transfer ID to read root list header for. 94 * @param ppEvent Where to return the event to wait for. 95 * Must be released by the caller with ShClEventRelease(). 96 */ 97 int ShClSvcTransferGHRootListReadHdrAsync(PSHCLCLIENT pClient, SHCLTRANSFERID idTransfer, PSHCLEVENT *ppEvent) 98 { 99 LogFlowFuncEnter(); 100 101 int rc; 102 103 PSHCLCLIENTMSG pMsgHdr = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_HDR_READ, 104 VBOX_SHCL_CPARMS_ROOT_LIST_HDR_READ_REQ); 105 if (pMsgHdr) 106 { 107 PSHCLEVENT pEvent; 108 rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvent); 109 if (RT_SUCCESS(rc)) 110 { 111 HGCMSvcSetU64(&pMsgHdr->aParms[0], VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID, 112 idTransfer, pEvent->idEvent)); 113 HGCMSvcSetU32(&pMsgHdr->aParms[1], 0 /* fRoots */); 114 115 shClSvcClientLock(pClient); 116 117 shClSvcMsgAdd(pClient, pMsgHdr, true /* fAppend */); 118 rc = shClSvcClientWakeup(pClient); 119 120 shClSvcClientUnlock(pClient); 121 122 /* Remove event from list if caller did not request event handle or in case 123 * of failure (in this case caller should not release event). */ 124 if ( RT_FAILURE(rc) 125 || !ppEvent) 126 { 127 ShClEventRelease(pEvent); 128 pEvent = NULL; 129 } 130 else if (ppEvent) 131 *ppEvent = pEvent; 132 } 133 else 134 { 135 shClSvcMsgFree(pClient, pMsgHdr); 136 rc = VERR_SHCLPB_MAX_EVENTS_REACHED; 137 } 138 } 139 else 140 rc = VERR_NO_MEMORY; 141 142 LogFlowFuncLeaveRC(rc); 143 return rc; 144 } 145 146 /** 147 * Reads a root list header from the guest. 148 * 149 * @returns VBox status code. 150 * @param pClient Client to read from. 151 * @param idTransfer Transfer ID to read root list header for. 152 * @param pHdr Where to store the root list header on succeess. 153 */ 154 int ShClSvcTransferGHRootListReadHdr(PSHCLCLIENT pClient, SHCLTRANSFERID idTransfer, PSHCLLISTHDR pHdr) 155 { 156 PSHCLEVENT pEvent; 157 int rc = ShClSvcTransferGHRootListReadHdrAsync(pClient, idTransfer, &pEvent); 158 if (RT_SUCCESS(rc)) 159 { 160 PSHCLEVENTPAYLOAD pPayload; 161 rc = ShClEventWait(pEvent, SHCL_TIMEOUT_DEFAULT_MS, &pPayload); 162 if (RT_SUCCESS(rc)) 163 { 164 Assert(pPayload->cbData == sizeof(SHCLLISTHDR)); 165 166 memcpy(pHdr, (PSHCLLISTHDR)pPayload->pvData, sizeof(SHCLLISTHDR)); 167 168 LogFlowFunc(("cRoots=%RU32, fFeatures=0x%x\n", pHdr->cEntries, pHdr->fFeatures)); 169 170 ShClPayloadFree(pPayload); 171 } 172 173 ShClEventRelease(pEvent); 174 pEvent = NULL; 175 } 176 177 LogFlowFuncLeaveRC(rc); 178 return rc; 179 } 180 181 /** 182 * Reads a root list entry from the guest, asynchronous version. 183 * 184 * @returns VBox status code. 185 * @param pClient Client to read from. 186 * @param idTransfer Transfer ID to read root list header for. 187 * @param idxEntry Index of entry to read. 188 * @param ppEvent Where to return the event to wait for. 189 * Must be released by the caller with ShClEventRelease(). 190 */ 191 int ShClSvcTransferGHRootListReadEntryAsync(PSHCLCLIENT pClient, SHCLTRANSFERID idTransfer, uint64_t idxEntry, 192 PSHCLEVENT *ppEvent) 193 { 194 LogFlowFuncEnter(); 195 196 PSHCLCLIENTMSG pMsgEntry = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_ENTRY_READ, 197 VBOX_SHCL_CPARMS_ROOT_LIST_ENTRY_READ_REQ); 198 199 PSHCLEVENT pEvent; 200 int rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvent); 201 if (RT_SUCCESS(rc)) 202 { 203 HGCMSvcSetU64(&pMsgEntry->aParms[0], 204 VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uClientID, idTransfer, pEvent->idEvent)); 205 HGCMSvcSetU32(&pMsgEntry->aParms[1], 0 /* fFeatures */); 206 HGCMSvcSetU64(&pMsgEntry->aParms[2], idxEntry /* uIndex */); 207 208 shClSvcClientLock(pClient); 209 210 shClSvcMsgAdd(pClient, pMsgEntry, true /* fAppend */); 211 rc = shClSvcClientWakeup(pClient); 212 213 shClSvcClientUnlock(pClient); 214 215 /* Remove event from list if caller did not request event handle or in case 216 * of failure (in this case caller should not release event). */ 217 if ( RT_FAILURE(rc) 218 || !ppEvent) 219 { 220 ShClEventRelease(pEvent); 221 pEvent = NULL; 222 } 223 else if (ppEvent) 224 *ppEvent = pEvent; 225 } 226 else 227 rc = VERR_NO_MEMORY; 228 229 LogFlowFuncLeave(); 230 return rc; 231 } 232 233 /** 234 * Reads a root list entry from the guest. 235 * 236 * @returns VBox status code. 237 * @param pClient Client to read from. 238 * @param idTransfer Transfer ID to read root list header for. 239 * @param idxEntry Index of entry to read. 240 * @param ppListEntry Where to return the allocated root list entry. 241 */ 242 int ShClSvcTransferGHRootListReadEntry(PSHCLCLIENT pClient, SHCLTRANSFERID idTransfer, uint64_t idxEntry, 243 PSHCLLISTENTRY *ppListEntry) 244 { 245 AssertPtrReturn(ppListEntry, VERR_INVALID_POINTER); 246 247 PSHCLEVENT pEvent; 248 int rc = ShClSvcTransferGHRootListReadEntryAsync(pClient, idTransfer, idxEntry, &pEvent); 249 if (RT_SUCCESS(rc)) 250 { 251 PSHCLEVENTPAYLOAD pPayload; 252 rc = ShClEventWait(pEvent, SHCL_TIMEOUT_DEFAULT_MS, &pPayload); 253 if (RT_SUCCESS(rc)) 254 { 255 *ppListEntry = (PSHCLLISTENTRY)pPayload->pvData; /* ppLisEntry own pPayload-pvData now. */ 256 257 } 258 259 ShClEventRelease(pEvent); 260 pEvent = NULL; 261 } 262 263 LogFlowFuncLeaveRC(rc); 264 return rc; 92 265 } 93 266 … … 98 271 99 272 /** @copydoc SHCLTXPROVIDERIFACE::pfnRootListRead */ 100 DECLCALLBACK(int) shClSvcTransferIface RootListRead(PSHCLTXPROVIDERCTX pCtx)273 DECLCALLBACK(int) shClSvcTransferIfaceGHRootListRead(PSHCLTXPROVIDERCTX pCtx) 101 274 { 102 275 LogFlowFuncEnter(); … … 105 278 AssertPtr(pClient); 106 279 107 int rc; 108 109 PSHCLCLIENTMSG pMsgHdr = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_HDR_READ, 110 VBOX_SHCL_CPARMS_ROOT_LIST_HDR_READ_REQ); 111 if (pMsgHdr) 112 { 113 PSHCLEVENT pEvent; 114 rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvent); 115 if (RT_SUCCESS(rc)) 116 { 117 HGCMSvcSetU64(&pMsgHdr->aParms[0], VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID, 118 pCtx->pTransfer->State.uID, pEvent->idEvent)); 119 HGCMSvcSetU32(&pMsgHdr->aParms[1], 0 /* fRoots */); 120 121 shClSvcClientLock(pClient); 122 123 shClSvcMsgAdd(pClient, pMsgHdr, true /* fAppend */); 124 rc = shClSvcClientWakeup(pClient); 125 126 shClSvcClientUnlock(pClient); 127 280 SHCLTRANSFERID const idTransfer = ShClTransferGetID(pCtx->pTransfer); 281 282 SHCLLISTHDR Hdr; 283 int rc = ShClSvcTransferGHRootListReadHdr(pClient, idTransfer, &Hdr); 284 if (RT_SUCCESS(rc)) 285 { 286 for (uint64_t i = 0; i < Hdr.cEntries; i++) 287 { 288 PSHCLLISTENTRY pEntry; 289 rc = ShClSvcTransferGHRootListReadEntry(pClient, idTransfer, i, &pEntry); 128 290 if (RT_SUCCESS(rc)) 129 { 130 PSHCLEVENTPAYLOAD pPayloadHdr; 131 rc = ShClEventWait(pEvent, pCtx->pTransfer->uTimeoutMs, &pPayloadHdr); 132 if (RT_SUCCESS(rc)) 133 { 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++) 140 { 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); 146 if (RT_SUCCESS(rc)) 147 { 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; 174 } 175 else 176 { 177 shClSvcMsgFree(pClient, pMsgEntry); 178 rc = VERR_SHCLPB_MAX_EVENTS_REACHED; 179 } 180 181 if (RT_FAILURE(rc)) 182 break; 183 } 184 185 ShClPayloadFree(pPayloadHdr); 186 } 187 } 188 189 ShClEventRelease(pEvent); 190 } 191 else 192 { 193 shClSvcMsgFree(pClient, pMsgHdr); 194 rc = VERR_SHCLPB_MAX_EVENTS_REACHED; 195 } 196 } 197 else 198 rc = VERR_NO_MEMORY; 291 rc = ShClTransferListAddEntry(&pCtx->pTransfer->lstRoots, pEntry, true /* fAppend */); 292 293 if (RT_FAILURE(rc)) 294 break; 295 } 296 } 199 297 200 298 LogFlowFuncLeave(); … … 203 301 204 302 /** @copydoc SHCLTXPROVIDERIFACE::pfnListOpen */ 205 DECLCALLBACK(int) shClSvcTransferIface ListOpen(PSHCLTXPROVIDERCTX pCtx,206 PSHCLLISTOPENPARMS pOpenParms, PSHCLLISTHANDLE phList)303 DECLCALLBACK(int) shClSvcTransferIfaceGHListOpen(PSHCLTXPROVIDERCTX pCtx, 304 PSHCLLISTOPENPARMS pOpenParms, PSHCLLISTHANDLE phList) 207 305 { 208 306 LogFlowFuncEnter(); … … 245 343 AssertPtr(pReply); 246 344 247 Assert(pReply->uType == VBOX_SHCL_ REPLYMSGTYPE_LIST_OPEN);345 Assert(pReply->uType == VBOX_SHCL_TX_REPLYMSGTYPE_LIST_OPEN); 248 346 249 347 LogFlowFunc(("hList=%RU64\n", pReply->u.ListOpen.uHandle)); … … 272 370 273 371 /** @copydoc SHCLTXPROVIDERIFACE::pfnListClose */ 274 DECLCALLBACK(int) shClSvcTransferIface ListClose(PSHCLTXPROVIDERCTX pCtx, SHCLLISTHANDLE hList)372 DECLCALLBACK(int) shClSvcTransferIfaceGHListClose(PSHCLTXPROVIDERCTX pCtx, SHCLLISTHANDLE hList) 275 373 { 276 374 LogFlowFuncEnter(); … … 327 425 328 426 /** @copydoc SHCLTXPROVIDERIFACE::pfnListHdrRead */ 329 DECLCALLBACK(int) shClSvcTransferIface ListHdrRead(PSHCLTXPROVIDERCTX pCtx,330 SHCLLISTHANDLE hList, PSHCLLISTHDR pListHdr)427 DECLCALLBACK(int) shClSvcTransferIfaceGHListHdrRead(PSHCLTXPROVIDERCTX pCtx, 428 SHCLLISTHANDLE hList, PSHCLLISTHDR pListHdr) 331 429 { 332 430 LogFlowFuncEnter(); … … 387 485 388 486 /** @copydoc SHCLTXPROVIDERIFACE::pfnListHdrWrite */ 389 DECLCALLBACK(int) shClSvcTransferIface ListHdrWrite(PSHCLTXPROVIDERCTX pCtx,390 SHCLLISTHANDLE hList, PSHCLLISTHDR pListHdr)487 DECLCALLBACK(int) shClSvcTransferIfaceHGListHdrWrite(PSHCLTXPROVIDERCTX pCtx, 488 SHCLLISTHANDLE hList, PSHCLLISTHDR pListHdr) 391 489 { 392 490 RT_NOREF(pCtx, hList, pListHdr); … … 398 496 399 497 /** @copydoc SHCLTXPROVIDERIFACE::pfnListEntryRead */ 400 DECLCALLBACK(int) shClSvcTransferIface ListEntryRead(PSHCLTXPROVIDERCTX pCtx,401 SHCLLISTHANDLE hList, PSHCLLISTENTRY pListEntry)498 DECLCALLBACK(int) shClSvcTransferIfaceGHListEntryRead(PSHCLTXPROVIDERCTX pCtx, 499 SHCLLISTHANDLE hList, PSHCLLISTENTRY pListEntry) 402 500 { 403 501 LogFlowFuncEnter(); … … 458 556 459 557 /** @copydoc SHCLTXPROVIDERIFACE::pfnListEntryWrite */ 460 DECLCALLBACK(int) shClSvcTransferIface ListEntryWrite(PSHCLTXPROVIDERCTX pCtx,461 SHCLLISTHANDLE hList, PSHCLLISTENTRY pListEntry)558 DECLCALLBACK(int) shClSvcTransferIfaceHGListEntryWrite(PSHCLTXPROVIDERCTX pCtx, 559 SHCLLISTHANDLE hList, PSHCLLISTENTRY pListEntry) 462 560 { 463 561 RT_NOREF(pCtx, hList, pListEntry); … … 469 567 470 568 /** @copydoc SHCLTXPROVIDERIFACE::pfnObjOpen */ 471 DECLCALLBACK(int) shClSvcTransferIface ObjOpen(PSHCLTXPROVIDERCTX pCtx, PSHCLOBJOPENCREATEPARMS pCreateParms, PSHCLOBJHANDLE phObj)569 DECLCALLBACK(int) shClSvcTransferIfaceGHObjOpen(PSHCLTXPROVIDERCTX pCtx, PSHCLOBJOPENCREATEPARMS pCreateParms, PSHCLOBJHANDLE phObj) 472 570 { 473 571 LogFlowFuncEnter(); … … 514 612 AssertPtr(pReply); 515 613 516 Assert(pReply->uType == VBOX_SHCL_ REPLYMSGTYPE_OBJ_OPEN);614 Assert(pReply->uType == VBOX_SHCL_TX_REPLYMSGTYPE_OBJ_OPEN); 517 615 518 616 LogFlowFunc(("hObj=%RU64\n", pReply->u.ObjOpen.uHandle)); … … 540 638 541 639 /** @copydoc SHCLTXPROVIDERIFACE::pfnObjClose */ 542 DECLCALLBACK(int) shClSvcTransferIface ObjClose(PSHCLTXPROVIDERCTX pCtx, SHCLOBJHANDLE hObj)640 DECLCALLBACK(int) shClSvcTransferIfaceGHObjClose(PSHCLTXPROVIDERCTX pCtx, SHCLOBJHANDLE hObj) 543 641 { 544 642 LogFlowFuncEnter(); … … 579 677 AssertPtr(pReply); 580 678 581 Assert(pReply->uType == VBOX_SHCL_ REPLYMSGTYPE_OBJ_CLOSE);679 Assert(pReply->uType == VBOX_SHCL_TX_REPLYMSGTYPE_OBJ_CLOSE); 582 680 583 681 LogFlowFunc(("hObj=%RU64\n", pReply->u.ObjClose.uHandle)); … … 603 701 604 702 /** @copydoc SHCLTXPROVIDERIFACE::pfnObjRead */ 605 DECLCALLBACK(int) shClSvcTransferIface ObjRead(PSHCLTXPROVIDERCTX pCtx, SHCLOBJHANDLE hObj,606 void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbRead)703 DECLCALLBACK(int) shClSvcTransferIfaceGHObjRead(PSHCLTXPROVIDERCTX pCtx, SHCLOBJHANDLE hObj, 704 void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbRead) 607 705 { 608 706 LogFlowFuncEnter(); … … 672 770 673 771 /** @copydoc SHCLTXPROVIDERIFACE::pfnObjWrite */ 674 DECLCALLBACK(int) shClSvcTransferIface ObjWrite(PSHCLTXPROVIDERCTX pCtx, SHCLOBJHANDLE hObj,675 void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbWritten)772 DECLCALLBACK(int) shClSvcTransferIfaceHGObjWrite(PSHCLTXPROVIDERCTX pCtx, SHCLOBJHANDLE hObj, 773 void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbWritten) 676 774 { 677 775 LogFlowFuncEnter(); … … 851 949 switch (pReply->uType) 852 950 { 853 case VBOX_SHCL_ REPLYMSGTYPE_TRANSFER_STATUS:951 case VBOX_SHCL_TX_REPLYMSGTYPE_TRANSFER_STATUS: 854 952 { 855 953 if (cParms > idxParm) … … 860 958 } 861 959 862 case VBOX_SHCL_ REPLYMSGTYPE_LIST_OPEN:960 case VBOX_SHCL_TX_REPLYMSGTYPE_LIST_OPEN: 863 961 { 864 962 if (cParms > idxParm) … … 869 967 } 870 968 871 case VBOX_SHCL_ REPLYMSGTYPE_LIST_CLOSE:969 case VBOX_SHCL_TX_REPLYMSGTYPE_LIST_CLOSE: 872 970 { 873 971 if (cParms > idxParm) … … 878 976 } 879 977 880 case VBOX_SHCL_ REPLYMSGTYPE_OBJ_OPEN:978 case VBOX_SHCL_TX_REPLYMSGTYPE_OBJ_OPEN: 881 979 { 882 980 if (cParms > idxParm) … … 887 985 } 888 986 889 case VBOX_SHCL_ REPLYMSGTYPE_OBJ_CLOSE:987 case VBOX_SHCL_TX_REPLYMSGTYPE_OBJ_CLOSE: 890 988 { 891 989 if (cParms > idxParm) … … 1249 1347 * @returns VBox status code. 1250 1348 * @param pClient Pointer to associated client. 1251 * @param pTransfer Pointer to transfer to handle guest reply for.1349 * @param idTransfer Transfer ID supplied from the guest. 1252 1350 * @param cParms Number of function parameters supplied. 1253 1351 * @param aParms Array function parameters supplied. 1254 1352 */ 1255 static int shClSvcTransferHandleReply(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer, 1256 uint32_t cParms, VBOXHGCMSVCPARM aParms[]) 1257 { 1258 RT_NOREF(pClient, pTransfer); 1259 1353 static int shClSvcTransferHandleReply(PSHCLCLIENT pClient, SHCLTRANSFERID idTransfer, uint32_t cParms, VBOXHGCMSVCPARM aParms[]) 1354 { 1260 1355 int rc; 1356 1357 PSHCLTRANSFER pTransfer = NULL; 1261 1358 1262 1359 uint32_t cbReply = sizeof(SHCLREPLY); … … 1267 1364 if (RT_SUCCESS(rc)) 1268 1365 { 1366 if ( pReply->uType == VBOX_SHCL_TX_REPLYMSGTYPE_TRANSFER_STATUS 1367 && pReply->u.TransferStatus.uStatus == SHCLTRANSFERSTATUS_REQUESTED) 1368 { 1369 /* SHCLTRANSFERSTATUS_REQUESTED is special, as it doesn't provide a transfer ID. */ 1370 } 1371 else /* Everything else needs a valid transfer ID. */ 1372 { 1373 pTransfer = ShClTransferCtxGetTransferById(&pClient->Transfers.Ctx, idTransfer); 1374 if (!pTransfer) 1375 { 1376 LogRel2(("Shared Clipboard: Transfer with ID %RU16 not found\n", idTransfer)); 1377 rc = VERR_SHCLPB_TRANSFER_ID_NOT_FOUND; 1378 } 1379 } 1380 1381 if (RT_FAILURE(rc)) 1382 { 1383 RTMemFree(pReply); 1384 pReply = NULL; 1385 1386 return rc; 1387 } 1388 1269 1389 PSHCLEVENTPAYLOAD pPayload 1270 1390 = (PSHCLEVENTPAYLOAD)RTMemAlloc(sizeof(SHCLEVENTPAYLOAD)); … … 1276 1396 switch (pReply->uType) 1277 1397 { 1278 case VBOX_SHCL_ REPLYMSGTYPE_TRANSFER_STATUS:1398 case VBOX_SHCL_TX_REPLYMSGTYPE_TRANSFER_STATUS: 1279 1399 { 1280 LogRel(("Shared Clipboard: Guest reported status %s for transfer %RU32\n", 1281 ShClTransferStatusToStr(pReply->u.TransferStatus.uStatus), pTransfer->State.uID)); 1400 /* SHCLTRANSFERSTATUS_REQUESTED is special, as it doesn't provide a transfer ID. */ 1401 if (SHCLTRANSFERSTATUS_REQUESTED == pReply->u.TransferStatus.uStatus) 1402 { 1403 LogRel2(("Shared Clipboard: Guest requested a new host -> guest transfer\n")); 1404 } 1405 else 1406 LogRel2(("Shared Clipboard: Guest reported status %s for transfer %RU32\n", 1407 ShClTransferStatusToStr(pReply->u.TransferStatus.uStatus), idTransfer)); 1282 1408 1283 1409 switch (pReply->u.TransferStatus.uStatus) 1284 1410 { 1285 case SHCLTRANSFERSTATUS_INITIALIZED: /* Initialized -> Started */ 1286 rc = shClSvcTransferStart(pClient, pTransfer); 1411 case SHCLTRANSFERSTATUS_REQUESTED: /* Guest requests a H->G transfer. */ 1412 { 1413 uint32_t const uMode = ShClSvcGetMode(); 1414 if ( uMode == VBOX_SHCL_MODE_HOST_TO_GUEST 1415 || uMode == VBOX_SHCL_MODE_BIDIRECTIONAL) 1416 { 1417 /* We only create (but not initialize) the transfer here. This is the most lightweight form of 1418 * having a pending transfer around. Report back the new transfer ID to the guest then. */ 1419 if (pTransfer == NULL) /* Must not exist yet. */ 1420 { 1421 rc = ShClSvcTransferCreate(pClient, SHCLTRANSFERDIR_TO_REMOTE, SHCLSOURCE_LOCAL, 1422 NIL_SHCLTRANSFERID /* Creates a new transfer ID */, 1423 &pTransfer); 1424 if (RT_SUCCESS(rc)) 1425 { 1426 shClSvcClientLock(pClient); 1427 1428 rc = shClSvcTransferSendStatusAsyncInternal(pClient, pTransfer, 1429 SHCLTRANSFERSTATUS_REQUESTED, VINF_SUCCESS, 1430 NULL); 1431 shClSvcClientUnlock(pClient); 1432 } 1433 } 1434 else 1435 rc = VERR_WRONG_ORDER; 1436 } 1437 else 1438 rc = VERR_INVALID_PARAMETER; 1439 1287 1440 break; 1288 1289 case SHCLTRANSFERSTATUS_STARTED: 1441 } 1442 1443 case SHCLTRANSFERSTATUS_INITIALIZED: /* Guest reports the transfer as being initialized. */ 1444 { 1445 switch (ShClTransferGetDir(pTransfer)) 1446 { 1447 case SHCLTRANSFERDIR_FROM_REMOTE: /* G->H */ 1448 /* Already done locally when creating the transfer. */ 1449 break; 1450 1451 case SHCLTRANSFERDIR_TO_REMOTE: /* H->G */ 1452 { 1453 /* Initialize the transfer on the host side. */ 1454 rc = ShClSvcTransferInit(pClient, pTransfer); 1455 break; 1456 } 1457 1458 default: 1459 AssertFailed(); 1460 break; 1461 } 1462 1290 1463 break; 1464 } 1465 case SHCLTRANSFERSTATUS_STARTED: /* Guest has started the transfer on its side. */ 1466 { 1467 /* We only need to start for H->G transfers here. 1468 * For G->H transfers we start this as soon as the host clipboard requests data. */ 1469 if (ShClTransferGetDir(pTransfer) == SHCLTRANSFERDIR_TO_REMOTE) 1470 { 1471 /* Start the transfer on the host side. */ 1472 rc = ShClSvcTransferStart(pClient, pTransfer); 1473 } 1474 break; 1475 } 1476 1477 case SHCLTRANSFERSTATUS_CANCELED: 1478 RT_FALL_THROUGH(); 1479 case SHCLTRANSFERSTATUS_KILLED: 1480 { 1481 LogRel(("Shared Clipboard: Guest has %s transfer %RU32\n", 1482 pReply->uType == SHCLTRANSFERSTATUS_CANCELED ? "canceled" : "killed", pTransfer->State.uID)); 1483 1484 rc = ShClSvcTransferStop(pClient, pTransfer, false /* fWaitForGuest */); 1485 1486 /* Regardless of whether the guest was able to report back and/or stop the transfer, remove the transfer on the host 1487 * so that we don't risk of having stale transfers here. */ 1488 ShClSvcTransferDestroy(pClient, pTransfer); 1489 pTransfer = NULL; 1490 break; 1491 } 1492 1493 case SHCLTRANSFERSTATUS_STOPPED: 1494 { 1495 LogRel(("Shared Clipboard: Guest has stopped transfer %RU32\n", pTransfer->State.uID)); 1496 1497 rc = ShClSvcTransferStop(pClient, pTransfer, false /* fWaitForGuest */); 1498 break; 1499 } 1291 1500 1292 1501 case SHCLTRANSFERSTATUS_ERROR: … … 1294 1503 LogRel(("Shared Clipboard: Guest reported error %Rrc for transfer %RU32\n", 1295 1504 pReply->rc, pTransfer->State.uID)); 1296 1297 rc = shClSvcTransferStop(pClient, pTransfer, false /* fWaitForGuest */); 1505 RT_FALL_THROUGH(); 1506 } 1507 default: 1508 { 1509 /* Regardless of whether the guest was able to report back and/or stop the transfer, remove the transfer on the host 1510 * so that we don't risk of having stale transfers here. */ 1511 ShClSvcTransferDestroy(pClient, pTransfer); 1512 pTransfer = NULL; 1298 1513 break; 1299 1514 } 1300 1301 default:1302 rc = shClSvcTransferStop(pClient, pTransfer, true /* fWaitForGuest */);1303 break;1304 1515 } 1516 1517 /* Tell the backend. */ 1518 int rc2 = ShClBackendTransferHandleStatusReply(pClient->pBackend, pClient, pTransfer, 1519 SHCLSOURCE_REMOTE, pReply->u.TransferStatus.uStatus, 1520 pReply->rc); 1521 if (RT_SUCCESS(rc)) 1522 rc = rc2; 1305 1523 1306 1524 RT_FALL_THROUGH(); 1307 1525 } 1308 case VBOX_SHCL_ REPLYMSGTYPE_LIST_OPEN:1526 case VBOX_SHCL_TX_REPLYMSGTYPE_LIST_OPEN: 1309 1527 RT_FALL_THROUGH(); 1310 case VBOX_SHCL_ REPLYMSGTYPE_LIST_CLOSE:1528 case VBOX_SHCL_TX_REPLYMSGTYPE_LIST_CLOSE: 1311 1529 RT_FALL_THROUGH(); 1312 case VBOX_SHCL_ REPLYMSGTYPE_OBJ_OPEN:1530 case VBOX_SHCL_TX_REPLYMSGTYPE_OBJ_OPEN: 1313 1531 RT_FALL_THROUGH(); 1314 case VBOX_SHCL_ REPLYMSGTYPE_OBJ_CLOSE:1532 case VBOX_SHCL_TX_REPLYMSGTYPE_OBJ_CLOSE: 1315 1533 { 1316 1534 uint64_t uCID; … … 1391 1609 int rc = VERR_INVALID_PARAMETER; /* Play safe by default. */ 1392 1610 1611 if (cParms < 1) 1612 return rc; 1613 ASSERT_GUEST_RETURN(aParms[0].type == VBOX_HGCM_SVC_PARM_64BIT, VERR_WRONG_PARAMETER_TYPE); 1614 1615 uint64_t uCID = 0; /* Context ID */ 1616 rc = HGCMSvcGetU64(&aParms[0], &uCID); 1617 if (RT_FAILURE(rc)) 1618 return rc; 1619 1620 const SHCLTRANSFERID idTransfer = VBOX_SHCL_CONTEXTID_GET_TRANSFER(uCID); 1621 1393 1622 /* 1394 1623 * Pre-check: For certain messages we need to make sure that a (right) transfer is present. 1395 1624 */ 1396 uint64_t uCID = 0; /* Context ID */1397 1625 PSHCLTRANSFER pTransfer = NULL; 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 1404 1626 switch (u32Function) 1405 1627 { 1628 case VBOX_SHCL_GUEST_FN_REPLY: 1629 /* Function does its own lookup. */ 1630 break; 1631 1406 1632 default: 1407 1633 { 1408 if (!ShClTransferCtxGetTotalTransfers(&pClient->Transfers.Ctx)) 1409 { 1410 LogFunc(("No transfers found\n")); 1411 rc = VERR_SHCLPB_TRANSFER_ID_NOT_FOUND; 1412 break; 1413 } 1414 1415 if (cParms < 1) 1416 break; 1417 1418 ASSERT_GUEST_RETURN(aParms[0].type == VBOX_HGCM_SVC_PARM_64BIT, VERR_WRONG_PARAMETER_TYPE); 1419 1420 rc = HGCMSvcGetU64(&aParms[0], &uCID); 1421 if (RT_FAILURE(rc)) 1422 break; 1423 1424 const SHCLTRANSFERID uTransferID = VBOX_SHCL_CONTEXTID_GET_TRANSFER(uCID); 1425 1426 pTransfer = ShClTransferCtxGetTransferById(&pClient->Transfers.Ctx, uTransferID); 1634 pTransfer = ShClTransferCtxGetTransferById(&pClient->Transfers.Ctx, idTransfer); 1427 1635 if (!pTransfer) 1428 1636 { 1429 Log Func(("Transfer with ID %RU16 not found\n", uTransferID));1637 LogRel(("Shared Clipboard: Transfer with ID %RU16 not found\n", idTransfer)); 1430 1638 rc = VERR_SHCLPB_TRANSFER_ID_NOT_FOUND; 1431 1639 } … … 1443 1651 case VBOX_SHCL_GUEST_FN_REPLY: 1444 1652 { 1445 rc = shClSvcTransferHandleReply(pClient, pTransfer, cParms, aParms);1653 rc = shClSvcTransferHandleReply(pClient, idTransfer, cParms, aParms); 1446 1654 break; 1447 1655 } … … 1458 1666 && ShClTransferGetDir(pTransfer) == SHCLTRANSFERDIR_TO_REMOTE) 1459 1667 { 1460 /* Get roots if this is a local write transfer (host -> guest). */ 1461 rc = ShClBackendTransferGetRoots(pClient->pBackend, pClient, pTransfer); 1668 rc = ShClBackendTransferHGRootListRead(pClient->pBackend, pClient, pTransfer); 1669 if (RT_FAILURE(rc)) 1670 break; 1462 1671 } 1463 1672 else … … 1473 1682 HGCMSvcSetU32(&aParms[1], rootListHdr.fFeatures); 1474 1683 HGCMSvcSetU64(&aParms[2], rootListHdr.cEntries); 1475 1476 rc = VINF_SUCCESS;1477 1684 break; 1478 1685 } … … 1830 2037 } 1831 2038 2039 /* If anything wrong has happened, make sure to unregister the transfer again (if not done already) and tell the guest. */ 2040 if ( RT_FAILURE(rc) 2041 && pTransfer) 2042 { 2043 shClSvcClientLock(pClient); 2044 2045 /* Let the guest know. */ 2046 int rc2 = shClSvcTransferSendStatusAsyncInternal(pClient, pTransfer, 2047 SHCLTRANSFERSTATUS_ERROR, rc, NULL /* ppEvent */); 2048 AssertRC(rc2); 2049 2050 ShClSvcTransferDestroy(pClient, pTransfer); 2051 2052 shClSvcClientUnlock(pClient); 2053 } 2054 1832 2055 LogFlowFunc(("[Client %RU32] Returning rc=%Rrc\n", pClient->State.uClientID, rc)); 1833 2056 return rc; … … 1879 2102 break; 1880 2103 } 2104 2105 LogFlowFuncLeaveRC(rc); 2106 return rc; 2107 } 2108 2109 /** 2110 * Reports a transfer status to the guest. 2111 * 2112 * @returns VBox status code. 2113 * @param pClient Client that owns the transfer. 2114 * @param idTransfer Transfer ID to report status for. 2115 * @param enmDir Transfer direction to report status for. 2116 * @param uStatus Status to report. 2117 * @param rcTransfer Result code to report. Optional and depending on status. 2118 * @param ppEvent Where to return the wait event on success. Optional. 2119 * Must be released by the caller with ShClEventRelease(). 2120 * 2121 * @note Caller must enter the client's critical section. 2122 */ 2123 static int shClSvcTransferSendStatusExAsync(PSHCLCLIENT pClient, SHCLTRANSFERID idTransfer, SHCLTRANSFERDIR enmDir, SHCLTRANSFERSTATUS uStatus, 2124 int rcTransfer, PSHCLEVENT *ppEvent) 2125 { 2126 AssertPtrReturn(pClient, VERR_INVALID_POINTER); 2127 AssertReturn(idTransfer != NIL_SHCLTRANSFERID, VERR_INVALID_PARAMETER); 2128 /* ppEvent is optional. */ 2129 2130 PSHCLCLIENTMSG pMsgReadData = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_TRANSFER_STATUS, 2131 VBOX_SHCL_CPARMS_TRANSFER_STATUS); 2132 if (!pMsgReadData) 2133 return VERR_NO_MEMORY; 2134 2135 PSHCLEVENT pEvent; 2136 int rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvent); 2137 if (RT_SUCCESS(rc)) 2138 { 2139 HGCMSvcSetU64(&pMsgReadData->aParms[0], VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID, idTransfer, pEvent->idEvent)); 2140 HGCMSvcSetU32(&pMsgReadData->aParms[1], enmDir); 2141 HGCMSvcSetU32(&pMsgReadData->aParms[2], uStatus); 2142 HGCMSvcSetU32(&pMsgReadData->aParms[3], (uint32_t)rcTransfer); /** @todo uint32_t vs. int. */ 2143 HGCMSvcSetU32(&pMsgReadData->aParms[4], 0 /* fFlags, unused */); 2144 2145 shClSvcMsgAdd(pClient, pMsgReadData, true /* fAppend */); 2146 2147 rc = shClSvcClientWakeup(pClient); 2148 if (RT_SUCCESS(rc)) 2149 { 2150 LogRel2(("Shared Clipboard: Reported status %s (rc=%Rrc) of transfer %RU32 to guest\n", 2151 ShClTransferStatusToStr(uStatus), rcTransfer, idTransfer)); 2152 2153 if (ppEvent) 2154 { 2155 *ppEvent = pEvent; /* Takes ownership. */ 2156 } 2157 else /* If event is not consumed by the caller, release the event again. */ 2158 ShClEventRelease(pEvent); 2159 } 2160 else 2161 ShClEventRelease(pEvent); 2162 } 2163 else 2164 rc = VERR_SHCLPB_MAX_EVENTS_REACHED; 2165 2166 if (RT_FAILURE(rc)) 2167 LogRel(("Shared Clipboard: Reporting status %s (%Rrc) for transfer %RU32 to guest failed with %Rrc\n", 2168 ShClTransferStatusToStr(uStatus), rcTransfer, idTransfer, rc)); 1881 2169 1882 2170 LogFlowFuncLeaveRC(rc); … … 1895 2183 * Must be released by the caller with ShClEventRelease(). 1896 2184 * 1897 * @note Caller must enter critical section.1898 */ 1899 int shClSvcTransferSendStatus(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer, SHCLTRANSFERSTATUS uStatus,1900 int rcTransfer, PSHCLEVENT *ppEvent)2185 * @note Caller must enter the client's critical section. 2186 */ 2187 static int shClSvcTransferSendStatusAsyncInternal(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer, SHCLTRANSFERSTATUS uStatus, 2188 int rcTransfer, PSHCLEVENT *ppEvent) 1901 2189 { 1902 2190 AssertPtrReturn(pClient, VERR_INVALID_POINTER); … … 1904 2192 /* ppEvent is optional. */ 1905 2193 1906 PSHCLCLIENTMSG pMsgReadData = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_TRANSFER_STATUS, 1907 VBOX_SHCL_CPARMS_TRANSFER_STATUS); 1908 if (!pMsgReadData) 1909 return VERR_NO_MEMORY; 1910 1911 PSHCLEVENT pEvent; 1912 int rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvent); 1913 if (RT_SUCCESS(rc)) 1914 { 1915 HGCMSvcSetU64(&pMsgReadData->aParms[0], VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID, 1916 pTransfer->State.uID, pEvent->idEvent)); 1917 HGCMSvcSetU32(&pMsgReadData->aParms[1], pTransfer->State.enmDir); 1918 HGCMSvcSetU32(&pMsgReadData->aParms[2], uStatus); 1919 HGCMSvcSetU32(&pMsgReadData->aParms[3], (uint32_t)rcTransfer); /** @todo uint32_t vs. int. */ 1920 HGCMSvcSetU32(&pMsgReadData->aParms[4], 0 /* fFlags, unused */); 1921 1922 shClSvcMsgAdd(pClient, pMsgReadData, true /* fAppend */); 1923 1924 rc = shClSvcClientWakeup(pClient); 1925 if (RT_SUCCESS(rc)) 1926 { 1927 LogRel2(("Shared Clipboard: Reported status %s (rc=%Rrc) of transfer %RU32 to guest\n", 1928 ShClTransferStatusToStr(uStatus), rcTransfer, pTransfer->State.uID)); 1929 1930 if (ppEvent) 1931 { 1932 *ppEvent = pEvent; /* Takes ownership. */ 1933 } 1934 else /* If event is not consumed by the caller, release the event again. */ 1935 ShClEventRelease(pEvent); 1936 } 1937 else 1938 ShClEventRelease(pEvent); 1939 } 1940 else 1941 rc = VERR_SHCLPB_MAX_EVENTS_REACHED; 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 1947 LogFlowFuncLeaveRC(rc); 1948 return rc; 1949 } 1950 1951 /** 1952 * Cleans up (unregisters and destroys) all transfers not in the 'started' state (anymore). 2194 return shClSvcTransferSendStatusExAsync(pClient, ShClTransferGetID(pTransfer), ShClTransferGetDir(pTransfer), 2195 uStatus, rcTransfer, ppEvent); 2196 } 2197 2198 int ShClSvcTransferSendStatusAsync(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer, SHCLTRANSFERSTATUS uStatus, 2199 int rcTransfer, PSHCLEVENT *ppEvent) 2200 { 2201 shClSvcClientLock(pClient); 2202 2203 int rc = shClSvcTransferSendStatusAsyncInternal(pClient, pTransfer, uStatus, rcTransfer, ppEvent); 2204 2205 shClSvcClientUnlock(pClient); 2206 2207 return rc; 2208 } 2209 2210 /** 2211 * Cleans up (unregisters and destroys) all transfers not in started state (anymore). 1953 2212 * 1954 2213 * @param pClient Client to clean up transfers for. … … 1956 2215 * @note Caller needs to take the critical section. 1957 2216 */ 1958 void shClSvcTransferCleanupAllUnused(PSHCLCLIENT pClient) 1959 { 2217 static void shClSvcTransferCleanupAllUnused(PSHCLCLIENT pClient) 2218 { 2219 Assert(RTCritSectIsOwner(&pClient->CritSect)); 2220 1960 2221 LogFlowFuncEnter(); 1961 2222 1962 2223 PSHCLTRANSFERCTX pTxCtx = &pClient->Transfers.Ctx; 1963 2224 1964 /* Remove all transfers which are not in a running state (e.g. only announced). */1965 2225 PSHCLTRANSFER pTransfer, pTransferNext; 1966 2226 RTListForEachSafe(&pTxCtx->List, pTransfer, pTransferNext, SHCLTRANSFER, Node) 1967 2227 { 1968 if (ShClTransferGetStatus(pTransfer) != SHCLTRANSFERSTATUS_STARTED) 2228 SHCLTRANSFERSTATUS const enmSts = ShClTransferGetStatus(pTransfer); 2229 if (enmSts != SHCLTRANSFERSTATUS_STARTED) 1969 2230 { 1970 2231 /* Let the guest know. */ 1971 int rc2 = shClSvcTransferSendStatus (pClient, pTransfer,1972 SHCLTRANSFERSTATUS_UNINITIALIZED, VINF_SUCCESS, NULL /* ppEvent */);2232 int rc2 = shClSvcTransferSendStatusAsyncInternal(pClient, pTransfer, 2233 SHCLTRANSFERSTATUS_UNINITIALIZED, VINF_SUCCESS, NULL /* ppEvent */); 1973 2234 AssertRC(rc2); 1974 2235 1975 ShClTransferCtx TransferUnregisterById(pTxCtx, pTransfer->State.uID);2236 ShClTransferCtxUnregisterById(pTxCtx, pTransfer->State.uID); 1976 2237 1977 2238 ShClTransferDestroy(pTransfer); … … 1984 2245 1985 2246 /** 1986 * Initializes a new transfer and sends the status to the guest. 1987 * 1988 * @note Assumes that the client's critical section is taken. 2247 * Creates a new transfer on the host. 1989 2248 * 1990 2249 * @returns VBox status code. 1991 2250 * @param pClient Client that owns the transfer. 1992 * @param enmDir Transfer direction to start. 1993 * @param enmSource Transfer source to start. 1994 * @param ppTransfer Where to return the created transfer on success. Optional. 1995 */ 1996 int shClSvcTransferInit(PSHCLCLIENT pClient, 1997 SHCLTRANSFERDIR enmDir, SHCLSOURCE enmSource, 1998 PSHCLTRANSFER *ppTransfer) 1999 { 2000 Assert(RTCritSectIsOwner(&pClient->CritSect)); 2001 2251 * @param enmDir Transfer direction to create. 2252 * @param enmSource Transfer source to create. 2253 * @param idTransfer Transfer ID to use for creation. 2254 * If set to NIL_SHCLTRANSFERID, a new transfer ID will be created. 2255 * @param ppTransfer Where to return the created transfer on success. Optional and can be NULL. 2256 */ 2257 int ShClSvcTransferCreate(PSHCLCLIENT pClient, SHCLTRANSFERDIR enmDir, SHCLSOURCE enmSource, SHCLTRANSFERID idTransfer, PSHCLTRANSFER *ppTransfer) 2258 { 2002 2259 AssertPtrReturn(pClient, VERR_INVALID_POINTER); 2003 2260 /* ppTransfer is optional. */ … … 2005 2262 LogFlowFuncEnter(); 2006 2263 2264 shClSvcClientLock(pClient); 2265 2266 /* When creating a new transfer, this is a good time to clean up old stuff we don't need anymore. */ 2007 2267 shClSvcTransferCleanupAllUnused(pClient); 2008 2268 2269 PSHCLTRANSFER pTransfer; 2270 int rc = ShClTransferCreate(enmDir, enmSource, &pTransfer); 2271 if (RT_SUCCESS(rc)) 2272 { 2273 if (idTransfer == NIL_SHCLTRANSFERID) 2274 rc = ShClTransferCtxRegister(&pClient->Transfers.Ctx, pTransfer, &idTransfer); 2275 else 2276 rc = ShClTransferCtxRegisterById(&pClient->Transfers.Ctx, pTransfer, idTransfer); 2277 if (RT_SUCCESS(rc)) 2278 { 2279 if (ppTransfer) 2280 *ppTransfer = pTransfer; 2281 } 2282 } 2283 2284 shClSvcClientUnlock(pClient); 2285 2286 if (RT_FAILURE(rc)) 2287 { 2288 ShClTransferDestroy(pTransfer); 2289 2290 RTMemFree(pTransfer); 2291 pTransfer = NULL; 2292 } 2293 2294 if (RT_FAILURE(rc)) 2295 LogRel(("Shared Clipboard: Creating transfer failed with %Rrc\n", rc)); 2296 2297 LogFlowFuncLeaveRC(rc); 2298 return rc; 2299 } 2300 2301 /** 2302 * Destroys a transfer on the host. 2303 * 2304 * @param pClient Client to destroy transfer for. 2305 * @param pTransfer Transfer to destroy. 2306 * The pointer will be invalid after return. 2307 */ 2308 void ShClSvcTransferDestroy(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer) 2309 { 2310 if (!pTransfer) 2311 return; 2312 2313 LogFlowFuncEnter(); 2314 2009 2315 PSHCLTRANSFERCTX pTxCtx = &pClient->Transfers.Ctx; 2010 2316 2317 ShClTransferCtxUnregisterById(pTxCtx, pTransfer->State.uID); 2318 2319 ShClTransferDestroy(pTransfer); 2320 2321 RTMemFree(pTransfer); 2322 pTransfer = NULL; 2323 2324 LogFlowFuncLeave(); 2325 } 2326 2327 /** 2328 * Initializes a (created) transfer on the host. 2329 * 2330 * @returns VBox status code. 2331 * @param pClient Client that owns the transfer. 2332 * @param pTransfer Transfer to initialize. 2333 */ 2334 int ShClSvcTransferInit(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer) 2335 { 2336 AssertPtrReturn(pClient, VERR_INVALID_POINTER); 2337 2338 LogFlowFuncEnter(); 2339 2340 shClSvcClientLock(pClient); 2341 2342 Assert(ShClTransferGetStatus(pTransfer) == SHCLTRANSFERSTATUS_NONE); 2343 2344 PSHCLTRANSFERCTX pTxCtx = &pClient->Transfers.Ctx; 2345 2011 2346 int rc; 2012 2347 2013 if (!ShClTransferCtxTransfersMaximumReached(pTxCtx)) 2014 { 2348 if (!ShClTransferCtxIsMaximumReached(pTxCtx)) 2349 { 2350 SHCLTRANSFERDIR const enmDir = ShClTransferGetDir(pTransfer); 2351 2015 2352 LogRel2(("Shared Clipboard: Initializing %s transfer ...\n", 2016 2353 enmDir == SHCLTRANSFERDIR_FROM_REMOTE ? "guest -> host" : "host -> guest")); 2017 2354 2018 PSHCLTRANSFER pTransfer; 2019 rc = ShClTransferCreate(&pTransfer); 2020 if (RT_SUCCESS(rc)) 2021 { 2022 SHCLTXPROVIDER Provider; 2023 RT_ZERO(Provider); 2024 2025 /* Assign local provider first and overwrite interface methods below if needed. */ 2026 VBClTransferProviderLocalQueryInterface(&Provider); 2027 2028 if (enmDir == SHCLTRANSFERDIR_FROM_REMOTE) /* Guest -> Host. */ 2029 { 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; 2040 } 2041 else if (enmDir == SHCLTRANSFERDIR_TO_REMOTE) /* Host -> Guest. */ 2042 { 2043 Provider.Interface.pfnListHdrWrite = shClSvcTransferIfaceListHdrWrite; 2044 Provider.Interface.pfnListEntryWrite = shClSvcTransferIfaceListEntryWrite; 2045 Provider.Interface.pfnObjWrite = shClSvcTransferIfaceObjWrite; 2046 } 2047 else 2048 AssertFailed(); 2049 2050 Provider.enmSource = pClient->State.enmSource; 2051 Provider.pvUser = pClient; 2052 2053 rc = ShClTransferSetProvider(pTransfer, &Provider); 2355 SHCLTXPROVIDER Provider; 2356 RT_ZERO(Provider); 2357 2358 /* Assign local provider first and overwrite interface methods below if needed. */ 2359 ShClTransferProviderLocalQueryInterface(&Provider); 2360 2361 if (enmDir == SHCLTRANSFERDIR_FROM_REMOTE) /* Guest -> Host. */ 2362 { 2363 Provider.Interface.pfnRootListRead = shClSvcTransferIfaceGHRootListRead; 2364 2365 Provider.Interface.pfnListOpen = shClSvcTransferIfaceGHListOpen; 2366 Provider.Interface.pfnListClose = shClSvcTransferIfaceGHListClose; 2367 Provider.Interface.pfnListHdrRead = shClSvcTransferIfaceGHListHdrRead; 2368 Provider.Interface.pfnListEntryRead = shClSvcTransferIfaceGHListEntryRead; 2369 2370 Provider.Interface.pfnObjOpen = shClSvcTransferIfaceGHObjOpen; 2371 Provider.Interface.pfnObjClose = shClSvcTransferIfaceGHObjClose; 2372 Provider.Interface.pfnObjRead = shClSvcTransferIfaceGHObjRead; 2373 } 2374 else if (enmDir == SHCLTRANSFERDIR_TO_REMOTE) /* Host -> Guest. */ 2375 { 2376 Provider.Interface.pfnListHdrWrite = shClSvcTransferIfaceHGListHdrWrite; 2377 Provider.Interface.pfnListEntryWrite = shClSvcTransferIfaceHGListEntryWrite; 2378 Provider.Interface.pfnObjWrite = shClSvcTransferIfaceHGObjWrite; 2379 } 2380 else 2381 AssertFailed(); 2382 2383 Provider.enmSource = pClient->State.enmSource; 2384 Provider.pvUser = pClient; 2385 2386 rc = ShClTransferSetProvider(pTransfer, &Provider); 2387 if (RT_SUCCESS(rc)) 2388 { 2389 ShClTransferSetCallbacks(pTransfer, &pClient->Transfers.Callbacks); 2390 2391 rc = ShClTransferInit(pTransfer); 2054 2392 if (RT_SUCCESS(rc)) 2055 2393 { 2056 ShClTransferSetCallbacks(pTransfer, &pClient->Transfers.Callbacks); 2057 2058 rc = ShClTransferInit(pTransfer, enmDir, enmSource); 2059 if (RT_SUCCESS(rc)) 2060 { 2061 SHCLTRANSFERID uTransferID = 0; 2062 rc = ShClTransferCtxTransferRegister(pTxCtx, pTransfer, &uTransferID); 2063 if (RT_SUCCESS(rc)) 2064 { 2065 rc = ShClBackendTransferCreate(pClient->pBackend, pClient, pTransfer); 2066 if (RT_SUCCESS(rc)) 2067 { 2068 /* Tell the guest that we've initialized the transfer locally. */ 2069 rc = shClSvcTransferSendStatus(pClient, pTransfer, 2070 SHCLTRANSFERSTATUS_INITIALIZED, VINF_SUCCESS, NULL /* ppEvent */); 2071 } 2072 } 2073 2074 if (RT_FAILURE(rc)) 2075 ShClTransferCtxTransferUnregisterById(pTxCtx, uTransferID); 2076 } 2077 } 2078 2079 if (RT_FAILURE(rc)) 2080 { 2081 ShClBackendTransferDestroy(pClient->pBackend, pClient, pTransfer); 2082 ShClTransferDestroy(pTransfer); 2083 2084 RTMemFree(pTransfer); 2085 pTransfer = NULL; 2086 } 2087 else 2088 { 2089 if (ppTransfer) 2090 *ppTransfer = pTransfer; 2091 } 2092 } 2093 2094 if (RT_FAILURE(rc)) 2095 LogRel(("Shared Clipboard: Starting transfer failed with %Rrc\n", rc)); 2394 /* Sanity: Make sure that the transfer we're gonna report as INITIALIZED to the guest 2395 * actually has some root entries set, as the guest can query for those at any time then. */ 2396 if (enmDir == SHCLTRANSFERDIR_TO_REMOTE) 2397 AssertMsgStmt(ShClTransferRootsCount(pTransfer), ("Transfer has no root entries set\n"), rc = VERR_WRONG_ORDER); 2398 } 2399 } 2096 2400 } 2097 2401 else 2098 2402 rc = VERR_SHCLPB_MAX_TRANSFERS_REACHED; 2099 2403 2404 /* Tell the guest the outcome. */ 2405 int rc2 = shClSvcTransferSendStatusAsyncInternal(pClient, pTransfer, 2406 RT_SUCCESS(rc) 2407 ? SHCLTRANSFERSTATUS_INITIALIZED : SHCLTRANSFERSTATUS_ERROR, rc, 2408 NULL /* ppEvent */); 2409 if (RT_SUCCESS(rc)) 2410 rc2 = rc; 2411 2412 if (RT_FAILURE(rc)) 2413 LogRel(("Shared Clipboard: Initializing transfer failed with %Rrc\n", rc)); 2414 2415 shClSvcClientUnlock(pClient); 2416 2100 2417 LogFlowFuncLeaveRC(rc); 2101 2418 return rc; … … 2107 2424 * @returns VBox status code. 2108 2425 * @param pClient Client that owns the transfer. 2109 * @param pTransfer Transfer to st op.2110 */ 2111 int shClSvcTransferStart(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer)2426 * @param pTransfer Transfer to start. 2427 */ 2428 int ShClSvcTransferStart(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer) 2112 2429 { 2113 2430 LogRel2(("Shared Clipboard: Starting transfer %RU32 ...\n", pTransfer->State.uID)); … … 2119 2436 /* Let the guest know in any case 2120 2437 * (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 */); 2438 int rc2 = shClSvcTransferSendStatusAsyncInternal(pClient, pTransfer, 2439 RT_SUCCESS(rc) ? SHCLTRANSFERSTATUS_STARTED : SHCLTRANSFERSTATUS_ERROR, rc, 2440 NULL /* ppEvent */); 2123 2441 if (RT_SUCCESS(rc)) 2124 2442 rc = rc2; … … 2136 2454 * @param fWaitForGuest Set to \c true to wait for acknowledgement from guest, or \c false to skip waiting. 2137 2455 */ 2138 int shClSvcTransferStop(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer, bool fWaitForGuest)2456 int ShClSvcTransferStop(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer, bool fWaitForGuest) 2139 2457 { 2140 2458 LogRel2(("Shared Clipboard: Stopping transfer %RU32 ...\n", pTransfer->State.uID)); … … 2143 2461 2144 2462 PSHCLEVENT pEvent; 2145 int rc = shClSvcTransferSendStatus (pClient, pTransfer,2146 SHCLTRANSFERSTATUS_STOPPED, VINF_SUCCESS, &pEvent);2463 int rc = shClSvcTransferSendStatusAsyncInternal(pClient, pTransfer, 2464 SHCLTRANSFERSTATUS_STOPPED, VINF_SUCCESS, &pEvent); 2147 2465 if ( RT_SUCCESS(rc) 2148 2466 && fWaitForGuest) … … 2165 2483 pTransfer->State.uID, rc)); 2166 2484 2167 /* Regardless of whether the guest was able to report back and/or stop the transfer, remove the transfer on the host2168 * so that we don't risk of having stale transfers here. */2169 int rc2 = ShClTransferCtxTransferUnregisterById(&pClient->Transfers.Ctx, ShClTransferGetID(pTransfer));2170 if (RT_SUCCESS(rc2))2171 {2172 ShClBackendTransferDestroy(pClient->pBackend, pClient, pTransfer);2173 ShClTransferDestroy(pTransfer);2174 pTransfer = NULL;2175 }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 2485 shClSvcClientUnlock(pClient); 2185 2486 … … 2213 2514 AssertPtr(pClient); 2214 2515 2215 shClSvc ClientTransfersReset(pClient);2516 shClSvcTransferDestroyAll(pClient); 2216 2517 2217 2518 ++itClient; -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-transfers.h
r98103 r100367 32 32 #endif 33 33 34 int shClSvcTransferModeSet(uint32_t fMode); 35 int ShClSvcTransferCreate(PSHCLCLIENT pClient, SHCLTRANSFERDIR enmDir, SHCLSOURCE enmSource, SHCLTRANSFERID idTransfer, PSHCLTRANSFER *ppTransfer); 36 void ShClSvcTransferDestroy(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer); 37 int ShClSvcTransferInit(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer); 38 int ShClSvcTransferStart(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer); 39 int ShClSvcTransferStop(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer, bool fWaitForGuest); 40 int ShClSvcTransferSendStatusAsync(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer, SHCLTRANSFERSTATUS uStatus, int rcTransfer, PSHCLEVENT *ppEvent); 41 int ShClSvcTransferRootListReadFromGuest(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer); 42 bool shClSvcTransferMsgIsAllowed(uint32_t uMode, uint32_t uMsg); 43 void shClSvcTransferDestroyAll(PSHCLCLIENT pClient); 44 34 45 #endif /* !VBOX_INCLUDED_SRC_SharedClipboard_VBoxSharedClipboardSvc_transfers_h */ 35 46 -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-win.cpp
r100205 r100367 166 166 LogFlowFunc(("uFmt=%#x\n", uFmt)); 167 167 168 int rc; 169 170 PSHCLEVENT pEvent; 171 rc = ShClSvcReadDataFromGuestAsync(pCtx->pClient, uFmt, &pEvent); 172 if (RT_SUCCESS(rc)) 173 { 174 PSHCLEVENTPAYLOAD pPayload; 175 rc = ShClEventWait(pEvent, SHCL_TIMEOUT_DEFAULT_MS, &pPayload); 176 if (RT_SUCCESS(rc)) 177 { 178 if (ppvData) 179 *ppvData = pPayload ? pPayload->pvData : NULL; 180 if (pcbData) 181 *pcbData = pPayload ? pPayload->cbData : 0; 182 } 183 184 ShClEventRelease(pEvent); 185 } 186 168 int rc = ShClSvcReadDataFromGuest(pCtx->pClient, uFmt, &pEvent); 187 169 if (RT_FAILURE(rc)) 188 170 LogRel(("Shared Clipboard: Reading guest clipboard data for Windows host failed with %Rrc\n", rc)); … … 231 213 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 232 214 /** 233 * @copydoc SHCLTRANSFERCALLBACKS::pfnOn Start234 * 235 * Called on transfer start to notify the "in-flight" IDataObject about a startedtransfer.215 * @copydoc SHCLTRANSFERCALLBACKS::pfnOnInitialized 216 * 217 * Called on transfer intialization to notify the "in-flight" IDataObject about a data transfer. 236 218 * 237 219 * @thread Service main thread. 238 220 */ 239 static DECLCALLBACK(void) vboxClipboardSvcWinTransfer StartedCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx)221 static DECLCALLBACK(void) vboxClipboardSvcWinTransferInitializedCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx) 240 222 { 241 223 PSHCLCONTEXT pCtx = (PSHCLCONTEXT)pCbCtx->pvUser; … … 259 241 SharedClipboardWinDataObject *pObj = pCtx->Win.pDataObjInFlight; 260 242 AssertPtrReturnVoid(pObj); 261 rc = pObj->Set AndStartTransfer(pTransfer);243 rc = pObj->SetTransfer(pTransfer); 262 244 263 245 pCtx->Win.pDataObjInFlight = NULL; /* Hand off to Windows. */ … … 272 254 273 255 LogFlowFunc(("LEAVE: idTransfer=%RU32, rc=%Rrc\n", ShClTransferGetID(pTransfer), rc)); 256 } 257 258 /** 259 * @copydoc SHCLTRANSFERCALLBACKS::pfnOnDestroy 260 * 261 * @thread Service main thread. 262 */ 263 static DECLCALLBACK(void) vboxClipboardSvcWinTransferDestroyCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx) 264 { 265 PSHCLCONTEXT pCtx = (PSHCLCONTEXT)pCbCtx->pvUser; 266 AssertPtr(pCtx); 267 268 PSHCLTRANSFER pTransfer = pCbCtx->pTransfer; 269 AssertPtr(pTransfer); 270 271 SharedClipboardWinTransferDestroy(&pCtx->Win, pTransfer); 272 } 273 274 /** 275 * @copydoc SHCLTRANSFERCALLBACKS::pfnOnStarted 276 * 277 * @thread Service main thread. 278 */ 279 static DECLCALLBACK(void) vboxClipboardSvcWinTransferStartedCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx) 280 { 281 PSHCLCONTEXT pCtx = (PSHCLCONTEXT)pCbCtx->pvUser; 282 AssertPtr(pCtx); 283 284 PSHCLTRANSFER pTransfer = pCbCtx->pTransfer; 285 AssertPtr(pTransfer); 286 287 if (ShClTransferGetDir(pTransfer) == SHCLTRANSFERDIR_FROM_REMOTE) /* G->H */ 288 { 289 /* Report to the guest that we now entered the STARTED state. */ 290 ShClSvcTransferStart(pCtx->pClient, pTransfer); 291 } 274 292 } 275 293 #endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */ … … 385 403 void *pvData = NULL; 386 404 uint32_t cbData = 0; 387 int rc = vboxClipboardSvcWinReadDataFromGuest(pCtx, uFormat, &pvData, &cbData);405 int rc = ShClSvcReadDataFromGuest(pCtx->pClient, uFormat, &pvData, &cbData); 388 406 if ( RT_SUCCESS(rc) 389 407 && pvData … … 440 458 441 459 int rc = SharedClipboardWinClearAndAnnounceFormats(pWinCtx, fFormats, hWnd); 442 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS443 if ( RT_SUCCESS(rc)444 && fFormats & VBOX_SHCL_FMT_URI_LIST)445 {446 /*447 * The host requested data from the guest as URI list.448 *449 * This means on Windows we450 * - need to first create an own IDataObject and push it on the clipboard451 * - register a transfer locally so that we have a valid ID for it452 *453 * That way Windows will recognize that there is a data transfer "in flight".454 *455 * As soon as the user requests to "paste" the data (transfer), the IDataObject will try to read data via456 * the pfnOnRequestDataFromSource callback.457 */458 SHCLCALLBACKS Callbacks;459 RT_ZERO(Callbacks);460 Callbacks.pfnOnRequestDataFromSource = vboxClipboardSvcWinRequestDataFromSourceCallback;461 462 rc = SharedClipboardWinTransferCreateAndSetDataObject(pWinCtx, pCtx, &Callbacks);463 }464 #endif465 460 if (RT_FAILURE(rc)) 466 461 LogRel(("Shared Clipboard: Reporting clipboard formats %#x to Windows host failed with %Rrc\n", fFormats, rc)); … … 739 734 */ 740 735 RT_ZERO(pClient->Transfers.Callbacks); 741 pClient->Transfers.Callbacks.pfnOnStarted = vboxClipboardSvcWinTransferStartedCallback; 736 pClient->Transfers.Callbacks.pfnOnInitialized = vboxClipboardSvcWinTransferInitializedCallback; 737 pClient->Transfers.Callbacks.pfnOnStarted = vboxClipboardSvcWinTransferStartedCallback; 738 pClient->Transfers.Callbacks.pfnOnDestroy = vboxClipboardSvcWinTransferDestroyCallback; 742 739 743 740 pClient->Transfers.Callbacks.pvUser = pCtx; /* Assign context as user-provided callback data. */ … … 973 970 974 971 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 975 int ShClBackendTransferCreate(PSHCLBACKEND pBackend, PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer) 976 { 977 RT_NOREF(pBackend, pClient, pTransfer); 978 979 LogFlowFuncEnter(); 980 981 return VINF_SUCCESS; 982 } 983 984 int ShClBackendTransferDestroy(PSHCLBACKEND pBackend, PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer) 985 { 986 RT_NOREF(pBackend); 987 988 LogFlowFuncEnter(); 989 990 SharedClipboardWinTransferDestroy(&pClient->State.pCtx->Win, pTransfer); 991 992 return VINF_SUCCESS; 993 } 994 995 int ShClBackendTransferGetRoots(PSHCLBACKEND pBackend, PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer) 972 int ShClBackendTransferHGRootListRead(PSHCLBACKEND pBackend, PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer) 996 973 { 997 974 RT_NOREF(pBackend); -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-x11.cpp
r100237 r100367 44 44 #include <iprt/errcore.h> 45 45 46 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS _HTTP46 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 47 47 # include <VBox/GuestHost/SharedClipboard-transfers.h> 48 # ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP 49 # include <VBox/GuestHost/SharedClipboard-transfers.h> 50 # endif 48 51 #endif 49 52 50 53 #include "VBoxSharedClipboardSvc-internal.h" 54 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 55 # include "VBoxSharedClipboardSvc-transfers.h" 56 #endif 51 57 52 58 /* Number of currently extablished connections. */ … … 81 87 static DECLCALLBACK(int) shClSvcX11RequestDataFromSourceCallback(PSHCLCONTEXT pCtx, SHCLFORMAT uFmt, void **ppv, uint32_t *pcb, void *pvUser); 82 88 89 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 90 static DECLCALLBACK(void) shClSvcX11OnTransferInitCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx); 91 static DECLCALLBACK(void) shClSvcX11OnTransferDestroyCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx); 92 static DECLCALLBACK(void) shClSvcX11OnTransferUnregisteredCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx, PSHCLTRANSFERCTX pTransferCtx); 93 #endif 94 83 95 84 96 int ShClBackendInit(PSHCLBACKEND pBackend, VBOXHGCMSVCFNTABLE *pTable) … … 146 158 pClient->State.pCtx = pCtx; 147 159 pCtx->pClient = pClient; 160 161 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 162 /* 163 * Set callbacks. 164 * Those will be registered within ShClSvcTransferInit() when a new transfer gets initialized. 165 * 166 * Used for starting / stopping the HTTP server. 167 */ 168 RT_ZERO(pClient->Transfers.Callbacks); 169 170 pClient->Transfers.Callbacks.pvUser = pCtx; /* Assign context as user-provided callback data. */ 171 pClient->Transfers.Callbacks.cbUser = sizeof(SHCLCONTEXT); 172 173 pClient->Transfers.Callbacks.pfnOnInitialized = shClSvcX11OnTransferInitCallback; 174 pClient->Transfers.Callbacks.pfnOnDestroy = shClSvcX11OnTransferDestroyCallback; 175 pClient->Transfers.Callbacks.pfnOnUnregistered = shClSvcX11OnTransferUnregisteredCallback; 176 #endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */ 148 177 149 178 rc = ShClX11ThreadStart(&pCtx->X11, true /* grab shared clipboard */); … … 352 381 } 353 382 383 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 384 /** 385 * @copydoc SHCLTRANSFERCALLBACKS::pfnOnInitialized 386 * 387 * This starts the HTTP server if not done yet and registers the transfer with it. 388 * 389 * @thread Service main thread. 390 */ 391 static DECLCALLBACK(void) shClSvcX11OnTransferInitCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx) 392 { 393 RT_NOREF(pCbCtx); 394 395 #if 1 396 LogFlowFuncEnter(); 397 398 PSHCLCONTEXT pCtx = (PSHCLCONTEXT)pCbCtx->pvUser; 399 AssertPtr(pCtx); 400 401 PSHCLTRANSFER pTransfer = pCbCtx->pTransfer; 402 AssertPtr(pTransfer); 403 404 switch (ShClTransferGetDir(pTransfer)) 405 { 406 case SHCLTRANSFERDIR_FROM_REMOTE: /* G->H */ 407 { 408 # ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP 409 /* We only need to start the HTTP server when we actually receive data from the remote (host). */ 410 ShClTransferHttpServerMaybeStart(&pCtx->X11.HttpCtx); 411 # endif 412 break; 413 } 414 415 case SHCLTRANSFERDIR_TO_REMOTE: /* H->G */ 416 { 417 PSHCLEVENT pEvent; 418 int rc = ShClEventSourceGenerateAndRegisterEvent(&pCtx->pClient->EventSrc, &pEvent); 419 if (RT_SUCCESS(rc)) 420 { 421 rc = ShClX11ReadDataFromX11Async(&pCtx->X11, VBOX_SHCL_FMT_URI_LIST, UINT32_MAX, pEvent); 422 if (RT_SUCCESS(rc)) 423 { 424 /* X supplies the data asynchronously, so we need to wait for data to arrive first. */ 425 PSHCLEVENTPAYLOAD pPayload; 426 rc = ShClEventWait(pEvent, SHCL_TIMEOUT_DEFAULT_MS, &pPayload); 427 if (RT_SUCCESS(rc)) 428 { 429 if (pPayload) 430 { 431 Assert(pPayload->cbData == sizeof(SHCLX11RESPONSE)); 432 AssertPtr(pPayload->pvData); 433 PSHCLX11RESPONSE pResp = (PSHCLX11RESPONSE)pPayload->pvData; 434 435 rc = ShClTransferRootsInitFromStringList(pTransfer, 436 (char *)pResp->Read.pvData, pResp->Read.cbData + 1 /* Include zero terminator */); 437 //if (RT_SUCCESS(rc)) 438 // rc = ShClTransferRootListRead(pTransfer); 439 440 if (RT_SUCCESS(rc)) 441 LogRel2(("Shared Clipboard: Host reported %RU64 X11 root entries for transfer to guest\n", ShClTransferRootsCount(pTransfer))); 442 443 RTMemFree(pResp->Read.pvData); 444 pResp->Read.cbData = 0; 445 446 ShClPayloadFree(pPayload); 447 pPayload = NULL; 448 } 449 else 450 rc = VERR_NO_DATA; /* No payload. */ 451 } 452 } 453 454 ShClEventRelease(pEvent); 455 } 456 else 457 rc = VERR_SHCLPB_MAX_EVENTS_REACHED; 458 break; 459 } 460 461 default: 462 break; 463 } 464 465 LogFlowFuncLeave(); 466 } 467 468 /** 469 * @copydoc SHCLTRANSFERCALLBACKS::pfnOnDestroy 470 * 471 * This stops the HTTP server if not done yet. 472 * 473 * @thread Service main thread. 474 */ 475 static DECLCALLBACK(void) shClSvcX11OnTransferDestroyCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx) 476 { 477 LogFlowFuncEnter(); 478 479 # ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP 480 PSHCLCONTEXT pCtx = (PSHCLCONTEXT)pCbCtx->pvUser; 481 AssertPtr(pCtx); 482 483 PSHCLTRANSFER pTransfer = pCbCtx->pTransfer; 484 AssertPtr(pTransfer); 485 486 if (ShClTransferGetDir(pTransfer) == SHCLTRANSFERDIR_FROM_REMOTE) 487 ShClTransferHttpServerMaybeStop(&pCtx->X11.HttpCtx); 488 # else 489 RT_NOREF(pCbCtx); 490 # endif 491 492 LogFlowFuncLeave(); 493 } 494 495 /** 496 * Unregisters a transfer from a HTTP server. 497 * 498 * This also stops the HTTP server if no active transfers are found anymore. 499 * 500 * @param pCtx Shared clipboard context to unregister transfer for. 501 * @param pTransfer Transfer to unregister. 502 * 503 * @thread Clipboard main thread. 504 */ 505 static void shClSvcX11HttpTransferUnregister(PSHCLCONTEXT pCtx, PSHCLTRANSFER pTransfer) 506 { 507 if (ShClTransferGetDir(pTransfer) == SHCLTRANSFERDIR_FROM_REMOTE) 508 { 509 # ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP 510 if (ShClTransferHttpServerIsInitialized(&pCtx->X11.HttpCtx.HttpServer)) 511 { 512 ShClTransferHttpServerUnregisterTransfer(&pCtx->X11.HttpCtx.HttpServer, pTransfer); 513 ShClTransferHttpServerMaybeStop(&pCtx->X11.HttpCtx); 514 } 515 # else 516 RT_NOREF(pCtx); 517 # endif 518 } 519 520 //ShClTransferRelease(pTransfer); 521 } 522 523 /** 524 * @copydoc SHCLTRANSFERCALLBACKS::pfnOnUnregistered 525 * 526 * Unregisters a (now) unregistered transfer from the HTTP server. 527 * 528 * @thread Clipboard main thread. 529 */ 530 static DECLCALLBACK(void) shClSvcX11OnTransferUnregisteredCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx, PSHCLTRANSFERCTX pTransferCtx) 531 { 532 RT_NOREF(pTransferCtx); 533 shClSvcX11HttpTransferUnregister((PSHCLCONTEXT)pCbCtx->pvUser, pCbCtx->pTransfer); 534 } 535 #endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */ 536 354 537 /** 355 538 * @copydoc SHCLCALLBACKS::pfnOnRequestDataFromSource … … 373 556 } 374 557 375 int rc = VINF_SUCCESS; 376 377 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP 558 PSHCLCLIENT const pClient = pCtx->pClient; 559 int rc = ShClSvcReadDataFromGuest(pClient, uFmt, ppv, pcb); 560 if (RT_FAILURE(rc)) 561 return rc; 562 378 563 /* 379 * Note: We always return a generic URI list here.564 * Note: We always return a generic URI list (as HTTP links) here. 380 565 * As we don't know which Atom target format was requested by the caller, the X11 clipboard codes needs 381 566 * to decide & transform the list into the actual clipboard Atom target format the caller wanted. 382 567 */ 568 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 383 569 if (uFmt == VBOX_SHCL_FMT_URI_LIST) 384 570 { 385 PSHCLTRANSFER pTransfer = ShClTransferHttpServerGetTransferFirst(&pCtx->X11.HttpCtx.HttpServer); 386 if (pTransfer) 387 { 388 if (RT_SUCCESS(rc)) 389 rc = ShClTransferRootListRead(pTransfer); 390 } 391 392 /** @todo BUGBUG IMPLEMENT THIS! */ 393 394 *ppv = NULL; 395 *pcb = 0; 396 397 rc = VERR_NO_DATA; 398 } 399 #endif 400 401 if (RT_SUCCESS(rc)) 402 { 403 /* Request data from the guest and for data to arrive. */ 404 PSHCLEVENT pEvent; 405 rc = ShClSvcReadDataFromGuestAsync(pCtx->pClient, uFmt, &pEvent); 571 PSHCLTRANSFER pTransfer; 572 rc = ShClSvcTransferCreate(pClient, SHCLTRANSFERDIR_FROM_REMOTE, SHCLSOURCE_REMOTE, 573 NIL_SHCLTRANSFERID /* Creates a new transfer ID */, &pTransfer); 406 574 if (RT_SUCCESS(rc)) 407 575 { 408 PSHCLEVENTPAYLOAD pPayload; 409 rc = ShClEventWait(pEvent, SHCL_TIMEOUT_DEFAULT_MS, &pPayload); 576 /* Initialize the transfer on the host side. */ 577 rc = ShClSvcTransferInit(pClient, pTransfer); 578 if (RT_FAILURE(rc)) 579 ShClSvcTransferDestroy(pClient, pTransfer); 580 } 581 582 if (RT_SUCCESS(rc)) 583 { 584 /* We have to wait for the guest reporting the transfer as being initialized. 585 * Only then we can start reading stuff. */ 586 rc = ShClTransferWaitForStatus(pTransfer, SHCL_TIMEOUT_DEFAULT_MS, SHCLTRANSFERSTATUS_INITIALIZED); 410 587 if (RT_SUCCESS(rc)) 411 588 { 412 if ( !pPayload413 || !pPayload->cbData)589 rc = ShClTransferRootListRead(pTransfer); 590 if (RT_SUCCESS(rc)) 414 591 { 415 rc = VERR_NO_DATA; 416 } 417 else 418 { 419 *ppv = pPayload->pvData; 420 *pcb = pPayload->cbData; 592 # ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP 593 /* As soon as we register the transfer with the HTTP server, the transfer needs to have its roots set. */ 594 PSHCLHTTPSERVER const pHttpSrv = &pCtx->X11.HttpCtx.HttpServer; 595 rc = ShClTransferHttpServerRegisterTransfer(pHttpSrv, pTransfer); 596 if (RT_SUCCESS(rc)) 597 { 598 char *pszURL = ShClTransferHttpServerGetUrlA(pHttpSrv, pTransfer->State.uID); 599 if (pszURL) 600 { 601 *ppv = pszURL; 602 *pcb = strlen(pszURL) + 1 /* Include terminator */; 603 604 LogFlowFunc(("URL is '%s'\n", pszURL)); 605 606 /* ppv has ownership of pszURL. */ 607 608 rc = VINF_SUCCESS; 609 } 610 else 611 rc = VERR_NO_MEMORY; 612 } 613 # else 614 rc = VERR_NOT_SUPPORTED; 615 # endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP */ 421 616 } 422 617 } 423 424 ShClEventRelease(pEvent); 425 } 426 } 618 } 619 } 620 #endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */ 427 621 428 622 if (RT_FAILURE(rc)) 429 LogRel(("Shared Clipboard: Requesting data in format %#x for X11 host failed with %Rrc\n", uFmt, rc));623 LogRel(("Shared Clipboard: Requesting X11 data in format %#x from guest failed with %Rrc\n", uFmt, rc)); 430 624 431 625 LogFlowFuncLeaveRC(rc); … … 434 628 435 629 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 436 437 int ShClBackendTransferCreate(PSHCLBACKEND pBackend, PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer) 630 /** 631 * Handles transfer status replies from the guest. 632 */ 633 int ShClBackendTransferHandleStatusReply(PSHCLBACKEND pBackend, PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer, SHCLSOURCE enmSource, SHCLTRANSFERSTATUS enmStatus, int rcStatus) 634 { 635 RT_NOREF(pBackend, pClient, enmSource, rcStatus); 636 637 PSHCLCONTEXT pCtx = pClient->State.pCtx; RT_NOREF(pCtx); 638 639 if (ShClTransferGetDir(pTransfer) == SHCLTRANSFERDIR_FROM_REMOTE) /* Guest -> Host */ 640 { 641 switch (enmStatus) 642 { 643 case SHCLTRANSFERSTATUS_INITIALIZED: 644 { 645 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP 646 int rc2 = ShClTransferHttpServerMaybeStart(&pCtx->X11.HttpCtx); 647 if (RT_SUCCESS(rc2)) 648 { 649 650 } 651 652 if (RT_FAILURE(rc2)) 653 LogRel(("Shared Clipboard: Registering HTTP transfer failed: %Rrc\n", rc2)); 654 #endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP */ 655 break; 656 } 657 658 default: 659 break; 660 } 661 } 662 663 return VINF_SUCCESS; 664 } 665 666 int ShClBackendTransferHGRootListRead(PSHCLBACKEND pBackend, PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer) 438 667 { 439 668 RT_NOREF(pBackend); 440 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP 441 /* We only need to start the HTTP server (and register the transfer to it) when we actually receive data from the guest. */ 442 if (ShClTransferGetDir(pTransfer) == SHCLTRANSFERDIR_FROM_REMOTE)443 return ShClTransferHttpServerMaybeStart(&pClient->State.pCtx->X11.HttpCtx);669 670 #if 1 671 RT_NOREF(pClient, pTransfer); 672 int rc = 0; 444 673 #else 445 RT_NOREF(pClient, pTransfer);446 #endif447 return VINF_SUCCESS;448 }449 450 int ShClBackendTransferDestroy(PSHCLBACKEND pBackend, PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer)451 {452 RT_NOREF(pBackend);453 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP454 /* See comment in ShClBackendTransferCreate(). */455 if (ShClTransferGetDir(pTransfer) == SHCLTRANSFERDIR_FROM_REMOTE)456 return ShClTransferHttpServerMaybeStop(&pClient->State.pCtx->X11.HttpCtx);457 #else458 RT_NOREF(pClient, pTransfer);459 #endif460 return VINF_SUCCESS;461 }462 463 int ShClBackendTransferGetRoots(PSHCLBACKEND pBackend, PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer)464 {465 RT_NOREF(pBackend);466 467 674 LogFlowFuncEnter(); 468 675 … … 508 715 else 509 716 rc = VERR_SHCLPB_MAX_EVENTS_REACHED; 717 #endif 510 718 511 719 LogFlowFuncLeaveRC(rc); -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc.cpp
r100204 r100367 614 614 615 615 /* Make sure to send a quit message to the guest so that it can terminate gracefully. */ 616 RTCritSectEnter(&pClient->CritSect); 616 shClSvcClientLock(pClient); 617 617 618 if (pClient->Pending.uType) 618 619 { … … 627 628 pClient->Pending.paParms = NULL; 628 629 } 629 RTCritSectLeave(&pClient->CritSect); 630 631 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 632 shClSvcTransferDestroyAll(pClient); 633 ShClTransferCtxDestroy(&pClient->Transfers.Ctx); 634 #endif 630 635 631 636 ShClEventSourceDestroy(&pClient->EventSrc); 637 638 shClSvcClientUnlock(pClient); 632 639 633 640 shClSvcClientStateDestroy(&pClient->State); … … 635 642 PSHCLCLIENTLEGACYCID pCidIter, pCidIterNext; 636 643 RTListForEachSafe(&pClient->Legacy.lstCID, pCidIter, pCidIterNext, SHCLCLIENTLEGACYCID, Node) 637 {638 644 RTMemFree(pCidIter); 639 }640 645 641 646 int rc2 = RTCritSectDelete(&pClient->CritSect); … … 686 691 687 692 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 688 shClSvc ClientTransfersReset(pClient);693 shClSvcTransferDestroyAll(pClient); 689 694 #endif 690 695 … … 1220 1225 1221 1226 /** 1222 * Re quests to read clipboard data from the guest.1227 * Reads clipboard data from the guest, asynchronous version. 1223 1228 * 1224 1229 * @returns VBox status code. … … 1330 1335 } 1331 1336 1332 #if def VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS1337 #if 0 /* ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */ 1333 1338 /* 1334 1339 * When the host wants to read URI data from the guest: 1335 1340 * - Initialize a transfer locally. 1336 1341 * - 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. 1342 * - Start the transfer locally once we receive the transfer INITIALIZED status from the guest via VBOX_SHCL_GUEST_FN_REPLY. 1343 * 1344 * When this function returns, the X11 clipboard will try reading the data, so we need to make sure that 1345 * - the local HTTP server is up and running (will be done in ShClBackendTransferCreate() on X11) 1346 * - the right (HTTP) URL data is filled into the clipboard 1347 * by then. 1338 1348 */ 1339 1349 if ( RT_SUCCESS(rc) 1340 && fFormat == VBOX_SHCL_FMT_URI_LIST)1350 && (fFormat & VBOX_SHCL_FMT_URI_LIST)) 1341 1351 { 1342 rc = shClSvcTransferInit(pClient, SHCLTRANSFERDIR_FROM_REMOTE, SHCLSOURCE_REMOTE,1343 NULL /* pTransfer */);1352 PSHCLTRANSFER pTransfer; 1353 rc = ShClSvcTransferInit(pClient, SHCLTRANSFERDIR_FROM_REMOTE, SHCLSOURCE_REMOTE, &pTransfer); 1344 1354 if (RT_SUCCESS(rc)) 1345 1355 rc = shClSvcSetSource(pClient, SHCLSOURCE_REMOTE); … … 1381 1391 1382 1392 /** 1393 * Reads clipboard data from the guest. 1394 * 1395 * @returns VBox status code. 1396 * @param pClient Client to request to read data form. 1397 * @param fFormats The formats being requested, OR'ed together (VBOX_SHCL_FMT_XXX). 1398 * @param ppv Where to return the allocated data read. 1399 * Must be free'd by the caller. 1400 * @param pcb Where to return number of bytes read. 1401 */ 1402 int ShClSvcReadDataFromGuest(PSHCLCLIENT pClient, SHCLFORMAT fFormats, void **ppv, uint32_t *pcb) 1403 { 1404 LogFlowFuncEnter(); 1405 1406 /* Request data from the guest and wait for data to arrive. */ 1407 PSHCLEVENT pEvent; 1408 int rc = ShClSvcReadDataFromGuestAsync(pClient, fFormats, &pEvent); 1409 if (RT_SUCCESS(rc)) 1410 { 1411 PSHCLEVENTPAYLOAD pPayload; 1412 rc = ShClEventWait(pEvent, SHCL_TIMEOUT_DEFAULT_MS, &pPayload); 1413 if (RT_SUCCESS(rc)) 1414 { 1415 if ( !pPayload 1416 || !pPayload->cbData) 1417 { 1418 rc = VERR_NO_DATA; 1419 } 1420 else 1421 { 1422 *ppv = pPayload->pvData; 1423 *pcb = pPayload->cbData; 1424 } 1425 } 1426 1427 ShClEventRelease(pEvent); 1428 } 1429 1430 if (RT_FAILURE(rc)) 1431 LogRel(("Shared Clipboard: Reading data from guest failed with %Rrc\n", rc)); 1432 1433 LogFlowFuncLeaveRC(rc); 1434 return rc; 1435 } 1436 1437 /** 1383 1438 * Signals the host that clipboard data from the guest has been received. 1384 1439 * … … 1575 1630 */ 1576 1631 int rc; 1577 if (!fFormats && pClient->State.enmSource != SHCLSOURCE_REMOTE)1632 if (!fFormats) 1578 1633 rc = VINF_SUCCESS; 1579 1634 else 1580 1635 { 1581 rc = shClSvcSetSource(pClient, SHCLSOURCE_REMOTE);1636 rc = RTCritSectEnter(&g_CritSect); 1582 1637 if (RT_SUCCESS(rc)) 1583 1638 { 1584 rc = RTCritSectEnter(&g_CritSect); 1585 if (RT_SUCCESS(rc)) 1639 if (g_ExtState.pfnExtension) 1586 1640 { 1587 if (g_ExtState.pfnExtension) 1588 { 1589 SHCLEXTPARMS parms; 1590 RT_ZERO(parms); 1591 parms.uFormat = fFormats; 1592 1593 g_ExtState.pfnExtension(g_ExtState.pvExtension, VBOX_CLIPBOARD_EXT_FN_FORMAT_ANNOUNCE, &parms, sizeof(parms)); 1594 } 1595 else 1596 { 1597 #ifdef LOG_ENABLED 1598 char *pszFmts = ShClFormatsToStrA(fFormats); 1599 if (pszFmts) 1600 { 1601 LogRel2(("Shared Clipboard: Guest reported formats '%s' to host\n", pszFmts)); 1602 RTStrFree(pszFmts); 1603 } 1604 #endif 1605 rc = ShClBackendReportFormats(&g_ShClBackend, pClient, fFormats); 1606 if (RT_FAILURE(rc)) 1607 LogRel(("Shared Clipboard: Reporting guest clipboard formats to the host failed with %Rrc\n", rc)); 1608 } 1609 1610 RTCritSectLeave(&g_CritSect); 1641 SHCLEXTPARMS parms; 1642 RT_ZERO(parms); 1643 parms.uFormat = fFormats; 1644 1645 g_ExtState.pfnExtension(g_ExtState.pvExtension, VBOX_CLIPBOARD_EXT_FN_FORMAT_ANNOUNCE, &parms, sizeof(parms)); 1611 1646 } 1612 1647 else 1613 LogRel2(("Shared Clipboard: Unable to take internal lock while receiving guest clipboard announcement: %Rrc\n", rc)); 1614 } 1648 { 1649 #ifdef LOG_ENABLED 1650 char *pszFmts = ShClFormatsToStrA(fFormats); 1651 if (pszFmts) 1652 { 1653 LogRel2(("Shared Clipboard: Guest reported formats '%s' to host\n", pszFmts)); 1654 RTStrFree(pszFmts); 1655 } 1656 #endif 1657 rc = ShClBackendReportFormats(&g_ShClBackend, pClient, fFormats); 1658 if (RT_FAILURE(rc)) 1659 LogRel(("Shared Clipboard: Reporting guest clipboard formats to the host failed with %Rrc\n", rc)); 1660 } 1661 1662 RTCritSectLeave(&g_CritSect); 1663 } 1664 else 1665 LogRel2(("Shared Clipboard: Unable to take internal lock while receiving guest clipboard announcement: %Rrc\n", rc)); 1615 1666 } 1616 1667 … … 1762 1813 else 1763 1814 LogRel(("Shared Clipboard: Reading host clipboard data failed with %Rrc\n", rc)); 1764 1765 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS1766 /*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 #endif1787 1815 } 1788 1816 … … 1998 2026 } 1999 2027 2000 /**2001 * Sets the transfer source type of a Shared Clipboard client.2002 *2003 * @returns VBox status code.2004 * @param pClient Client to set transfer source type for.2005 * @param enmSource Source type to set.2006 */2007 int shClSvcSetSource(PSHCLCLIENT pClient, SHCLSOURCE enmSource)2008 {2009 if (!pClient) /* If no client connected (anymore), bail out. */2010 return VINF_SUCCESS;2011 2012 int rc = VINF_SUCCESS;2013 2014 pClient->State.enmSource = enmSource;2015 2016 LogFlowFunc(("Source of client %RU32 is now %RU32\n", pClient->State.uClientID, pClient->State.enmSource));2017 2018 LogFlowFuncLeaveRC(rc);2019 return rc;2020 }2021 2022 2028 static int svcInit(VBOXHGCMSVCFNTABLE *pTable) 2023 2029 { … … 2069 2075 g_ExtState.uClientID = 0; 2070 2076 } 2071 2072 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS2073 shClSvcClientTransfersReset(pClient);2074 #endif2075 2077 2076 2078 ShClBackendDisconnect(&g_ShClBackend, pClient); … … 2250 2252 2251 2253 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 2252 shClSvcClientTransfersReset(pClient); 2254 /* Reset transfer state. */ 2255 shClSvcTransferDestroyAll(pClient); 2253 2256 #endif 2254 2257 shClSvcClientUnlock(pClient); -
trunk/src/VBox/HostServices/SharedClipboard/testcase/tstClipboardServiceHost.cpp
r100204 r100367 330 330 331 331 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 332 int ShClBackendTransferCreate(PSHCLBACKEND, PSHCLCLIENT, PSHCLTRANSFER) { return VINF_SUCCESS; } 333 int ShClBackendTransferDestroy(PSHCLBACKEND, PSHCLCLIENT, PSHCLTRANSFER) { return VINF_SUCCESS; } 334 int ShClBackendTransferGetRoots(PSHCLBACKEND, PSHCLCLIENT, PSHCLTRANSFER) { return VINF_SUCCESS; } 332 int ShClBackendTransferHandleStatusReply(PSHCLBACKEND, PSHCLCLIENT, PSHCLTRANSFER, SHCLSOURCE, SHCLTRANSFERSTATUS, int) { return VINF_SUCCESS; } 333 int ShClBackendTransferHGRootListRead(PSHCLBACKEND, PSHCLCLIENT, PSHCLTRANSFER) { return VINF_SUCCESS; } 335 334 #endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */ 336 335 -
trunk/src/VBox/HostServices/SharedClipboard/testcase/tstClipboardTransfers.cpp
r100204 r100367 212 212 { 213 213 PSHCLTRANSFER pTransfer; 214 int rc = ShClTransferCreate( &pTransfer);214 int rc = ShClTransferCreate(SHCLTRANSFERDIR_TO_REMOTE, SHCLSOURCE_LOCAL, &pTransfer); 215 215 RTTESTI_CHECK_RC_OK(rc); 216 216 217 217 SHCLTXPROVIDER Provider; 218 RTTESTI_CHECK( VBClTransferProviderLocalQueryInterface(&Provider) != NULL);218 RTTESTI_CHECK(ShClTransferProviderLocalQueryInterface(&Provider) != NULL); 219 219 RTTESTI_CHECK_RC_OK(ShClTransferSetProvider(pTransfer, &Provider)); 220 220 … … 246 246 247 247 PSHCLTRANSFER pTransfer; 248 int rc = ShClTransferCreate( &pTransfer);248 int rc = ShClTransferCreate(SHCLTRANSFERDIR_TO_REMOTE, SHCLSOURCE_LOCAL, &pTransfer); 249 249 RTTESTI_CHECK_RC_OK(rc); 250 250 251 251 SHCLTXPROVIDER Provider; 252 VBClTransferProviderLocalQueryInterface(&Provider);252 ShClTransferProviderLocalQueryInterface(&Provider); 253 253 254 254 rc = ShClTransferSetProvider(pTransfer, &Provider); 255 255 RTTESTI_CHECK_RC_OK(rc); 256 256 257 rc = ShClTransferInit(pTransfer , SHCLTRANSFERDIR_FROM_REMOTE, SHCLSOURCE_LOCAL);257 rc = ShClTransferInit(pTransfer); 258 258 RTTESTI_CHECK_RC_OK(rc); 259 259 … … 309 309 RTTESTI_CHECK_RC_OK(rc); 310 310 PSHCLTRANSFER pTransfer; 311 rc = ShClTransferCreate( &pTransfer);311 rc = ShClTransferCreate(SHCLTRANSFERDIR_TO_REMOTE, SHCLSOURCE_LOCAL, &pTransfer); 312 312 RTTESTI_CHECK_RC_OK(rc); 313 313 rc = ShClTransferDestroy(pTransfer); … … 318 318 PSHCLLIST pList = ShClTransferListAlloc(); 319 319 RTTESTI_CHECK(pList != NULL); 320 rc = ShClTransferCreate( &pTransfer);320 rc = ShClTransferCreate(SHCLTRANSFERDIR_TO_REMOTE, SHCLSOURCE_LOCAL, &pTransfer); 321 321 RTTESTI_CHECK_RC_OK(rc); 322 322 ShClTransferListFree(pList);
Note:
See TracChangeset
for help on using the changeset viewer.