Changeset 79497 in vbox for trunk/src/VBox
- Timestamp:
- Jul 3, 2019 1:28:33 PM (6 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 4 deleted
- 20 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxClipboard.cpp
r79366 r79497 32 32 33 33 #include <VBox/GuestHost/SharedClipboard.h> 34 #include <VBox/HostServices/VBoxClipboardSvc.h> /* Temp, remove. */ 34 35 #include <VBox/GuestHost/SharedClipboard-win.h> 35 36 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 36 # include <VBox/GuestHost/SharedClipboard-uri.h>37 # include <VBox/GuestHost/SharedClipboard-uri.h> 37 38 #endif 38 39 … … 41 42 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 42 43 /** !!! HACK ALERT !!! Dynamically resolve functions! */ 43 # ifdef _WIN32_IE44 # undef _WIN32_IE45 # define _WIN32_IE 0x050146 # endif47 # include <iprt/win/shlobj.h>48 # include <iprt/win/shlwapi.h>44 # ifdef _WIN32_IE 45 # undef _WIN32_IE 46 # define _WIN32_IE 0x0501 47 # endif 48 # include <iprt/win/shlobj.h> 49 # include <iprt/win/shlwapi.h> 49 50 #endif 50 51 … … 54 55 *********************************************************************************************************************************/ 55 56 56 struct _VBOXCLIPBOARDCONTEXT57 typedef struct _VBOXCLIPBOARDCONTEXT 57 58 { 58 59 /** Pointer to the VBoxClient service environment. */ … … 66 67 SHAREDCLIPBOARDURICTX URI; 67 68 #endif 68 }; 69 } VBOXCLIPBOARDCONTEXT, *PVBOXCLIPBOARDCONTEXT; 70 71 typedef struct _VBOXCLIPBOARDWRITETHREADCTX 72 { 73 PVBOXCLIPBOARDCONTEXT pClipboardCtx; 74 PSHAREDCLIPBOARDURITRANSFER pTransfer; 75 char *papszURIList; 76 uint32_t cbURIList; 77 } VBOXCLIPBOARDWRITETHREADCTX, *PVBOXCLIPBOARDWRITETHREADCTX; 69 78 70 79 … … 88 97 89 98 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 99 static DECLCALLBACK(int) vboxClipboardURIWriteThread(RTTHREAD ThreadSelf, void *pvUser) 100 { 101 RT_NOREF(ThreadSelf); 102 103 LogFlowFuncEnter(); 104 105 PVBOXCLIPBOARDWRITETHREADCTX pCtx = (PVBOXCLIPBOARDWRITETHREADCTX)pvUser; 106 AssertPtr(pCtx); 107 108 RTThreadUserSignal(RTThreadSelf()); 109 110 uint32_t uClientID; 111 int rc = VbglR3ClipboardConnect(&uClientID); 112 if (RT_SUCCESS(rc)) 113 { 114 VBoxClipboardTransferReport Msg; 115 RT_ZERO(Msg); 116 117 VBGL_HGCM_HDR_INIT(&Msg.hdr, uClientID, 118 VBOX_SHARED_CLIPBOARD_GUEST_FN_TRANSFER_REPORT, VBOX_SHARED_CLIPBOARD_CPARMS_TRANSFER_REPORT); 119 120 Msg.uContext.SetUInt32(0); 121 Msg.uStatus.SetUInt32(0); 122 123 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg)); 124 125 if (RT_SUCCESS(rc)) 126 { 127 bool fTerminate = false; 128 unsigned cErrors = 0; 129 130 for (;;) 131 { 132 PVBGLR3CLIPBOARDEVENT pEvent; 133 rc = VbglR3ClipboardEventGetNext(uClientID, pCtx->pTransfer, &pEvent); 134 if (RT_SUCCESS(rc)) 135 { 136 switch (pEvent->enmType) 137 { 138 case VBGLR3CLIPBOARDEVENTTYPE_URI_LIST_HDR_READ: 139 { 140 LogFlowFunc(("VBGLR3CLIPBOARDEVENTTYPE_URI_READ_LIST_HDR\n")); 141 break; 142 } 143 144 case VBGLR3CLIPBOARDEVENTTYPE_URI_LIST_ENTRY_READ: 145 { 146 LogFlowFunc(("VBGLR3CLIPBOARDEVENTTYPE_URI_READ_LIST_ENTRY\n")); 147 break; 148 } 149 150 case VBGLR3CLIPBOARDEVENTTYPE_URI_OBJ_OPEN: 151 { 152 LogFlowFunc(("VBGLR3CLIPBOARDEVENTTYPE_URI_OBJ_OPEN\n")); 153 break; 154 } 155 156 case VBGLR3CLIPBOARDEVENTTYPE_URI_OBJ_CLOSE: 157 { 158 LogFlowFunc(("VBGLR3CLIPBOARDEVENTTYPE_URI_OBJ_CLOSE\n")); 159 break; 160 } 161 162 case VBGLR3CLIPBOARDEVENTTYPE_URI_OBJ_READ: 163 { 164 LogFlowFunc(("VBGLR3CLIPBOARDEVENTTYPE_URI_OBJ_READ\n")); 165 break; 166 } 167 168 case VBGLR3CLIPBOARDEVENTTYPE_URI_CANCEL: 169 RT_FALL_THROUGH(); 170 case VBGLR3CLIPBOARDEVENTTYPE_URI_ERROR: 171 LogFlowFunc(("VBGLR3CLIPBOARDEVENTTYPE_URI_CANCEL / ERROR\n")); 172 fTerminate = true; 173 break; 174 175 default: 176 rc = VERR_NOT_SUPPORTED; 177 cErrors++; 178 break; 179 } 180 181 VbglR3ClipboardEventFree(pEvent); 182 } 183 184 if (fTerminate) 185 break; 186 187 if (RT_FAILURE(rc)) 188 { 189 if (cErrors++ >= 3) 190 break; 191 RTThreadSleep(1000); 192 } 193 } 194 } 195 196 VbglR3ClipboardDisconnect(uClientID); 197 } 198 199 if (pCtx->papszURIList) 200 RTStrFree(pCtx->papszURIList); 201 202 RTMemFree(pCtx); 203 204 LogFlowFuncLeaveRC(rc); 205 return rc; 206 } 207 90 208 static DECLCALLBACK(void) vboxClipboardURITransferCompleteCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData, int rc) 91 209 { … … 136 254 } 137 255 138 static int vboxClipboardURIReadDataHdr(PSHAREDCLIPBOARDPROVIDERCTX pCtx, PVBOXCLIPBOARDDATAHDR *ppDataHdr) 139 { 256 static int vboxClipboardURITransferOpen(PSHAREDCLIPBOARDPROVIDERCTX pCtx) 257 { 258 RT_NOREF(pCtx); 259 260 LogFlowFuncLeave(); 261 return VINF_SUCCESS; 262 } 263 264 static int vboxClipboardURITransferClose(PSHAREDCLIPBOARDPROVIDERCTX pCtx) 265 { 266 RT_NOREF(pCtx); 267 268 LogFlowFuncLeave(); 269 return VINF_SUCCESS; 270 } 271 272 static int vboxClipboardURIListHdrRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx, VBOXCLIPBOARDLISTHANDLE hList, 273 PVBOXCLIPBOARDLISTHDR pListHdr) 274 { 275 RT_NOREF(hList); 276 140 277 LogFlowFuncEnter(); 141 278 … … 145 282 LogFlowFunc(("c=%RU32\n", pThisCtx->u32ClientID)); 146 283 147 VBOXCLIPBOARDDATAHDR dataHdr; 148 SharedClipboardURIDataHdrInit(&dataHdr); 149 150 int rc = VbglR3ClipboardReadDataHdr(pThisCtx->u32ClientID, &dataHdr); 151 if (RT_SUCCESS(rc)) 152 { 153 *ppDataHdr = SharedClipboardURIDataHdrDup(&dataHdr); 154 } 284 RT_NOREF(pListHdr); 285 int rc = 0; //VbglR3ClipboardListHdrRead(pThisCtx->u32ClientID, pListHdr); 155 286 156 287 LogFlowFuncLeaveRC(rc); … … 158 289 } 159 290 160 static int vboxClipboardURIWriteDataHdr(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const PVBOXCLIPBOARDDATAHDR pDataHdr) 291 static int vboxClipboardURIListHdrWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx, VBOXCLIPBOARDLISTHANDLE hList, 292 PVBOXCLIPBOARDLISTHDR pListHdr) 161 293 { 162 294 LogFlowFuncEnter(); … … 165 297 AssertPtr(pThisCtx); 166 298 167 int rc = VbglR3Clipboard WriteDataHdr(pThisCtx->u32ClientID, pDataHdr);299 int rc = VbglR3ClipboardSendListHdrWrite(pThisCtx->u32ClientID, hList, pListHdr); 168 300 169 301 LogFlowFuncLeaveRC(rc); … … 171 303 } 172 304 173 static int vboxClipboardURI ReadDataChunk(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const PVBOXCLIPBOARDDATAHDR pDataHdr,174 void *pvChunk, uint32_t cbChunk, uint32_t fFlags, uint32_t *pcbRead)175 { 176 RT_NOREF( fFlags);305 static int vboxClipboardURIListEntryRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx, VBOXCLIPBOARDLISTHANDLE hList, 306 PVBOXCLIPBOARDLISTENTRY pListEntry) 307 { 308 RT_NOREF(hList); 177 309 178 310 LogFlowFuncEnter(); … … 181 313 AssertPtr(pThisCtx); 182 314 183 int rc = VINF_SUCCESS; 184 185 uint32_t cbReadTotal = 0; 186 uint32_t cbToRead = RT_MIN(pDataHdr->cbMeta, cbChunk); 187 188 while (cbToRead) 189 { 190 uint32_t cbRead; 191 rc = VbglR3ClipboardReadMetaData(pThisCtx->u32ClientID, pDataHdr, (uint8_t *)pvChunk + cbReadTotal, cbToRead, &cbRead); 192 if (RT_FAILURE(rc)) 193 break; 194 195 cbReadTotal += cbRead; 196 Assert(cbToRead >= cbRead); 197 cbToRead -= cbRead; 198 } 199 200 if (RT_SUCCESS(rc)) 201 { 202 if (pcbRead) 203 *pcbRead = cbReadTotal; 204 } 315 RT_NOREF(pListEntry); 316 int rc = 0; // VbglR3ClipboardListEntryRead(pThisCtx->u32ClientID, pListEntry); 205 317 206 318 LogFlowFuncLeaveRC(rc); … … 208 320 } 209 321 210 static int vboxClipboardURIWriteDataChunk(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const PVBOXCLIPBOARDDATAHDR pDataHdr, 211 const void *pvChunk, uint32_t cbChunk, uint32_t fFlags, uint32_t *pcbWritten) 212 { 213 RT_NOREF(fFlags); 214 322 static int vboxClipboardURIListEntryWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx, VBOXCLIPBOARDLISTHANDLE hList, 323 PVBOXCLIPBOARDLISTENTRY pListEntry) 324 { 215 325 LogFlowFuncEnter(); 216 326 … … 218 328 AssertPtr(pThisCtx); 219 329 220 int rc = VINF_SUCCESS; 221 222 uint32_t cbWrittenTotal = 0; 223 uint32_t cbToWrite = RT_MIN(pDataHdr->cbMeta, cbChunk); 224 225 while (cbToWrite) 226 { 227 uint32_t cbWritten; 228 rc = VbglR3ClipboardWriteMetaData(pThisCtx->u32ClientID, pDataHdr, (uint8_t *)pvChunk + cbWrittenTotal, cbToWrite, 229 &cbWritten); 230 if (RT_FAILURE(rc)) 231 break; 232 233 cbWrittenTotal += cbWritten; 234 Assert(cbToWrite >= cbWritten); 235 cbToWrite -= cbWritten; 236 } 237 238 if (RT_SUCCESS(rc)) 239 { 240 if (pcbWritten) 241 *pcbWritten = cbWrittenTotal; 242 } 243 244 LogFlowFunc(("cbWrittenTotal=%RU32, rc=%Rrc\n", cbWrittenTotal, rc)); 330 int rc = VbglR3ClipboardSendListEntryWrite(pThisCtx->u32ClientID, hList, pListEntry); 331 332 LogFlowFuncLeaveRC(rc); 245 333 return rc; 246 334 } 247 335 248 static int vboxClipboardURIReadDir(PSHAREDCLIPBOARDPROVIDERCTX pCtx, PVBOXCLIPBOARDDIRDATA *ppDirData) 336 static int vboxClipboardURIObjOpen(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const char *pszPath, 337 PVBOXCLIPBOARDCREATEPARMS pCreateParms, PSHAREDCLIPBOARDOBJHANDLE phObj) 249 338 { 250 339 LogFlowFuncEnter(); … … 253 342 AssertPtr(pThisCtx); 254 343 255 VBOXCLIPBOARDDIRDATA dirData; 256 SharedClipboardURIDirDataInit(&dirData); 257 258 int rc = VbglR3ClipboardReadDir(pThisCtx->u32ClientID, dirData.pszPath, dirData.cbPath, &dirData.cbPath, &dirData.fMode); 259 if (RT_SUCCESS(rc)) 260 { 261 *ppDirData = SharedClipboardURIDirDataDup(&dirData); 262 } 344 int rc = VbglR3ClipboardObjOpen(pThisCtx->u32ClientID, pszPath, pCreateParms, phObj); 263 345 264 346 LogFlowFuncLeaveRC(rc); … … 266 348 } 267 349 268 static int vboxClipboardURI WriteDir(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const PVBOXCLIPBOARDDIRDATA pDirData)350 static int vboxClipboardURIObjClose(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDOBJHANDLE hObj) 269 351 { 270 352 LogFlowFuncEnter(); … … 273 355 AssertPtr(pThisCtx); 274 356 275 int rc = VbglR3Clipboard WriteDir(pThisCtx->u32ClientID, pDirData->pszPath, pDirData->cbPath, pDirData->fMode);357 int rc = VbglR3ClipboardObjClose(pThisCtx->u32ClientID, hObj); 276 358 277 359 LogFlowFuncLeaveRC(rc); … … 279 361 } 280 362 281 static int vboxClipboardURIReadFileHdr(PSHAREDCLIPBOARDPROVIDERCTX pCtx, PVBOXCLIPBOARDFILEHDR *ppFileHdr) 282 { 363 static int vboxClipboardURIObjRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDOBJHANDLE hObj, 364 void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbRead) 365 { 366 RT_NOREF(fFlags); 367 283 368 LogFlowFuncEnter(); 284 369 … … 286 371 AssertPtr(pThisCtx); 287 372 288 VBOXCLIPBOARDFILEHDR fileHdr; 289 SharedClipboardURIFileHdrInit(&fileHdr); 290 291 int rc = VbglR3ClipboardReadFileHdr(pThisCtx->u32ClientID, fileHdr.pszFilePath, fileHdr.cbFilePath, 292 &fileHdr.fFlags, &fileHdr.fMode, &fileHdr.cbSize); 293 if (RT_SUCCESS(rc)) 294 { 295 *ppFileHdr = SharedClipboardURIFileHdrDup(&fileHdr); 296 } 373 int rc = VbglR3ClipboardObjRead(pThisCtx->u32ClientID, hObj, pvData, cbData, pcbRead); 297 374 298 375 LogFlowFuncLeaveRC(rc); … … 300 377 } 301 378 302 static int vboxClipboardURIWriteFileHdr(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const PVBOXCLIPBOARDFILEHDR pFileHdr) 303 { 379 static int vboxClipboardURIObjWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDOBJHANDLE hObj, 380 void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbWritten) 381 { 382 RT_NOREF(fFlags); 383 304 384 LogFlowFuncEnter(); 305 385 … … 307 387 AssertPtr(pThisCtx); 308 388 309 int rc = VbglR3ClipboardWriteFileHdr(pThisCtx->u32ClientID, pFileHdr->pszFilePath, pFileHdr->cbFilePath, 310 pFileHdr->fFlags, pFileHdr->fMode, pFileHdr->cbSize); 311 LogFlowFuncLeaveRC(rc); 312 return rc; 313 } 314 315 static int vboxClipboardURIReadFileData(PSHAREDCLIPBOARDPROVIDERCTX pCtx, void *pvData, uint32_t cbData, uint32_t fFlags, 316 uint32_t *pcbRead) 317 { 318 RT_NOREF(fFlags); 319 320 AssertPtrReturn(pcbRead, VERR_INVALID_POINTER); 321 322 LogFlowFuncEnter(); 323 324 PVBOXCLIPBOARDCONTEXT pThisCtx = (PVBOXCLIPBOARDCONTEXT)pCtx->pvUser; 325 AssertPtr(pThisCtx); 326 327 int rc = VbglR3ClipboardReadFileData(pThisCtx->u32ClientID, pvData, cbData, pcbRead); 328 329 LogFlowFuncLeaveRC(rc); 330 return rc; 331 } 332 333 static int vboxClipboardURIWriteFileData(PSHAREDCLIPBOARDPROVIDERCTX pCtx, void *pvData, uint32_t cbData, uint32_t fFlags, 334 uint32_t *pcbWritten) 335 { 336 RT_NOREF(fFlags); 337 338 AssertPtrReturn(pcbWritten, VERR_INVALID_POINTER); 339 340 LogFlowFuncEnter(); 341 342 PVBOXCLIPBOARDCONTEXT pThisCtx = (PVBOXCLIPBOARDCONTEXT)pCtx->pvUser; 343 AssertPtr(pThisCtx); 344 345 int rc = VbglR3ClipboardWriteFileData(pThisCtx->u32ClientID, pvData, cbData, pcbWritten); 389 int rc = VbglR3ClipboardObjWrite(pThisCtx->u32ClientID, hObj, pvData, cbData, pcbWritten); 346 390 347 391 LogFlowFuncLeaveRC(rc); … … 379 423 } 380 424 } 381 break;425 break; 382 426 383 427 case WM_CHANGECBCHAIN: … … 386 430 lresultRc = VBoxClipboardWinHandleWMChangeCBChain(pWinCtx, hwnd, msg, wParam, lParam); 387 431 } 388 break;432 break; 389 433 390 434 case WM_DRAWCLIPBOARD: … … 404 448 lresultRc = VBoxClipboardWinChainPassToNext(pWinCtx, msg, wParam, lParam); 405 449 } 406 break;450 break; 407 451 408 452 case WM_TIMER: 409 453 { 410 411 454 int rc = VBoxClipboardWinHandleWMTimer(pWinCtx); 455 AssertRC(rc); 412 456 } 413 break;457 break; 414 458 415 459 case WM_CLOSE: … … 417 461 /* Do nothing. Ignore the message. */ 418 462 } 419 break;463 break; 420 464 421 465 case WM_RENDERFORMAT: … … 566 610 } 567 611 } 568 break;612 break; 569 613 570 614 case WM_RENDERALLFORMATS: … … 575 619 AssertRC(rc); 576 620 } 577 break;621 break; 578 622 579 623 case VBOX_CLIPBOARD_WM_SET_FORMATS: 580 624 { 581 582 583 584 585 586 587 588 589 590 625 LogFunc(("VBOX_CLIPBOARD_WM_SET_FORMATS\n")); 626 627 /* Announce available formats. Do not insert data -- will be inserted in WM_RENDERFORMAT. */ 628 VBOXCLIPBOARDFORMATS fFormats = (uint32_t)lParam; 629 if (fFormats != VBOX_SHARED_CLIPBOARD_FMT_NONE) /* Could arrive with some older GA versions. */ 630 { 631 int rc = VBoxClipboardWinOpen(hwnd); 632 if (RT_SUCCESS(rc)) 633 { 634 VBoxClipboardWinClear(); 591 635 592 636 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 593 if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_URI_LIST) 594 { 595 LogFunc(("VBOX_SHARED_CLIPBOARD_FMT_URI_LIST\n")); 596 597 PSHAREDCLIPBOARDURITRANSFER pTransfer; 598 rc = SharedClipboardURITransferCreate(SHAREDCLIPBOARDURITRANSFERDIR_READ, 599 SHAREDCLIPBOARDSOURCE_REMOTE, 600 &pTransfer); 601 if (RT_SUCCESS(rc)) 602 { 603 SHAREDCLIPBOARDURITRANSFERCALLBACKS TransferCallbacks; 604 RT_ZERO(TransferCallbacks); 605 606 TransferCallbacks.pvUser = &pCtx->URI; 607 TransferCallbacks.pfnTransferComplete = vboxClipboardURITransferCompleteCallback; 608 TransferCallbacks.pfnTransferError = vboxClipboardURITransferErrorCallback; 609 610 SharedClipboardURITransferSetCallbacks(pTransfer, &TransferCallbacks); 611 612 SHAREDCLIPBOARDPROVIDERCREATIONCTX creationCtx; 613 RT_ZERO(creationCtx); 614 creationCtx.enmSource = SHAREDCLIPBOARDSOURCE_REMOTE; 615 616 RT_ZERO(creationCtx.Interface); 617 creationCtx.Interface.pfnReadDataHdr = vboxClipboardURIReadDataHdr; 618 creationCtx.Interface.pfnReadDataChunk = vboxClipboardURIReadDataChunk; 619 creationCtx.Interface.pfnReadDirectory = vboxClipboardURIReadDir; 620 creationCtx.Interface.pfnReadFileHdr = vboxClipboardURIReadFileHdr; 621 creationCtx.Interface.pfnReadFileData = vboxClipboardURIReadFileData; 622 623 creationCtx.pvUser = pCtx; 624 625 rc = SharedClipboardURITransferProviderCreate(pTransfer, &creationCtx); 626 if (RT_SUCCESS(rc)) 627 { 628 rc = SharedClipboardURICtxTransferAdd(&pCtx->URI, pTransfer); 629 if (RT_SUCCESS(rc)) 630 rc = VBoxClipboardWinURITransferCreate(pWinCtx, pTransfer); 631 } 632 633 /* Note: VBoxClipboardWinURITransferCreate() takes care of closing the clipboard. */ 634 635 LogFunc(("VBOX_SHARED_CLIPBOARD_FMT_URI_LIST: rc=%Rrc\n", rc)); 636 } 637 } 638 else 639 { 637 if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_URI_LIST) 638 { 639 LogFunc(("VBOX_SHARED_CLIPBOARD_FMT_URI_LIST\n")); 640 641 PSHAREDCLIPBOARDURITRANSFER pTransfer; 642 rc = SharedClipboardURITransferCreate(SHAREDCLIPBOARDURITRANSFERDIR_READ, 643 SHAREDCLIPBOARDSOURCE_REMOTE, 644 &pTransfer); 645 if (RT_SUCCESS(rc)) 646 { 647 SHAREDCLIPBOARDURITRANSFERCALLBACKS TransferCallbacks; 648 RT_ZERO(TransferCallbacks); 649 650 TransferCallbacks.pvUser = &pCtx->URI; 651 TransferCallbacks.pfnTransferComplete = vboxClipboardURITransferCompleteCallback; 652 TransferCallbacks.pfnTransferError = vboxClipboardURITransferErrorCallback; 653 654 SharedClipboardURITransferSetCallbacks(pTransfer, &TransferCallbacks); 655 656 SHAREDCLIPBOARDPROVIDERCREATIONCTX creationCtx; 657 RT_ZERO(creationCtx); 658 creationCtx.enmSource = SHAREDCLIPBOARDSOURCE_REMOTE; 659 660 RT_ZERO(creationCtx.Interface); 661 creationCtx.Interface.pfnTransferOpen = vboxClipboardURITransferOpen; 662 creationCtx.Interface.pfnTransferClose = vboxClipboardURITransferClose; 663 creationCtx.Interface.pfnListHdrRead = vboxClipboardURIListHdrRead; 664 creationCtx.Interface.pfnListEntryRead = vboxClipboardURIListEntryRead; 665 creationCtx.Interface.pfnObjOpen = vboxClipboardURIObjOpen; 666 creationCtx.Interface.pfnObjClose = vboxClipboardURIObjClose; 667 creationCtx.Interface.pfnObjRead = vboxClipboardURIObjRead; 668 669 creationCtx.pvUser = pCtx; 670 671 rc = SharedClipboardURITransferProviderCreate(pTransfer, &creationCtx); 672 if (RT_SUCCESS(rc)) 673 { 674 rc = SharedClipboardURICtxTransferAdd(&pCtx->URI, pTransfer); 675 if (RT_SUCCESS(rc)) 676 rc = VBoxClipboardWinURITransferCreate(pWinCtx, pTransfer); 677 } 678 679 /* Note: VBoxClipboardWinURITransferCreate() takes care of closing the clipboard. */ 680 681 LogFunc(("VBOX_SHARED_CLIPBOARD_FMT_URI_LIST: rc=%Rrc\n", rc)); 682 } 683 } 684 else 685 { 640 686 #endif 641 642 643 687 rc = VBoxClipboardWinAnnounceFormats(pWinCtx, fFormats); 688 689 VBoxClipboardWinClose(); 644 690 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 645 691 } 646 692 #endif 647 648 649 650 651 break;693 } 694 } 695 LogFunc(("VBOX_CLIPBOARD_WM_SET_FORMATS: fFormats=0x%x, lastErr=%ld\n", fFormats, GetLastError())); 696 } 697 break; 652 698 653 699 case VBOX_CLIPBOARD_WM_READ_DATA: … … 721 767 } 722 768 } 723 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 724 else if (uFormat == VBOX_SHARED_CLIPBOARD_FMT_URI_LIST) 725 { 726 LogFunc(("VBOX_SHARED_CLIPBOARD_FMT_URI_LIST cTransfers=%RU32\n", 727 SharedClipboardURICtxGetRunningTransfers(&pCtx->URI))); 728 729 PSHAREDCLIPBOARDURITRANSFER pTransfer; 730 rc = SharedClipboardURITransferCreate(SHAREDCLIPBOARDURITRANSFERDIR_WRITE, 731 SHAREDCLIPBOARDSOURCE_LOCAL, 732 &pTransfer); 733 if (RT_SUCCESS(rc)) 734 { 735 SHAREDCLIPBOARDURITRANSFERCALLBACKS TransferCallbacks; 736 RT_ZERO(TransferCallbacks); 737 738 TransferCallbacks.pvUser = &pCtx->URI; 739 TransferCallbacks.pfnTransferComplete = vboxClipboardURITransferCompleteCallback; 740 TransferCallbacks.pfnTransferError = vboxClipboardURITransferErrorCallback; 741 742 SharedClipboardURITransferSetCallbacks(pTransfer, &TransferCallbacks); 743 744 SHAREDCLIPBOARDPROVIDERCREATIONCTX creationCtx; 745 RT_ZERO(creationCtx); 746 creationCtx.enmSource = SHAREDCLIPBOARDSOURCE_LOCAL; 747 748 RT_ZERO(creationCtx.Interface); 749 creationCtx.Interface.pfnWriteDataHdr = vboxClipboardURIWriteDataHdr; 750 creationCtx.Interface.pfnWriteDataChunk = vboxClipboardURIWriteDataChunk; 751 creationCtx.Interface.pfnWriteDirectory = vboxClipboardURIWriteDir; 752 creationCtx.Interface.pfnWriteFileHdr = vboxClipboardURIWriteFileHdr; 753 creationCtx.Interface.pfnWriteFileData = vboxClipboardURIWriteFileData; 754 755 creationCtx.pvUser = pCtx; 756 757 rc = SharedClipboardURITransferProviderCreate(pTransfer, &creationCtx); 758 if (RT_SUCCESS(rc)) 759 { 760 rc = SharedClipboardURICtxTransferAdd(&pCtx->URI, pTransfer); 761 if (RT_SUCCESS(rc)) 762 { 763 /* The data data in CF_HDROP format, as the files are locally present and don't need to be 764 * presented as a IDataObject or IStream. */ 765 hClip = GetClipboardData(CF_HDROP); 766 if (hClip) 767 { 768 HDROP hDrop = (HDROP)GlobalLock(hClip); 769 if (hDrop) 770 { 771 rc = VBoxClipboardWinDropFilesToTransfer((DROPFILES *)hDrop, pTransfer); 772 773 GlobalUnlock(hClip); 774 775 if (RT_SUCCESS(rc)) 776 { 777 rc = SharedClipboardURITransferPrepare(pTransfer); 778 if (RT_SUCCESS(rc)) 779 rc = SharedClipboardURITransferRun(pTransfer, true /* fAsync */); 780 } 781 } 782 else 783 { 784 hClip = NULL; 785 } 786 } 787 } 788 } 789 } 790 791 if (RT_FAILURE(rc)) 792 LogFunc(("VBOX_SHARED_CLIPBOARD_FMT_URI_LIST failed with rc=%Rrc\n", rc)); 793 } 794 #endif 769 795 770 if (hClip == NULL) 796 771 { … … 806 781 VBoxClipboardWinClose(); 807 782 } 783 break; 808 784 } 809 break; 785 786 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 787 /* The host wants to read URI data. */ 788 case VBOX_CLIPBOARD_WM_URI_START_READ: 789 { 790 LogFunc(("VBOX_CLIPBOARD_WM_URI_START_READ: cTransfersRunning=%RU32\n", 791 SharedClipboardURICtxGetRunningTransfers(&pCtx->URI))); 792 793 int rc = VBoxClipboardWinOpen(hwnd); 794 if (RT_SUCCESS(rc)) 795 { 796 PSHAREDCLIPBOARDURITRANSFER pTransfer; 797 rc = SharedClipboardURITransferCreate(SHAREDCLIPBOARDURITRANSFERDIR_WRITE, 798 SHAREDCLIPBOARDSOURCE_LOCAL, 799 &pTransfer); 800 if (RT_SUCCESS(rc)) 801 { 802 SHAREDCLIPBOARDURITRANSFERCALLBACKS TransferCallbacks; 803 RT_ZERO(TransferCallbacks); 804 805 TransferCallbacks.pvUser = &pCtx->URI; 806 TransferCallbacks.pfnTransferComplete = vboxClipboardURITransferCompleteCallback; 807 TransferCallbacks.pfnTransferError = vboxClipboardURITransferErrorCallback; 808 809 SharedClipboardURITransferSetCallbacks(pTransfer, &TransferCallbacks); 810 811 SHAREDCLIPBOARDPROVIDERCREATIONCTX creationCtx; 812 RT_ZERO(creationCtx); 813 creationCtx.enmSource = SHAREDCLIPBOARDSOURCE_LOCAL; 814 815 RT_ZERO(creationCtx.Interface); 816 creationCtx.Interface.pfnListHdrWrite = vboxClipboardURIListHdrWrite; 817 creationCtx.Interface.pfnListEntryWrite = vboxClipboardURIListEntryWrite; 818 creationCtx.Interface.pfnObjOpen = vboxClipboardURIObjOpen; 819 creationCtx.Interface.pfnObjClose = vboxClipboardURIObjClose; 820 creationCtx.Interface.pfnObjWrite = vboxClipboardURIObjWrite; 821 822 creationCtx.pvUser = pCtx; 823 824 rc = SharedClipboardURITransferProviderCreate(pTransfer, &creationCtx); 825 if (RT_SUCCESS(rc)) 826 { 827 rc = SharedClipboardURICtxTransferAdd(&pCtx->URI, pTransfer); 828 if (RT_SUCCESS(rc)) 829 { 830 /* The data data in CF_HDROP format, as the files are locally present and don't need to be 831 * presented as a IDataObject or IStream. */ 832 HANDLE hClip = hClip = GetClipboardData(CF_HDROP); 833 if (hClip) 834 { 835 HDROP hDrop = (HDROP)GlobalLock(hClip); 836 if (hDrop) 837 { 838 char *papszList; 839 uint32_t cbList; 840 rc = VBoxClipboardWinDropFilesToStringList((DROPFILES *)hDrop, &papszList, &cbList); 841 if (RT_SUCCESS(rc)) 842 { 843 PVBOXCLIPBOARDWRITETHREADCTX pThreadCtx 844 = (PVBOXCLIPBOARDWRITETHREADCTX)RTMemAllocZ(sizeof(VBOXCLIPBOARDWRITETHREADCTX)); 845 if (pThreadCtx) 846 { 847 pThreadCtx->pClipboardCtx = pCtx; 848 pThreadCtx->pTransfer = pTransfer; 849 pThreadCtx->papszURIList = papszList; 850 pThreadCtx->cbURIList = cbList; 851 852 GlobalUnlock(hClip); 853 854 if (RT_SUCCESS(rc)) 855 { 856 rc = SharedClipboardURITransferPrepare(pTransfer); 857 if (RT_SUCCESS(rc)) 858 { 859 rc = SharedClipboardURITransferRun(pTransfer, vboxClipboardURIWriteThread, 860 pThreadCtx /* pvUser */); 861 /* pThreadCtx now is owned by vboxClipboardURIWriteThread(). */ 862 } 863 } 864 } 865 else 866 rc = VERR_NO_MEMORY; 867 868 if (RT_FAILURE(rc)) 869 { 870 RTStrFree(papszList); 871 } 872 } 873 } 874 else 875 { 876 hClip = NULL; 877 } 878 } 879 } 880 } 881 } 882 883 VBoxClipboardWinClose(); 884 } 885 886 if (RT_FAILURE(rc)) 887 LogFunc(("VBOX_CLIPBOARD_WM_URI_START_READ: Failed with rc=%Rrc\n", rc)); 888 break; 889 } 890 891 case VBOX_CLIPBOARD_WM_URI_START_WRITE: 892 { 893 LogFunc(("VBOX_CLIPBOARD_WM_URI_START_WRITE: cTransfersRunning=%RU32\n", 894 SharedClipboardURICtxGetRunningTransfers(&pCtx->URI))); 895 896 break; 897 } 898 #endif /* VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */ 810 899 811 900 case WM_DESTROY: … … 821 910 */ 822 911 } 823 break;912 break; 824 913 825 914 default: … … 828 917 lresultRc = DefWindowProc(hwnd, msg, wParam, lParam); 829 918 } 830 break;919 break; 831 920 } 832 921 … … 1004 1093 uint32_t u32Msg; 1005 1094 uint32_t u32Formats; 1006 rc = VbglR3ClipboardGetHostMsg (pCtx->u32ClientID, &u32Msg, &u32Formats);1095 rc = VbglR3ClipboardGetHostMsgOld(pCtx->u32ClientID, &u32Msg, &u32Formats); 1007 1096 if (RT_FAILURE(rc)) 1008 1097 { … … 1044 1133 } 1045 1134 1135 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 1136 case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_TRANSFER_START: 1137 { 1138 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_TRANSFER_START\n")); 1139 1140 const UINT uMsg = u32Formats == 0 ? 1141 VBOX_CLIPBOARD_WM_URI_START_READ : VBOX_CLIPBOARD_WM_URI_START_WRITE; 1142 1143 ::PostMessage(pWinCtx->hWnd, uMsg, 0 /* wParm */, 0 /* lParm */); 1144 break; 1145 } 1146 #endif 1046 1147 case VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT: 1047 1148 { -
trunk/src/VBox/Additions/common/VBoxGuest/lib/Makefile.kmk
r78897 r79497 152 152 ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 153 153 VBoxGuestR3Lib_SOURCES += \ 154 $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardMetaData.cpp \155 154 $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardMIME.cpp 156 155 endif -
trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibClipboard.cpp
r79267 r79497 50 50 * Prototypes * 51 51 *********************************************************************************************************************************/ 52 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST53 static int vbglR3ClipboardWriteErrorInternal(HGCMCLIENTID idClient, int rcErr);54 #endif55 52 56 53 … … 67 64 if (rc == VERR_HGCM_SERVICE_NOT_FOUND) 68 65 rc = VINF_PERMISSION_DENIED; 66 67 LogFlowFuncLeaveRC(rc); 69 68 return rc; 70 69 } … … 84 83 85 84 /** 86 * Get a host message. 85 * Get a host message, old version. 86 * 87 * Note: This is the old message which still is being used for the non-URI Shared Clipboard transfers, 88 * to not break compatibility with older additions / VBox versions. 87 89 * 88 90 * This will block until a message becomes available. … … 93 95 * @param pfFormats Where to store the format(s) the message applies to. 94 96 */ 95 VBGLR3DECL(int) VbglR3ClipboardGetHostMsg(HGCMCLIENTID idClient, uint32_t *pidMsg, uint32_t *pfFormats) 96 { 97 VBoxClipboardGetHostMsg Msg; 98 99 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG, VBOX_SHARED_CLIPBOARD_CPARMS_GET_HOST_MSG); 97 VBGLR3DECL(int) VbglR3ClipboardGetHostMsgOld(HGCMCLIENTID idClient, uint32_t *pidMsg, uint32_t *pfFormats) 98 { 99 VBoxClipboardGetHostMsgOld Msg; 100 101 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, 102 VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD, VBOX_SHARED_CLIPBOARD_CPARMS_GET_HOST_MSG_OLD); 103 100 104 VbglHGCMParmUInt32Set(&Msg.msg, 0); 101 105 VbglHGCMParmUInt32Set(&Msg.formats, 0); … … 157 161 } 158 162 159 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 160 /** 161 * Reads a (meta) data header from the host. 162 * 163 * @returns IPRT status code. 164 * @param idClient The client id returned by VbglR3ClipboardConnect(). 165 * @param pDataHdr Where to store the read meta data header. 166 */ 167 VBGLR3DECL(int) VbglR3ClipboardReadDataHdr(HGCMCLIENTID idClient, PVBOXCLIPBOARDDATAHDR pDataHdr) 168 { 169 AssertPtrReturn(pDataHdr, VERR_INVALID_POINTER); 170 171 VBoxClipboardReadDataHdrMsg Msg; 172 RT_ZERO(Msg); 173 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, 174 VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_DATA_HDR, VBOX_SHARED_CLIPBOARD_CPARMS_READ_DATA_HDR); 175 Msg.uContext.SetUInt32(0); 176 Msg.uFlags.SetUInt32(0); 177 Msg.uScreenId.SetUInt32(0); 178 Msg.cbTotal.SetUInt64(0); 179 Msg.cbMeta.SetUInt32(0); 180 Msg.cbMetaFmt.SetUInt32(0); 181 Msg.pvMetaFmt.SetPtr(pDataHdr->pvMetaFmt, pDataHdr->cbMetaFmt); 182 Msg.cObjects.SetUInt64(0); 163 static int vbglR3ClipboardGetNextMsgType(HGCMCLIENTID idClient, uint32_t *puMsg, uint32_t *pcParms, bool fWait) 164 { 165 AssertPtrReturn(puMsg, VERR_INVALID_POINTER); 166 AssertPtrReturn(pcParms, VERR_INVALID_POINTER); 167 168 VBoxClipboardGetHostMsg Msg; 169 RT_ZERO(Msg); 170 171 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, 172 VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG, VBOX_SHARED_CLIPBOARD_CPARMS_GET_HOST_MSG); 173 174 Msg.uMsg.SetUInt32(0); 175 Msg.cParms.SetUInt32(0); 176 Msg.fBlock.SetUInt32(fWait ? 1 : 0); 177 178 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg)); 179 if (RT_SUCCESS(rc)) 180 { 181 rc = Msg.uMsg.GetUInt32(puMsg); 182 if (RT_SUCCESS(rc)) 183 rc = Msg.cParms.GetUInt32(pcParms); 184 } 185 186 LogFlowFuncLeaveRC(rc); 187 return rc; 188 } 189 190 static int vbglR3ClipboardRecvListOpen(HGCMCLIENTID idClient, PVBOXCLIPBOARDLISTHDR pListHdr) 191 { 192 AssertPtrReturn(pListHdr, VERR_INVALID_POINTER); 193 194 VBoxClipboardListOpenMsg Msg; 195 RT_ZERO(Msg); 196 197 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, 198 VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_OPEN, VBOX_SHARED_CLIPBOARD_CPARMS_LIST_OPEN); 199 200 Msg.uContext.SetUInt32(0); /** @todo Context ID not used yet. */ 201 Msg.uHandle.SetUInt64(0); 202 Msg.fList.SetUInt32(0); 203 Msg.fFeatures.SetUInt32(0); 204 Msg.cbFilter.SetUInt32(0); 205 Msg.pvFilter.SetPtr(pListHdr->pszFilter, pListHdr->cbFilter); 206 207 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg)); 208 if (RT_SUCCESS(rc)) 209 { 210 rc = Msg.fList.GetUInt32(&pListHdr->fList); AssertRC(rc); 211 rc = Msg.fFeatures.GetUInt32(&pListHdr->fFeatures); AssertRC(rc); 212 } 213 214 LogFlowFuncLeaveRC(rc); 215 return rc; 216 } 217 218 static int vbglR3ClipboardRecvListClose(HGCMCLIENTID idClient, PVBOXCLIPBOARDLISTHANDLE phList) 219 { 220 AssertPtrReturn(phList, VERR_INVALID_POINTER); 221 222 VBoxClipboardListCloseMsg Msg; 223 RT_ZERO(Msg); 224 225 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, 226 VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_CLOSE, VBOX_SHARED_CLIPBOARD_CPARMS_LIST_CLOSE); 227 228 Msg.uContext.SetUInt32(0); /** @todo Context ID not used yet. */ 229 Msg.uHandle.SetUInt64(0); 230 231 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg)); 232 if (RT_SUCCESS(rc)) 233 { 234 rc = Msg.uHandle.GetUInt64(phList); AssertRC(rc); 235 } 236 237 LogFlowFuncLeaveRC(rc); 238 return rc; 239 } 240 241 static int vbglR3ClipboardRecvListHdrRead(HGCMCLIENTID idClient, PVBOXCLIPBOARDLISTHANDLE phList, PVBOXCLIPBOARDLISTHDR pListHdr) 242 { 243 AssertPtrReturn(pListHdr, VERR_INVALID_POINTER); 244 AssertPtrReturn(phList, VERR_INVALID_POINTER); 245 246 VBoxClipboardListHdrReadMsg Msg; 247 RT_ZERO(Msg); 248 249 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, 250 VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_HDR_READ, VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR_READ); 251 252 Msg.uContext.SetUInt32(0); /** @todo Context ID not used yet. */ 253 Msg.uHandle.SetUInt64(0); 254 Msg.cTotalObjects.SetUInt64(0); 255 Msg.cbTotalSize.SetUInt64(0); 183 256 Msg.enmCompression.SetUInt32(0); 184 257 Msg.enmChecksumType.SetUInt32(0); 185 Msg.pvChecksum.SetPtr(pDataHdr->pvChecksum, pDataHdr->cbChecksum); 186 Msg.cbChecksum.SetUInt32(0); 187 188 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg)); 189 if (RT_SUCCESS(rc)) 190 { 191 /* Msg.uContext not needed here. */ 192 Msg.uFlags.GetUInt32(&pDataHdr->uFlags); 193 Msg.uScreenId.GetUInt32(&pDataHdr->uScreenId); 194 Msg.cbTotal.GetUInt64(&pDataHdr->cbTotal); 195 Msg.cbMeta.GetUInt32(&pDataHdr->cbMeta); 196 Msg.cbMetaFmt.GetUInt32(&pDataHdr->cbMetaFmt); 197 Msg.cObjects.GetUInt64(&pDataHdr->cObjects); 198 Msg.enmCompression.GetUInt32(&pDataHdr->enmCompression); 199 Msg.enmChecksumType.GetUInt32((uint32_t *)&pDataHdr->enmChecksumType); 200 Msg.cbChecksum.GetUInt32(&pDataHdr->cbChecksum); 201 202 AssertReturn(SharedClipboardURIDataHdrIsValid(pDataHdr), VERR_INVALID_PARAMETER); 203 } 204 205 LogFlowFuncLeaveRC(rc); 206 return rc; 207 } 208 209 /** 210 * Sends a guest clipboard data header to the host. 211 * 212 * This is usually called in reply to a VBOX_SHARED_CLIPBOARD_HOST_READ_DATA message from the host 213 * (if URI format is specified). 258 259 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg)); 260 if (RT_SUCCESS(rc)) 261 { 262 rc = Msg.uHandle.GetUInt64(phList); AssertRC(rc); 263 } 264 265 LogFlowFuncLeaveRC(rc); 266 return rc; 267 } 268 269 static int vbglR3ClipboardRecvListEntryRead(HGCMCLIENTID idClient, PVBOXCLIPBOARDLISTHANDLE phList, 270 PVBOXCLIPBOARDLISTENTRY pListEntry) 271 { 272 AssertPtrReturn(pListEntry, VERR_INVALID_POINTER); 273 AssertPtrReturn(phList, VERR_INVALID_POINTER); 274 275 VBoxClipboardListEntryReadMsg Msg; 276 RT_ZERO(Msg); 277 278 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, 279 VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_ENTRY_READ, VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY_READ); 280 281 Msg.uContext.SetUInt32(0); /** @todo Context ID not used yet. */ 282 Msg.uHandle.SetUInt64(0); 283 Msg.fInfo.SetUInt32(0); 284 Msg.cbInfo.SetUInt32(0); 285 Msg.pvInfo.SetPtr(pListEntry->pvInfo, pListEntry->cbInfo); 286 287 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg)); 288 if (RT_SUCCESS(rc)) 289 { 290 rc = Msg.uHandle.GetUInt64(phList); AssertRC(rc); 291 rc = Msg.fInfo.GetUInt32(&pListEntry->fInfo); AssertRC(rc); 292 rc = Msg.cbInfo.GetUInt32(&pListEntry->cbInfo); AssertRC(rc); 293 } 294 295 LogFlowFuncLeaveRC(rc); 296 return rc; 297 } 298 299 VBGLR3DECL(int) VbglR3ClipboardEventGetNext(HGCMCLIENTID idClient, PSHAREDCLIPBOARDURITRANSFER pTransfer, 300 PVBGLR3CLIPBOARDEVENT *ppEvent) 301 { 302 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER); 303 AssertPtrReturn(ppEvent, VERR_INVALID_POINTER); 304 305 PVBGLR3CLIPBOARDEVENT pEvent = (PVBGLR3CLIPBOARDEVENT)RTMemAllocZ(sizeof(VBGLR3CLIPBOARDEVENT)); 306 if (!pEvent) 307 return VERR_NO_MEMORY; 308 309 uint32_t uMsg = 0; 310 uint32_t cParms = 0; 311 int rc = vbglR3ClipboardGetNextMsgType(idClient, &uMsg, &cParms, true /* fWait */); 312 if (RT_SUCCESS(rc)) 313 { 314 /** @todo Check for VM session change. */ 315 } 316 317 #if 0 318 typedef struct _ 319 { 320 union 321 { 322 struct Dir 323 { 324 RTDIR hDir; 325 }; 326 } u; 327 }; 328 #endif 329 330 if (RT_SUCCESS(rc)) 331 { 332 LogFunc(("Handling uMsg=%RU32\n", uMsg)); 333 334 switch (uMsg) 335 { 336 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 337 case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_OPEN: 338 { 339 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_OPEN\n")); 340 341 VBOXCLIPBOARDLISTHDR listHdr; 342 rc = SharedClipboardURIListHdrInit(&listHdr); 343 if (RT_SUCCESS(rc)) 344 { 345 rc = vbglR3ClipboardRecvListOpen(idClient, &listHdr); 346 if (RT_SUCCESS(rc)) 347 { 348 rc = SharedClipboardURITransferListOpen(pTransfer, &listHdr, NULL /* phList */); 349 } 350 351 SharedClipboardURIListHdrDestroy(&listHdr); 352 } 353 354 break; 355 } 356 357 case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_CLOSE: 358 { 359 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_CLOSE\n")); 360 361 VBOXCLIPBOARDLISTHANDLE hList; 362 rc = vbglR3ClipboardRecvListClose(idClient, &hList); 363 if (RT_SUCCESS(rc)) 364 { 365 rc = SharedClipboardURITransferListClose(pTransfer, hList); 366 } 367 368 break; 369 } 370 371 case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_HDR_READ: 372 { 373 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_HDR_READ\n")); 374 375 /** @todo Handle filter + list features. */ 376 377 VBOXCLIPBOARDLISTHDR listHdr; 378 rc = SharedClipboardURIListHdrInit(&listHdr); 379 if (RT_SUCCESS(rc)) 380 { 381 VBOXCLIPBOARDLISTHANDLE hList; 382 rc = vbglR3ClipboardRecvListHdrRead(idClient, &hList, &listHdr); 383 if (RT_SUCCESS(rc)) 384 { 385 if (SharedClipboardURITransferListHandleIsValid(pTransfer, hList)) 386 { 387 rc = VbglR3ClipboardSendListHdrWrite(idClient, hList, &listHdr); 388 } 389 else 390 rc = VERR_INVALID_HANDLE; 391 } 392 393 SharedClipboardURIListHdrDestroy(&listHdr); 394 } 395 396 break; 397 } 398 399 case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_HDR_WRITE: 400 { 401 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_HDR_WRITE\n")); 402 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_URI_LIST_HDR_WRITE; 403 break; 404 } 405 406 case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_ENTRY_READ: 407 { 408 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_ENTRY_READ\n")); 409 410 VBOXCLIPBOARDLISTENTRY listEntry; 411 rc = SharedClipboardURIListEntryInit(&listEntry); 412 if (RT_SUCCESS(rc)) 413 { 414 VBOXCLIPBOARDLISTHANDLE hList; 415 rc = vbglR3ClipboardRecvListEntryRead(idClient, &hList, &listEntry); 416 if (RT_SUCCESS(rc)) 417 { 418 if (SharedClipboardURITransferListHandleIsValid(pTransfer, hList)) 419 { 420 rc = VbglR3ClipboardSendListEntryWrite(idClient, hList, &listEntry); 421 } 422 else 423 rc = VERR_INVALID_HANDLE; 424 } 425 426 SharedClipboardURIListEntryDestroy(&listEntry); 427 } 428 break; 429 } 430 431 case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_ENTRY_WRITE: 432 { 433 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_ENTRY_WRITE\n")); 434 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_URI_LIST_ENTRY_WRITE; 435 break; 436 } 437 438 case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_OPEN: 439 { 440 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_OPEN\n")); 441 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_URI_OBJ_OPEN; 442 break; 443 } 444 445 case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_CLOSE: 446 { 447 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_CLOSE\n")); 448 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_URI_OBJ_CLOSE; 449 break; 450 } 451 452 case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_READ: 453 { 454 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_READ\n")); 455 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_URI_OBJ_READ; 456 break; 457 } 458 459 case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_WRITE: 460 { 461 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_WRITE\n")); 462 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_URI_OBJ_WRITE; 463 break; 464 } 465 #endif /* VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */ 466 467 default: 468 rc = VERR_NOT_SUPPORTED; 469 break; 470 } 471 } 472 473 474 if (RT_SUCCESS(rc)) 475 { 476 if (pEvent->enmType != VBGLR3CLIPBOARDEVENTTYPE_INVALID) 477 { 478 *ppEvent = pEvent; 479 } 480 else 481 VbglR3ClipboardEventFree(pEvent); 482 } 483 else 484 { 485 /* Report error back to the host. */ 486 VbglR3ClipboardWriteError(idClient, rc); 487 488 VbglR3ClipboardEventFree(pEvent); 489 } 490 491 LogFlowFuncLeaveRC(rc); 492 return rc; 493 } 494 495 /** 496 * Frees (destroys) a formerly allocated Shared Clipboard event. 497 * 498 * @returns IPRT status code. 499 * @param pEvent Event to free (destroy). 500 */ 501 VBGLR3DECL(void) VbglR3ClipboardEventFree(PVBGLR3CLIPBOARDEVENT pEvent) 502 { 503 if (!pEvent) 504 return; 505 506 /* Some messages require additional cleanup. */ 507 switch (pEvent->enmType) 508 { 509 default: 510 break; 511 } 512 513 RTMemFree(pEvent); 514 pEvent = NULL; 515 } 516 517 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 518 /** 519 * Sends a list header to the host. 214 520 * 215 521 * @returns VBox status code. 216 522 * @param idClient The client id returned by VbglR3ClipboardConnect(). 217 * @param pDataHdr Pointer to data header to send. 218 */ 219 VBGLR3DECL(int) VbglR3ClipboardWriteDataHdr(HGCMCLIENTID idClient, const PVBOXCLIPBOARDDATAHDR pDataHdr) 220 { 221 VBoxClipboardWriteDataHdrMsg Msg; 222 RT_ZERO(Msg); 223 224 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DATA_HDR, VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_DATA_HDR); 225 226 AssertReturn(SharedClipboardURIDataHdrIsValid(pDataHdr), VERR_INVALID_PARAMETER); 227 228 Msg.uContext.SetUInt32(0); /** @todo Not used yet. */ 229 Msg.uFlags.SetUInt32(pDataHdr->uFlags); /** @todo Not used yet. */ 230 Msg.uScreenId.SetUInt32(pDataHdr->uScreenId); /** @todo Not used yet. */ 231 Msg.cbTotal.SetUInt64(pDataHdr->cbTotal); 232 Msg.cbMeta.SetUInt32(pDataHdr->cbMeta); 233 Msg.cbMetaFmt.SetUInt32(pDataHdr->cbMetaFmt); 234 Msg.pvMetaFmt.SetPtr(pDataHdr->pvMetaFmt, pDataHdr->cbMetaFmt); 235 Msg.cObjects.SetUInt64(pDataHdr->cObjects); 236 Msg.enmCompression.SetUInt32(pDataHdr->enmCompression); /** @todo Not used yet. */ 237 Msg.enmChecksumType.SetUInt32(RTDIGESTTYPE_INVALID); /** @todo Not used yet. */ 238 Msg.cbChecksum.SetUInt32(0); /** @todo Not used yet. */ 239 Msg.pvChecksum.SetPtr(NULL, 0); /** @todo Not used yet. */ 240 241 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg)); 242 243 LogFlowFunc(("cbTotal=%RU64, cbMeta=%RU32, pvMetaFmt=%p (%RU32), cObjects=%RU64, rc=%Rrc\n", 244 pDataHdr->cbTotal, pDataHdr->cbMeta, pDataHdr->pvMetaFmt, pDataHdr->cbMetaFmt, pDataHdr->cObjects, rc)); 245 246 LogFlowFuncLeaveRC(rc); 247 return rc; 248 } 249 250 /** 251 * Reads a (meta) data chunk from the host. 523 * @param hList List handle to send header for. 524 * @param pListHdr List header to send. 525 */ 526 VBGLR3DECL(int) VbglR3ClipboardSendListHdrWrite(HGCMCLIENTID idClient, 527 VBOXCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTHDR pListHdr) 528 { 529 VBoxClipboardListHdrWriteMsg Msg; 530 RT_ZERO(Msg); 531 532 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, 533 VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_WRITE, VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR_WRITE); 534 535 Msg.uContext.SetUInt32(0); /** @todo Not used yet. */ 536 Msg.uHandle.SetUInt64(hList); 537 Msg.cTotalObjects.SetUInt64(pListHdr->cTotalObjects); 538 Msg.cbTotalSize.SetUInt64(pListHdr->cbTotalSize); 539 Msg.enmCompression.SetUInt32(pListHdr->enmCompression); 540 Msg.enmChecksumType.SetUInt32(RTDIGESTTYPE_INVALID); 541 542 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg)); 543 544 LogFlowFuncLeaveRC(rc); 545 return rc; 546 } 547 548 /** 549 * Sends a list entry to the host. 252 550 * 253 551 * @returns IPRT status code. 254 * @param idClient The client id returned by VbglR3ClipboardConnect(). 255 * @param pDataHdr Data header to use. Need for accounting and stuff. 256 * @param pvData Where to store the received data from the host. 257 * @param cbData Size (in bytes) of where to store the received data. 258 * @param pcbDataRecv Where to store the received amount of data (in bytes). 259 */ 260 static int vbglR3ClipboardReadDataChunk(HGCMCLIENTID idClient, PVBOXCLIPBOARDDATAHDR pDataHdr, 261 void *pvData, uint32_t cbData, uint32_t *pcbDataRecv) 262 { 263 AssertPtrReturn(pDataHdr, VERR_INVALID_POINTER); 264 AssertPtrReturn(pvData, VERR_INVALID_POINTER); 265 AssertReturn(cbData, VERR_INVALID_PARAMETER); 266 AssertPtrNullReturn(pcbDataRecv, VERR_INVALID_POINTER); 267 268 LogFlowFunc(("pvDate=%p, cbData=%RU32\n", pvData, cbData)); 269 270 VBoxClipboardReadDataChunkMsg Msg; 271 RT_ZERO(Msg); 272 273 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, 274 VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_DATA_CHUNK, VBOX_SHARED_CLIPBOARD_CPARMS_READ_DATA_CHUNK); 552 * @param idClient The client id returned by VbglR3ClipboardConnect() 553 * @param hList List handle to send entry for. 554 * @param pListEntry List entry to send. 555 */ 556 VBGLR3DECL(int) VbglR3ClipboardSendListEntryWrite(HGCMCLIENTID idClient, 557 VBOXCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTENTRY pListEntry) 558 { 559 AssertPtrReturn(pListEntry, VERR_INVALID_POINTER); 560 561 VBoxClipboardListEntryWriteMsg Msg; 562 RT_ZERO(Msg); 563 564 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, 565 VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_ENTRY_WRITE, VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY_WRITE); 566 567 Msg.uContext.SetUInt32(0); /** @todo Not used yet. */ 568 Msg.uHandle.SetUInt64(hList); 569 Msg.fInfo.SetUInt32(pListEntry->fInfo); 570 Msg.cbInfo.SetUInt32(pListEntry->cbInfo); 571 Msg.pvInfo.SetPtr(pListEntry->pvInfo, pListEntry->cbInfo); 572 573 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg)); 574 575 LogFlowFuncLeaveRC(rc); 576 return rc; 577 } 578 579 VBGLR3DECL(int) VbglR3ClipboardObjOpen(HGCMCLIENTID idClient, 580 const char *pszPath, PVBOXCLIPBOARDCREATEPARMS pCreateParms, 581 PSHAREDCLIPBOARDOBJHANDLE phObj) 582 { 583 AssertPtrReturn(pszPath, VERR_INVALID_POINTER); 584 AssertPtrReturn(pCreateParms, VERR_INVALID_POINTER); 585 AssertPtrReturn(phObj, VERR_INVALID_POINTER); 586 587 VBoxClipboardObjOpenMsg Msg; 588 RT_ZERO(Msg); 589 590 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, 591 VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_OPEN, VBOX_SHARED_CLIPBOARD_CPARMS_OBJ_OPEN); 592 593 int rc; 594 595 char *pszPathTmp = RTStrDup(pszPath); 596 if (pszPathTmp) 597 { 598 Msg.szPath.SetPtr((void *)pszPathTmp, (uint32_t)strlen(pszPathTmp) + 1 /* Include terminating zero */); 599 Msg.parms.SetPtr(pCreateParms, sizeof(VBOXCLIPBOARDCREATEPARMS)); 600 601 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg)); 602 if (RT_SUCCESS(rc)) 603 { 604 *phObj = pCreateParms->uHandle; 605 } 606 607 RTStrFree(pszPathTmp); 608 } 609 else 610 rc = VERR_NO_MEMORY; 611 612 LogFlowFuncLeaveRC(rc); 613 return rc; 614 } 615 616 VBGLR3DECL(int) VbglR3ClipboardObjClose(HGCMCLIENTID idClient, SHAREDCLIPBOARDOBJHANDLE hObj) 617 { 618 VBoxClipboardObjCloseMsg Msg; 619 RT_ZERO(Msg); 620 621 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, 622 VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_CLOSE, VBOX_SHARED_CLIPBOARD_CPARMS_OBJ_CLOSE); 623 624 Msg.uHandle.SetUInt64(hObj); 625 626 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg)); 627 628 LogFlowFuncLeaveRC(rc); 629 return rc; 630 } 631 632 VBGLR3DECL(int) VbglR3ClipboardObjRead(HGCMCLIENTID idClient, SHAREDCLIPBOARDOBJHANDLE hObj, 633 void *pvData, uint32_t cbData, uint32_t *pcbRead) 634 { 635 AssertPtrReturn(pvData, VERR_INVALID_POINTER); 636 AssertReturn(cbData, VERR_INVALID_PARAMETER); 637 /* pcbRead is optional. */ 638 639 VBoxClipboardObjReadWriteMsg Msg; 640 RT_ZERO(Msg); 641 642 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_READ, VBOX_SHARED_CLIPBOARD_CPARMS_OBJ_READ); 643 644 Msg.uContext.SetUInt32(0); 645 Msg.uHandle.SetUInt64(hObj); 275 646 Msg.pvData.SetPtr(pvData, cbData); 276 647 Msg.cbData.SetUInt32(0); … … 281 652 if (RT_SUCCESS(rc)) 282 653 { 283 uint32_t cbDataRecv;284 rc = Msg.cbData.GetUInt32(&cbDataRecv);285 AssertRC(rc); 286 if ( RT_SUCCESS(rc))654 /** @todo Context ID not used yet. */ 655 /** @todo Add checksum support. */ 656 657 if (pcbRead) 287 658 { 288 /** @todo Use checksum for validating the received data. */ 289 if (pcbDataRecv) 290 *pcbDataRecv = cbDataRecv; 291 LogFlowFuncLeaveRC(rc); 292 return rc; 659 rc = Msg.cbData.GetUInt32(pcbRead); AssertRC(rc); 660 AssertReturn(cbData >= *pcbRead, VERR_TOO_MUCH_DATA); 293 661 } 294 662 } 295 663 296 /* failure */ 297 LogFlowFuncLeaveRC(rc); 298 return rc; 299 } 300 301 /** 302 * Helper function for reading the actual clipboard (meta) data from the host. Do not call directly. 303 * 304 * @returns IPRT status code. 305 * @param idClient The client id returned by VbglR3ClipboardConnect(). 306 * @param pDataHdr Pointer to data header to use. 307 * @param pvMeta Where to store the received meta data. 308 * @param cbMeta Size (in bytes) of meta data buffer. 309 * @param pcbRead How much bytes were read on success. Optional. 310 */ 311 static int vbglR3ClipboardReadMetaDataLoop(HGCMCLIENTID idClient, PVBOXCLIPBOARDDATAHDR pDataHdr, 312 void *pvMeta, uint32_t cbMeta, uint32_t *pcbRead) 313 { 314 AssertPtrReturn(pDataHdr, VERR_INVALID_POINTER); 315 AssertPtrReturn(pvMeta, VERR_INVALID_POINTER); 316 317 LogFlowFuncEnter(); 318 319 int rc = VINF_SUCCESS; 320 321 uint32_t cbReadTotal = 0; 322 323 LogFlowFunc(("cbTotal=%RU64, cbMeta=%RU32, cObjects=%RU32\n", pDataHdr->cbTotal, pDataHdr->cbMeta, pDataHdr->cObjects)); 324 if (pDataHdr->cbMeta) 325 { 326 uint32_t cbToRead = RT_MIN(cbMeta, pDataHdr->cbMeta); 327 while (cbToRead) 328 { 329 uint32_t cbRead; 330 rc = vbglR3ClipboardReadDataChunk(idClient, pDataHdr, 331 (uint8_t *)pvMeta + cbReadTotal, cbToRead, &cbRead); 332 if (RT_FAILURE(rc)) 333 break; 334 335 Assert(cbToRead >= cbRead); 336 cbToRead -= cbRead; 337 338 cbReadTotal += cbRead; 339 } 340 } 341 342 if (RT_SUCCESS(rc)) 343 { 344 if (pcbRead) 345 *pcbRead = cbReadTotal; 346 } 347 348 LogFlowFuncLeaveRC(rc); 349 return rc; 350 } 351 352 /** 353 * Reads the actual meta data from the host, internal version. 354 * 355 * @returns IPRT status code. 356 * @param idClient The client id returned by VbglR3ClipboardConnect(). 357 * @param pDataHdr Pointer to data header to use. 358 * @param pvMeta Where to store the received meta data. 359 * @param cbMeta Size (in bytes) of meta data buffer. 360 * @param pcbRead How much bytes were read on success. Optional. 361 */ 362 static int vbglR3ClipboardReadMetaDataInternal(HGCMCLIENTID idClient, PVBOXCLIPBOARDDATAHDR pDataHdr, 363 void *pvMeta, uint32_t cbMeta, uint32_t *pcbRead) 364 { 365 LogFlowFuncEnter(); 366 367 int rc = vbglR3ClipboardReadMetaDataLoop(idClient, pDataHdr, pvMeta, cbMeta, pcbRead); 368 369 LogFlowFuncLeaveRC(rc); 370 return rc; 371 } 372 373 /** 374 * Reads the actual meta data from the host, extended version. 375 * 376 * @returns IPRT status code. 377 * @param idClient The client id returned by VbglR3ClipboardConnect(). 378 * @param pvMeta Where to store the received meta data. 379 * @param cbMeta Size (in bytes) of meta data buffer. 380 * @param pcbRead How much bytes were read on success. Optional. 381 */ 382 VBGLR3DECL(int) VbglR3ClipboardReadMetaDataEx(HGCMCLIENTID idClient, PVBOXCLIPBOARDDATAHDR pDataHdr, 383 void *pvMeta, uint32_t cbMeta, uint32_t *pcbRead) 384 { 385 return vbglR3ClipboardReadMetaDataInternal(idClient, pDataHdr, pvMeta, cbMeta, pcbRead); 386 } 387 388 /** 389 * Reads the actual meta data from the host. 390 * 391 * @returns IPRT status code. 392 * @param idClient The client id returned by VbglR3ClipboardConnect(). 393 * @param pvMeta Where to store the received meta data. 394 * @param cbMeta Size (in bytes) of meta data buffer. 395 * @param pcbRead How much bytes were read on success. Optional. 396 */ 397 VBGLR3DECL(int) VbglR3ClipboardReadMetaData(HGCMCLIENTID idClient, PVBOXCLIPBOARDDATAHDR pDataHdr, 398 void *pvMeta, uint32_t cbMeta, uint32_t *pcbRead) 399 { 400 return VbglR3ClipboardReadMetaDataEx(idClient, pDataHdr, pvMeta, cbMeta, pcbRead); 401 } 402 403 /** 404 * Writes a (meta) data chunk to the host. 405 * 406 * @returns IPRT status code. 407 * @param idClient The client id returned by VbglR3ClipboardConnect(). 408 * @param pDataHdr Data header to use. Need for accounting and stuff. 409 * @param pvData Where to store the received data from the host. 410 * @param cbData Size (in bytes) of where to store the received data. 411 * @param pcbDataWritten Where to store the written amount of data (in bytes). 412 */ 413 static int vbglR3ClipboardWriteDataChunk(HGCMCLIENTID idClient, PVBOXCLIPBOARDDATAHDR pDataHdr, 414 void *pvData, uint32_t cbData, uint32_t *pcbDataWritten) 415 { 416 AssertPtrReturn(pDataHdr, VERR_INVALID_POINTER); 417 AssertPtrReturn(pvData, VERR_INVALID_POINTER); 418 AssertReturn(cbData, VERR_INVALID_PARAMETER); 419 AssertPtrNullReturn(pcbDataWritten, VERR_INVALID_POINTER); 420 421 LogFlowFunc(("pvDate=%p, cbData=%RU32\n", pvData, cbData)); 422 423 VBoxClipboardReadDataChunkMsg Msg; 424 RT_ZERO(Msg); 425 426 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, 427 VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DATA_CHUNK, VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_DATA_CHUNK); 428 429 Msg.uContext.SetUInt32(0); /** @todo Not used yet. */ 664 LogFlowFuncLeaveRC(rc); 665 return rc; 666 } 667 668 VBGLR3DECL(int) VbglR3ClipboardObjWrite(HGCMCLIENTID idClient, 669 SHAREDCLIPBOARDOBJHANDLE hObj, 670 void *pvData, uint32_t cbData, uint32_t *pcbWritten) 671 { 672 AssertPtrReturn(pvData, VERR_INVALID_POINTER); 673 AssertReturn(cbData, VERR_INVALID_PARAMETER); 674 /* pcbWritten is optional. */ 675 676 VBoxClipboardObjReadWriteMsg Msg; 677 RT_ZERO(Msg); 678 679 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_WRITE, VBOX_SHARED_CLIPBOARD_CPARMS_OBJ_WRITE); 680 681 Msg.uContext.SetUInt32(0); 682 Msg.uHandle.SetUInt64(hObj); 683 Msg.pvData.SetPtr(pvData, cbData); 430 684 Msg.cbData.SetUInt32(cbData); 431 Msg.pvData.SetPtr(pvData, cbData);432 Msg.cbChecksum.SetUInt32(0);433 Msg.pvChecksum.SetPtr(NULL, 0);434 435 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));436 if (RT_SUCCESS(rc))437 {438 if (pcbDataWritten)439 *pcbDataWritten = cbData;440 }441 442 /* failure */443 LogFlowFuncLeaveRC(rc);444 return rc;445 }446 447 /**448 * Writes the actual meta data to the host, internal version.449 *450 * @returns IPRT status code.451 * @param idClient The client id returned by VbglR3ClipboardConnect().452 * @param pDataHdr Pointer to data header to use.453 * @param pvMeta Meta data buffer to write.454 * @param cbMeta Size (in bytes) of meta data buffer.455 * @param pcbWritten How much bytes were written on success. Optional.456 */457 static int vbglR3ClipboardWriteMetaDataInternal(HGCMCLIENTID idClient, PVBOXCLIPBOARDDATAHDR pDataHdr,458 const void *pvMeta, uint32_t cbMeta, uint32_t *pcbWritten)459 {460 AssertPtrReturn(pDataHdr, VERR_INVALID_POINTER);461 AssertPtrReturn(pvMeta, VERR_INVALID_POINTER);462 463 LogFlowFuncEnter();464 465 int rc = VINF_SUCCESS;466 467 uint32_t cbWrittenTotal = 0;468 469 LogFlowFunc(("cbTotal=%RU64, cbMeta=%RU32, cObjects=%RU32\n", pDataHdr->cbTotal, pDataHdr->cbMeta, pDataHdr->cObjects));470 if (pDataHdr->cbMeta)471 {472 uint32_t cbToWrite = RT_MIN(cbMeta, pDataHdr->cbMeta);473 while (cbToWrite)474 {475 uint32_t cbWritten;476 rc = vbglR3ClipboardWriteDataChunk(idClient, pDataHdr,477 (uint8_t *)pvMeta + cbWrittenTotal, cbToWrite, &cbWritten);478 if (RT_FAILURE(rc))479 break;480 481 Assert(cbToWrite >= cbWritten);482 cbToWrite -= cbWritten;483 484 cbWrittenTotal += cbWritten;485 }486 }487 488 if (RT_SUCCESS(rc))489 {490 if (pcbWritten)491 *pcbWritten = cbWrittenTotal;492 }493 494 LogFlowFunc(("cbWrittenTotal=%RU32, rc=%Rrc\n", cbWrittenTotal, rc));495 return rc;496 }497 498 /**499 * Writes the actual meta data to the host, extended version.500 *501 * @returns IPRT status code.502 * @param idClient The client id returned by VbglR3ClipboardConnect().503 * @param pDataHdr Pointer to data header to use.504 * @param pvMeta Pointer to meta data buffer.505 * @param cbMeta Size (in bytes) of meta data buffer.506 * @param pcbWritten How much bytes were written on success. Optional.507 */508 VBGLR3DECL(int) VbglR3ClipboardWriteMetaDataEx(HGCMCLIENTID idClient, PVBOXCLIPBOARDDATAHDR pDataHdr,509 const void *pvMeta, uint32_t cbMeta, uint32_t *pcbWritten)510 {511 int rc = vbglR3ClipboardWriteMetaDataInternal(idClient, pDataHdr, pvMeta, cbMeta, pcbWritten);512 513 LogFlowFuncLeaveRC(rc);514 return rc;515 }516 517 /**518 * Writes the actual meta data to the host.519 *520 * @returns IPRT status code.521 * @param idClient The client id returned by VbglR3ClipboardConnect().522 * @param pDataHdr Pointer to data header to use.523 * @param pvMeta Pointer to meta data buffer.524 * @param cbMeta Size (in bytes) of meta data buffer.525 * @param pcbWritten How much bytes were written on success. Optional.526 */527 VBGLR3DECL(int) VbglR3ClipboardWriteMetaData(HGCMCLIENTID idClient, PVBOXCLIPBOARDDATAHDR pDataHdr,528 const void *pvMeta, uint32_t cbMeta, uint32_t *pcbWritten)529 {530 return VbglR3ClipboardWriteMetaDataEx(idClient, pDataHdr, pvMeta, cbMeta, pcbWritten);531 }532 533 /**534 * Reads a directory entry from the host.535 *536 * @returns IPRT status code.537 * @param idClient The client id returned by VbglR3ClipboardConnect().538 * @param pszDirname Where to store the directory name of the directory being created.539 * @param cbDirname Size (in bytes) of where to store the directory name of the directory being created.540 * @param pcbDirnameRecv Size (in bytes) of the actual directory name received.541 * @param pfMode Where to store the directory creation mode.542 */543 VBGLR3DECL(int) VbglR3ClipboardReadDir(HGCMCLIENTID idClient,544 char *pszDirname,545 uint32_t cbDirname,546 uint32_t *pcbDirnameRecv,547 uint32_t *pfMode)548 {549 AssertPtrReturn(pszDirname, VERR_INVALID_POINTER);550 AssertReturn(cbDirname, VERR_INVALID_PARAMETER);551 AssertPtrReturn(pcbDirnameRecv, VERR_INVALID_POINTER);552 AssertPtrReturn(pfMode, VERR_INVALID_POINTER);553 554 VBoxClipboardReadDirMsg Msg;555 RT_ZERO(Msg);556 557 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_DIR, VBOX_SHARED_CLIPBOARD_CPARMS_READ_DIR);558 /** @todo Context ID not used yet. */559 Msg.uContext.SetUInt32(0);560 Msg.pvName.SetPtr(pszDirname, cbDirname);561 Msg.cbName.SetUInt32(cbDirname);562 Msg.fMode.SetUInt32(0);563 564 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));565 if (RT_SUCCESS(rc))566 {567 /** @todo Context ID not used yet. */568 rc = Msg.cbName.GetUInt32(pcbDirnameRecv); AssertRC(rc);569 rc = Msg.fMode.GetUInt32(pfMode); AssertRC(rc);570 571 AssertReturn(cbDirname >= *pcbDirnameRecv, VERR_TOO_MUCH_DATA);572 }573 574 return rc;575 }576 577 /**578 * Writes a guest directory to the host.579 *580 * @returns IPRT status code.581 * @param idClient The client id returned by VbglR3ClipboardConnect().582 * @param pszPath Directory path.583 * @param cbPath Size (in bytes) of directory path.584 * @param fMode File mode for directory (IPRT-style).585 */586 VBGLR3DECL(int) VbglR3ClipboardWriteDir(HGCMCLIENTID idClient,587 const char *pszPath,588 uint32_t cbPath,589 uint32_t fMode)590 {591 const size_t cchDir = strlen(pszPath);592 593 if ( !cchDir594 || cchDir > RTPATH_MAX595 || cchDir != cbPath) /* UTF-8 */596 return VERR_INVALID_PARAMETER;597 598 const uint32_t cbPathSz = (uint32_t)cchDir + 1; /* Include termination. */599 600 VBoxClipboardWriteDirMsg Msg;601 RT_ZERO(Msg);602 603 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DIR, VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_DIR);604 /** @todo Context ID not used yet. */605 Msg.pvName.SetPtr((void *)pszPath, (uint32_t)cbPathSz);606 Msg.cbName.SetUInt32(cbPathSz);607 Msg.fMode.SetUInt32(fMode);608 609 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));610 }611 612 /**613 * Receives a file header from the host.614 *615 * @returns IPRT status code.616 * @param idClient The client id returned by VbglR3ClipboardConnect().617 * @param pszFilename Where to store the file name of the file being transferred.618 * @param cbFilename Size (in bytes) of where to store the file name of the file being transferred.619 * @param puFlags File transfer flags. Currently not being used.620 * @param pfMode Where to store the file creation mode.621 * @param pcbTotal Where to store the file size (in bytes).622 */623 VBGLR3DECL(int) VbglR3ClipboardReadFileHdr(HGCMCLIENTID idClient,624 char *pszFilename,625 uint32_t cbFilename,626 uint32_t *puFlags,627 uint32_t *pfMode,628 uint64_t *pcbTotal)629 {630 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);631 AssertReturn(cbFilename, VERR_INVALID_PARAMETER);632 AssertPtrReturn(puFlags, VERR_INVALID_POINTER);633 AssertPtrReturn(pfMode, VERR_INVALID_POINTER);634 AssertReturn(pcbTotal, VERR_INVALID_POINTER);635 636 VBoxClipboardReadFileHdrMsg Msg;637 RT_ZERO(Msg);638 639 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,640 VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_FILE_HDR, VBOX_SHARED_CLIPBOARD_CPARMS_READ_FILE_HDR);641 Msg.uContext.SetUInt32(0); /** @todo Not used yet. */642 Msg.pvName.SetPtr(pszFilename, cbFilename);643 Msg.cbName.SetUInt32(cbFilename);644 Msg.uFlags.SetUInt32(0);645 Msg.fMode.SetUInt32(0);646 Msg.cbTotal.SetUInt64(0);647 648 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));649 if (RT_SUCCESS(rc))650 {651 /** @todo Get context ID. */652 rc = Msg.uFlags.GetUInt32(puFlags); AssertRC(rc);653 rc = Msg.fMode.GetUInt32(pfMode); AssertRC(rc);654 rc = Msg.cbTotal.GetUInt64(pcbTotal); AssertRC(rc);655 }656 657 return rc;658 }659 660 /**661 * Writes a file header from the guest to the host.662 *663 * @returns VBox status code.664 * @param idClient The client id returned by VbglR3ClipboardConnect().665 * @param pszFilename File name this header belong to.666 * @param cbFilename Size (in bytes) of file name.667 * @param fFlags Transfer flags; not being used and will be ignored.668 * @param fMode File mode.669 * @param cbTotal File size (in bytes).670 */671 VBGLR3DECL(int) VbglR3ClipboardWriteFileHdr(HGCMCLIENTID idClient, const char *pszFilename, uint32_t cbFilename,672 uint32_t fFlags, uint32_t fMode, uint64_t cbTotal)673 {674 RT_NOREF(fFlags);675 676 const size_t cchFile = strlen(pszFilename);677 678 if ( !cchFile679 || cchFile > RTPATH_MAX680 || cchFile != cbFilename)681 return VERR_INVALID_PARAMETER;682 683 const uint32_t cbFileSz = (uint32_t)cchFile + 1; /* Include termination. */684 685 VBoxClipboardWriteFileHdrMsg MsgHdr;686 RT_ZERO(MsgHdr);687 688 VBGL_HGCM_HDR_INIT(&MsgHdr.hdr, idClient, VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_FILE_HDR, VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_FILE_HDR);689 MsgHdr.uContext.SetUInt32(0); /* Context ID; unused at the moment. */690 MsgHdr.cbName.SetUInt32(cbFileSz);691 MsgHdr.pvName.SetPtr((void *)pszFilename, (uint32_t)(cbFileSz));692 MsgHdr.uFlags.SetUInt32(0); /* Flags; unused at the moment. */693 MsgHdr.fMode.SetUInt32(fMode); /* File mode */694 MsgHdr.cbTotal.SetUInt64(cbTotal); /* File size (in bytes). */695 696 return VbglR3HGCMCall(&MsgHdr.hdr, sizeof(MsgHdr));697 }698 699 /**700 * Reads a file data chunk from the host.701 *702 * @returns IPRT status code.703 * @param idClient The client id returned by VbglR3ClipboardConnect().704 * @param pvData Where to store the file data chunk.705 * @param cbData Size (in bytes) of where to store the data chunk.706 * @param pcbRead Size (in bytes) of the actual data chunk size read.707 */708 VBGLR3DECL(int) VbglR3ClipboardReadFileData(HGCMCLIENTID idClient,709 void *pvData,710 uint32_t cbData,711 uint32_t *pcbRead)712 {713 AssertPtrReturn(pvData, VERR_INVALID_POINTER);714 AssertReturn(cbData, VERR_INVALID_PARAMETER);715 AssertPtrReturn(pcbRead, VERR_INVALID_POINTER);716 717 VBoxClipboardReadFileDataMsg Msg;718 RT_ZERO(Msg);719 720 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,721 VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_FILE_DATA, VBOX_SHARED_CLIPBOARD_CPARMS_READ_FILE_DATA);722 Msg.uContext.SetUInt32(0);723 Msg.pvData.SetPtr(pvData, cbData);724 Msg.cbData.SetUInt32(0);725 685 Msg.pvChecksum.SetPtr(NULL, 0); 726 686 Msg.cbChecksum.SetUInt32(0); … … 729 689 if (RT_SUCCESS(rc)) 730 690 { 731 /** @todo Context ID not used yet. */ 732 rc = Msg.cbData.GetUInt32(pcbRead); AssertRC(rc); 733 AssertReturn(cbData >= *pcbRead, VERR_TOO_MUCH_DATA); 734 /** @todo Add checksum support. */ 735 } 736 737 return rc; 738 } 739 740 /** 741 * Writes a file data chunk to the host. 742 * 743 * @returns VBox status code. 744 * @param idClient The client id returned by VbglR3ClipboardConnect(). 745 * @param pvData Data chunk to write. 746 * @param cbData Size (in bytes) of data chunk to write. 747 * @param pcbWritten Returns how many bytes written. 748 */ 749 VBGLR3DECL(int) VbglR3ClipboardWriteFileData(HGCMCLIENTID idClient, void *pvData, uint32_t cbData, uint32_t *pcbWritten) 750 { 751 AssertPtrReturn(pvData, VERR_INVALID_POINTER); 752 AssertReturn(cbData, VERR_INVALID_PARAMETER); 753 AssertPtrReturn(pcbWritten, VERR_INVALID_POINTER); 754 755 VBoxClipboardWriteFileDataMsg MsgData; 756 RT_ZERO(MsgData); 757 758 VBGL_HGCM_HDR_INIT(&MsgData.hdr, idClient, VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_FILE_DATA, VBOX_SHARED_CLIPBOARD_CPARMS_READ_FILE_DATA); 759 MsgData.uContext.SetUInt32(0); /* Context ID; unused at the moment. */ 760 MsgData.pvData.SetPtr(pvData, cbData); 761 MsgData.cbData.SetUInt32(cbData); 762 MsgData.pvChecksum.SetPtr(NULL, 0); 763 MsgData.cbChecksum.SetUInt32(0); 764 765 int rc = VbglR3HGCMCall(&MsgData.hdr, sizeof(MsgData)); 766 if (RT_SUCCESS(rc)) 767 { 768 *pcbWritten = cbData; 769 } 770 691 if (pcbWritten) 692 *pcbWritten = cbData; 693 } 694 695 LogFlowFuncLeaveRC(rc); 771 696 return rc; 772 697 } … … 827 752 { 828 753 int rc = vbglR3ClipboardWriteDataRaw(idClient, fFormat, pv, cb); 829 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST830 if (RT_FAILURE(rc))831 {832 int rc2 = vbglR3ClipboardWriteErrorInternal(idClient, rc);833 if (RT_FAILURE(rc2))834 LogFlowFunc(("Unable to send error (%Rrc) to host, rc=%Rrc\n", rc, rc2));835 }836 #endif837 754 838 755 return rc; … … 847 764 * @param rcErr Error (IPRT-style) to send. 848 765 */ 849 static int vbglR3ClipboardWriteErrorInternal(HGCMCLIENTID idClient, int rcErr)766 VBGLR3DECL(int) VbglR3ClipboardWriteError(HGCMCLIENTID idClient, int rcErr) 850 767 { 851 768 VBoxClipboardWriteErrorMsg Msg; 852 769 RT_ZERO(Msg); 853 770 854 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_ERROR, 2); 771 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_GUEST_FN_ERROR, VBOX_SHARED_CLIPBOARD_CPARMS_ERROR); 772 855 773 /** @todo Context ID not used yet. */ 856 774 Msg.uContext.SetUInt32(0); … … 859 777 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg)); 860 778 861 /*862 * Never return an error if the host did not accept the error at the current863 * time. This can be due to the host not having any appropriate callbacks864 * set which would handle that error.865 *866 * bird: Looks like VERR_NOT_SUPPORTED is what the host will return if it867 * doesn't an appropriate callback. The code used to ignore ALL errors868 * the host would return, also relevant ones.869 */870 779 if (RT_FAILURE(rc)) 871 780 LogFlowFunc(("Sending error %Rrc failed with rc=%Rrc\n", rcErr, rc)); … … 873 782 rc = VINF_SUCCESS; 874 783 875 return rc; 876 } 877 878 /** 879 * Writes an error back to the host. 880 * 881 * @returns IPRT status code. 882 * @param idClient The client id returned by VbglR3ClipboardConnect(). 883 * @param rcErr Error (IPRT-style) to send. 884 */ 885 VBGLR3DECL(int) vbglR3ClipboardWriteError(HGCMCLIENTID idClient, int rcErr) 886 { 887 return vbglR3ClipboardWriteErrorInternal(idClient, rcErr); 784 if (RT_FAILURE(rc)) 785 LogRel(("Shared Clipboard: Reporting error %Rrc to the host failed with %Rrc\n", rcErr, rc)); 786 787 LogFlowFuncLeaveRC(rc); 788 return rc; 888 789 } 889 790 #endif /* VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */ -
trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibDragAndDrop.cpp
r78080 r79497 359 359 * @returns IPRT status code. 360 360 * @param pCtx DnD context to use. 361 * @param p DataHdr DnD data header to use. Needed for accounting.361 * @param pListHdr DnD data header to use. Needed for accounting. 362 362 * @param pDroppedFiles Dropped files object to use for maintaining the file creation / locking. 363 363 */ 364 static int vbglR3DnDHGRecvURIData(PVBGLR3GUESTDNDCMDCTX pCtx, PVBOXDNDSND DATAHDR pDataHdr, DnDDroppedFiles *pDroppedFiles)364 static int vbglR3DnDHGRecvURIData(PVBGLR3GUESTDNDCMDCTX pCtx, PVBOXDNDSNDListHdr pListHdr, DnDDroppedFiles *pDroppedFiles) 365 365 { 366 366 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 367 AssertPtrReturn(p DataHdr, VERR_INVALID_POINTER);367 AssertPtrReturn(pListHdr, VERR_INVALID_POINTER); 368 368 AssertPtrReturn(pDroppedFiles, VERR_INVALID_POINTER); 369 369 370 370 /* Only count the raw data minus the already received meta data. */ 371 Assert(p DataHdr->cbTotal >= pDataHdr->cbMeta);372 uint64_t cbToRecvBytes = p DataHdr->cbTotal - pDataHdr->cbMeta;373 uint64_t cToRecvObjs = p DataHdr->cObjects;371 Assert(pListHdr->cbTotal >= pListHdr->cbMeta); 372 uint64_t cbToRecvBytes = pListHdr->cbTotal - pListHdr->cbMeta; 373 uint64_t cToRecvObjs = pListHdr->cObjects; 374 374 375 375 LogFlowFunc(("cbToRecvBytes=%RU64, cToRecvObjs=%RU64, (cbTotal=%RU64, cbMeta=%RU32)\n", 376 cbToRecvBytes, cToRecvObjs, p DataHdr->cbTotal, pDataHdr->cbMeta));376 cbToRecvBytes, cToRecvObjs, pListHdr->cbTotal, pListHdr->cbMeta)); 377 377 378 378 /* Anything to do at all? */ … … 641 641 * @returns IPRT status code. 642 642 * @param pCtx DnD context to use. 643 * @param p DataHdr DnD data header to use. Need for accounting and stuff.643 * @param pListHdr DnD data header to use. Need for accounting and stuff. 644 644 * @param pvData Where to store the received data from the host. 645 645 * @param cbData Size (in bytes) of where to store the received data. 646 646 * @param pcbDataRecv Where to store the received amount of data (in bytes). 647 647 */ 648 static int vbglR3DnDHGRecvDataRaw(PVBGLR3GUESTDNDCMDCTX pCtx, PVBOXDNDSND DATAHDR pDataHdr,648 static int vbglR3DnDHGRecvDataRaw(PVBGLR3GUESTDNDCMDCTX pCtx, PVBOXDNDSNDListHdr pListHdr, 649 649 void *pvData, uint32_t cbData, uint32_t *pcbDataRecv) 650 650 { 651 651 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 652 AssertPtrReturn(p DataHdr, VERR_INVALID_POINTER);652 AssertPtrReturn(pListHdr, VERR_INVALID_POINTER); 653 653 AssertPtrReturn(pvData, VERR_INVALID_POINTER); 654 654 AssertReturn(cbData, VERR_INVALID_PARAMETER); … … 694 694 * @returns IPRT status code. 695 695 * @param pCtx DnD context to use. 696 * @param p DataHdr Where to store the receivd DnD data header.697 */ 698 static int vbglR3DnDHGRecv DataHdr(PVBGLR3GUESTDNDCMDCTX pCtx, PVBOXDNDSNDDATAHDR pDataHdr)696 * @param pListHdr Where to store the receivd DnD data header. 697 */ 698 static int vbglR3DnDHGRecvListHdr(PVBGLR3GUESTDNDCMDCTX pCtx, PVBOXDNDSNDListHdr pListHdr) 699 699 { 700 700 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 701 AssertPtrReturn(p DataHdr, VERR_INVALID_POINTER);701 AssertPtrReturn(pListHdr, VERR_INVALID_POINTER); 702 702 703 703 Assert(pCtx->uProtocol >= 3); /* Only for protocol v3 and up. */ 704 704 705 VBOXDNDHGSEND DATAHDRMSG Msg;705 VBOXDNDHGSENDListHdrMSG Msg; 706 706 RT_ZERO(Msg); 707 707 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, HOST_DND_HG_SND_DATA_HDR, 12); … … 711 711 Msg.cbTotal.SetUInt64(0); 712 712 Msg.cbMeta.SetUInt32(0); 713 Msg.pvMetaFmt.SetPtr(p DataHdr->pvMetaFmt, pDataHdr->cbMetaFmt);713 Msg.pvMetaFmt.SetPtr(pListHdr->pvMetaFmt, pListHdr->cbMetaFmt); 714 714 Msg.cbMetaFmt.SetUInt32(0); 715 715 Msg.cObjects.SetUInt64(0); 716 716 Msg.enmCompression.SetUInt32(0); 717 717 Msg.enmChecksumType.SetUInt32(0); 718 Msg.pvChecksum.SetPtr(p DataHdr->pvChecksum, pDataHdr->cbChecksum);718 Msg.pvChecksum.SetPtr(pListHdr->pvChecksum, pListHdr->cbChecksum); 719 719 Msg.cbChecksum.SetUInt32(0); 720 720 … … 723 723 { 724 724 /* Msg.uContext not needed here. */ 725 Msg.uFlags.GetUInt32(&p DataHdr->uFlags);726 Msg.uScreenId.GetUInt32(&p DataHdr->uScreenId);727 Msg.cbTotal.GetUInt64(&p DataHdr->cbTotal);728 Msg.cbMeta.GetUInt32(&p DataHdr->cbMeta);729 Msg.cbMetaFmt.GetUInt32(&p DataHdr->cbMetaFmt);730 Msg.cObjects.GetUInt64(&p DataHdr->cObjects);731 Msg.enmCompression.GetUInt32(&p DataHdr->enmCompression);732 Msg.enmChecksumType.GetUInt32((uint32_t *)&p DataHdr->enmChecksumType);733 Msg.cbChecksum.GetUInt32(&p DataHdr->cbChecksum);725 Msg.uFlags.GetUInt32(&pListHdr->uFlags); 726 Msg.uScreenId.GetUInt32(&pListHdr->uScreenId); 727 Msg.cbTotal.GetUInt64(&pListHdr->cbTotal); 728 Msg.cbMeta.GetUInt32(&pListHdr->cbMeta); 729 Msg.cbMetaFmt.GetUInt32(&pListHdr->cbMetaFmt); 730 Msg.cObjects.GetUInt64(&pListHdr->cObjects); 731 Msg.enmCompression.GetUInt32(&pListHdr->enmCompression); 732 Msg.enmChecksumType.GetUInt32((uint32_t *)&pListHdr->enmChecksumType); 733 Msg.cbChecksum.GetUInt32(&pListHdr->cbChecksum); 734 734 } 735 735 … … 744 744 * @returns IPRT status code. 745 745 * @param pCtx DnD context to use. 746 * @param p DataHdr Where to store the data header data.746 * @param pListHdr Where to store the data header data. 747 747 * @param ppvData Returns the received meta data. Needs to be free'd by the caller. 748 748 * @param pcbData Where to store the size (in bytes) of the received meta data. 749 749 */ 750 static int vbglR3DnDHGRecvDataLoop(PVBGLR3GUESTDNDCMDCTX pCtx, PVBOXDNDSND DATAHDR pDataHdr,750 static int vbglR3DnDHGRecvDataLoop(PVBGLR3GUESTDNDCMDCTX pCtx, PVBOXDNDSNDListHdr pListHdr, 751 751 void **ppvData, uint64_t *pcbData) 752 752 { 753 753 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 754 AssertPtrReturn(p DataHdr, VERR_INVALID_POINTER);754 AssertPtrReturn(pListHdr, VERR_INVALID_POINTER); 755 755 AssertPtrReturn(ppvData, VERR_INVALID_POINTER); 756 756 AssertPtrReturn(pcbData, VERR_INVALID_POINTER); … … 761 761 LogFlowFuncEnter(); 762 762 763 rc = vbglR3DnDHGRecv DataHdr(pCtx, pDataHdr);763 rc = vbglR3DnDHGRecvListHdr(pCtx, pListHdr); 764 764 if (RT_FAILURE(rc)) 765 765 return rc; 766 766 767 LogFlowFunc(("cbTotal=%RU64, cbMeta=%RU32, cObjects=%RU32\n", p DataHdr->cbTotal, pDataHdr->cbMeta, pDataHdr->cObjects));768 if (p DataHdr->cbMeta)767 LogFlowFunc(("cbTotal=%RU64, cbMeta=%RU32, cObjects=%RU32\n", pListHdr->cbTotal, pListHdr->cbMeta, pListHdr->cObjects)); 768 if (pListHdr->cbMeta) 769 769 { 770 770 uint64_t cbDataTmp = 0; 771 void *pvDataTmp = RTMemAlloc(p DataHdr->cbMeta);771 void *pvDataTmp = RTMemAlloc(pListHdr->cbMeta); 772 772 if (!pvDataTmp) 773 773 rc = VERR_NO_MEMORY; … … 776 776 { 777 777 uint8_t *pvDataOff = (uint8_t *)pvDataTmp; 778 while (cbDataTmp < p DataHdr->cbMeta)778 while (cbDataTmp < pListHdr->cbMeta) 779 779 { 780 rc = vbglR3DnDHGRecvDataRaw(pCtx, p DataHdr,781 pvDataOff, RT_MIN(p DataHdr->cbMeta - cbDataTmp, pCtx->cbMaxChunkSize),780 rc = vbglR3DnDHGRecvDataRaw(pCtx, pListHdr, 781 pvDataOff, RT_MIN(pListHdr->cbMeta - cbDataTmp, pCtx->cbMaxChunkSize), 782 782 &cbDataRecv); 783 783 if (RT_SUCCESS(rc)) 784 784 { 785 785 LogFlowFunc(("cbDataRecv=%RU32, cbDataTmp=%RU64\n", cbDataRecv, cbDataTmp)); 786 Assert(cbDataTmp + cbDataRecv <= p DataHdr->cbMeta);786 Assert(cbDataTmp + cbDataRecv <= pListHdr->cbMeta); 787 787 cbDataTmp += cbDataRecv; 788 788 pvDataOff += cbDataRecv; … … 794 794 if (RT_SUCCESS(rc)) 795 795 { 796 Assert(cbDataTmp == p DataHdr->cbMeta);796 Assert(cbDataTmp == pListHdr->cbMeta); 797 797 798 798 LogFlowFunc(("Received %RU64 bytes of data\n", cbDataTmp)); … … 833 833 /* The rest is optional. */ 834 834 835 VBOXDND DATAHDR dataHdr;836 RT_ZERO( dataHdr);835 VBOXDNDListHdr ListHdr; 836 RT_ZERO(ListHdr); 837 837 838 838 AssertMsg(pCtx->cbMaxChunkSize, ("Maximum chunk size must not be 0\n")); 839 839 840 dataHdr.cbMetaFmt = pCtx->cbMaxChunkSize;841 dataHdr.pvMetaFmt = RTMemAlloc(dataHdr.cbMetaFmt);842 if (! dataHdr.pvMetaFmt)840 ListHdr.cbMetaFmt = pCtx->cbMaxChunkSize; 841 ListHdr.pvMetaFmt = RTMemAlloc(ListHdr.cbMetaFmt); 842 if (!ListHdr.pvMetaFmt) 843 843 return VERR_NO_MEMORY; 844 844 … … 849 849 uint64_t cbData = 0; 850 850 851 int rc = vbglR3DnDHGRecvDataLoop(pCtx, & dataHdr, &pvData, &cbData);851 int rc = vbglR3DnDHGRecvDataLoop(pCtx, &ListHdr, &pvData, &cbData); 852 852 if (RT_SUCCESS(rc)) 853 853 { … … 860 860 * VBoxTray) small by not having too much redundant code. 861 861 */ 862 Assert( dataHdr.cbMetaFmt);863 AssertPtr( dataHdr.pvMetaFmt);864 if (DnDMIMEHasFileURLs((char *) dataHdr.pvMetaFmt, dataHdr.cbMetaFmt)) /* URI data. */862 Assert(ListHdr.cbMetaFmt); 863 AssertPtr(ListHdr.pvMetaFmt); 864 if (DnDMIMEHasFileURLs((char *)ListHdr.pvMetaFmt, ListHdr.cbMetaFmt)) /* URI data. */ 865 865 { 866 866 AssertPtr(pvData); … … 869 869 rc = lstURI.SetFromURIData(pvData, cbData, 0 /* fFlags */); 870 870 if (RT_SUCCESS(rc)) 871 rc = vbglR3DnDHGRecvURIData(pCtx, & dataHdr, &droppedFiles);871 rc = vbglR3DnDHGRecvURIData(pCtx, &ListHdr, &droppedFiles); 872 872 873 873 if (RT_SUCCESS(rc)) /** @todo Remove this block as soon as we hand in DnDURIList. */ … … 905 905 } 906 906 907 if ( dataHdr.pvMetaFmt)908 RTMemFree( dataHdr.pvMetaFmt);907 if (ListHdr.pvMetaFmt) 908 RTMemFree(ListHdr.pvMetaFmt); 909 909 910 910 if (RT_SUCCESS(rc)) … … 1480 1480 * @param pvData Data block to send. 1481 1481 * @param cbData Size (in bytes) of data block to send. 1482 * @param p DataHdr Data header to use -- needed for accounting.1482 * @param pListHdr Data header to use -- needed for accounting. 1483 1483 */ 1484 1484 static int vbglR3DnDGHSendDataInternal(PVBGLR3GUESTDNDCMDCTX pCtx, 1485 void *pvData, uint64_t cbData, PVBOXDNDSND DATAHDR pDataHdr)1485 void *pvData, uint64_t cbData, PVBOXDNDSNDListHdr pListHdr) 1486 1486 { 1487 1487 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 1488 1488 AssertPtrReturn(pvData, VERR_INVALID_POINTER); 1489 1489 AssertReturn(cbData, VERR_INVALID_PARAMETER); 1490 AssertPtrReturn(p DataHdr, VERR_INVALID_POINTER);1491 1492 VBOXDNDGHSEND DATAHDRMSG MsgHdr;1490 AssertPtrReturn(pListHdr, VERR_INVALID_POINTER); 1491 1492 VBOXDNDGHSENDListHdrMSG MsgHdr; 1493 1493 RT_ZERO(MsgHdr); 1494 1494 … … 1497 1497 MsgHdr.uFlags.SetUInt32(0); /** @todo Not used yet. */ 1498 1498 MsgHdr.uScreenId.SetUInt32(0); /** @todo Not used for guest->host (yet). */ 1499 MsgHdr.cbTotal.SetUInt64(p DataHdr->cbTotal);1500 MsgHdr.cbMeta.SetUInt32(p DataHdr->cbMeta);1501 MsgHdr.pvMetaFmt.SetPtr(p DataHdr->pvMetaFmt, pDataHdr->cbMetaFmt);1502 MsgHdr.cbMetaFmt.SetUInt32(p DataHdr->cbMetaFmt);1503 MsgHdr.cObjects.SetUInt64(p DataHdr->cObjects);1499 MsgHdr.cbTotal.SetUInt64(pListHdr->cbTotal); 1500 MsgHdr.cbMeta.SetUInt32(pListHdr->cbMeta); 1501 MsgHdr.pvMetaFmt.SetPtr(pListHdr->pvMetaFmt, pListHdr->cbMetaFmt); 1502 MsgHdr.cbMetaFmt.SetUInt32(pListHdr->cbMetaFmt); 1503 MsgHdr.cObjects.SetUInt64(pListHdr->cObjects); 1504 1504 MsgHdr.enmCompression.SetUInt32(0); /** @todo Not used yet. */ 1505 1505 MsgHdr.enmChecksumType.SetUInt32(RTDIGESTTYPE_INVALID); /** @todo Not used yet. */ … … 1510 1510 1511 1511 LogFlowFunc(("cbTotal=%RU64, cbMeta=%RU32, cObjects=%RU64, rc=%Rrc\n", 1512 p DataHdr->cbTotal, pDataHdr->cbMeta, pDataHdr->cObjects, rc));1512 pListHdr->cbTotal, pListHdr->cbMeta, pListHdr->cObjects, rc)); 1513 1513 1514 1514 if (RT_SUCCESS(rc)) … … 1733 1733 /* cbData can be 0. */ 1734 1734 1735 VBOXDND DATAHDR dataHdr;1736 RT_ZERO( dataHdr);1735 VBOXDNDListHdr ListHdr; 1736 RT_ZERO(ListHdr); 1737 1737 1738 1738 /* For raw data only the total size is required to be specified. */ 1739 dataHdr.cbTotal = cbData;1740 1741 return vbglR3DnDGHSendDataInternal(pCtx, pvData, cbData, & dataHdr);1739 ListHdr.cbTotal = cbData; 1740 1741 return vbglR3DnDGHSendDataInternal(pCtx, pvData, cbData, &ListHdr); 1742 1742 } 1743 1743 … … 1786 1786 const uint32_t cbMetaFmt = (uint32_t)strlen(szMetaFmt) + 1; /* Include termination. */ 1787 1787 1788 VBOXDND DATAHDR dataHdr;1789 dataHdr.uFlags = 0; /* Flags not used yet. */1790 dataHdr.cbTotal = cbTotal;1791 dataHdr.cbMeta = cbURLIist;1792 dataHdr.pvMetaFmt = (void *)szMetaFmt;1793 dataHdr.cbMetaFmt = cbMetaFmt;1794 dataHdr.cObjects = lstURI.GetTotalCount();1788 VBOXDNDListHdr ListHdr; 1789 ListHdr.uFlags = 0; /* Flags not used yet. */ 1790 ListHdr.cbTotal = cbTotal; 1791 ListHdr.cbMeta = cbURLIist; 1792 ListHdr.pvMetaFmt = (void *)szMetaFmt; 1793 ListHdr.cbMetaFmt = cbMetaFmt; 1794 ListHdr.cObjects = lstURI.GetTotalCount(); 1795 1795 1796 1796 rc = vbglR3DnDGHSendDataInternal(pCtx, 1797 pvURIList, cbURLIist, & dataHdr);1797 pvURIList, cbURLIist, &ListHdr); 1798 1798 } 1799 1799 else -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceClipboard-os2.cpp
r78346 r79497 884 884 uint32_t Msg; 885 885 uint32_t fFormats; 886 rc = VbglR3ClipboardGetHostMsg (g_u32ClientId, &Msg, &fFormats);886 rc = VbglR3ClipboardGetHostMsgOld(g_u32ClientId, &Msg, &fFormats); 887 887 if (RT_SUCCESS(rc)) 888 888 { -
trunk/src/VBox/Additions/haiku/VBoxTray/VBoxClipboard.cpp
r78346 r79497 375 375 uint32_t u32Msg; 376 376 uint32_t u32Formats; 377 int rc = VbglR3ClipboardGetHostMsg (fClientId, &u32Msg, &u32Formats);377 int rc = VbglR3ClipboardGetHostMsgOld(fClientId, &u32Msg, &u32Formats); 378 378 if (RT_SUCCESS(rc)) 379 379 { -
trunk/src/VBox/Additions/x11/VBoxClient/clipboard.cpp
r78581 r79497 224 224 uint32_t Msg; 225 225 uint32_t fFormats; 226 rc = VbglR3ClipboardGetHostMsg (g_ctx.client, &Msg, &fFormats);226 rc = VbglR3ClipboardGetHostMsgOld(g_ctx.client, &Msg, &fFormats); 227 227 if (RT_SUCCESS(rc)) 228 228 { -
trunk/src/VBox/GuestHost/SharedClipboard/ClipboardDataObjectImpl-win.cpp
r79366 r79497 34 34 #include <iprt/win/shlwapi.h> 35 35 36 #include <iprt/err.h> 36 37 #include <iprt/path.h> 37 38 #include <iprt/semaphore.h> … … 121 122 m_enmStatus = Initialized; 122 123 123 int rc2 = RTSemEventCreate(&m_Event MetaDataComplete);124 int rc2 = RTSemEventCreate(&m_EventListComplete); 124 125 AssertRC(rc2); 126 rc2 = RTSemEventCreate(&m_EventTransferComplete); 127 AssertRC(rc2); 125 128 } 126 129 … … 130 133 VBoxClipboardWinDataObject::~VBoxClipboardWinDataObject(void) 131 134 { 132 RTSemEventDestroy(m_EventMetaDataComplete); 135 RTSemEventDestroy(m_EventListComplete); 136 RTSemEventDestroy(m_EventTransferComplete); 133 137 134 138 if (m_pStream) … … 216 220 } 217 221 222 /* static */ 223 224 /** 225 * Thread for reading URI data. 226 * The data object needs the (high level, root) URI listing at the time of ::GetData(), so we need 227 * to block and wait until we have this data (via this thread) and continue. 228 * 229 * @returns VBox status code. 230 * @param ThreadSelf Thread handle. Unused at the moment. 231 * @param pvUser Pointer to user-provided data. Of type VBoxClipboardWinDataObject. 232 */ 233 DECLCALLBACK(int) VBoxClipboardWinDataObject::readThread(RTTHREAD ThreadSelf, void *pvUser) 234 { 235 RT_NOREF(ThreadSelf); 236 237 LogFlowFuncEnter(); 238 239 VBoxClipboardWinDataObject *pThis = (VBoxClipboardWinDataObject *)pvUser; 240 241 PSHAREDCLIPBOARDURITRANSFER pTransfer = pThis->m_pTransfer; 242 AssertPtr(pTransfer); 243 244 pTransfer->Thread.fStarted = true; 245 246 RTThreadUserSignal(RTThreadSelf()); 247 248 int rc = SharedClipboardURITransferOpen(pTransfer); 249 if (RT_SUCCESS(rc)) 250 { 251 VBOXCLIPBOARDLISTHDR Hdr; 252 rc = SharedClipboardURIListHdrInit(&Hdr); 253 if (RT_SUCCESS(rc)) 254 { 255 VBOXCLIPBOARDLISTHANDLE hList; 256 rc = SharedClipboardURITransferListOpen(pTransfer, &Hdr, &hList); 257 if (RT_SUCCESS(rc)) 258 { 259 LogFlowFunc(("hList=%RU64, cTotalObjects=%RU64, cbTotalSize=%RU64\n\n", 260 hList, Hdr.cTotalObjects, Hdr.cbTotalSize)); 261 262 for (uint64_t i = 0; i < Hdr.cTotalObjects; i++) 263 { 264 VBOXCLIPBOARDLISTENTRY Entry; 265 rc = SharedClipboardURITransferListRead(pTransfer, hList, &Entry); 266 if (RT_SUCCESS(rc)) 267 { 268 269 } 270 else 271 break; 272 273 if (pTransfer->Thread.fStop) 274 break; 275 } 276 277 if (RT_SUCCESS(rc)) 278 { 279 /* 280 * Signal the "list complete" event so that this data object can return (valid) data via ::GetData(). 281 * This in turn then will create IStream instances (by the OS) for each file system object to handle. 282 */ 283 int rc2 = RTSemEventSignal(pThis->m_EventListComplete); 284 AssertRC(rc2); 285 286 LogFlowFunc(("Waiting for transfer to complete ...\n")); 287 288 /* Transferring stuff can take a while, so don't use any timeout here. */ 289 rc2 = RTSemEventWait(pThis->m_EventTransferComplete, RT_INDEFINITE_WAIT); 290 AssertRC(rc2); 291 } 292 293 SharedClipboardURITransferListClose(pTransfer, hList); 294 } 295 296 SharedClipboardURIListHdrDestroy(&Hdr); 297 } 298 299 SharedClipboardURITransferClose(pTransfer); 300 } 301 302 LogFlowFuncLeaveRC(rc); 303 return rc; 304 } 305 218 306 /** 219 307 * Creates a FILEGROUPDESCRIPTOR object from a given URI transfer and stores the result into an HGLOBAL object. … … 232 320 LogFlowFuncEnter(); 233 321 234 SharedClipboardURIList *pURIList = SharedClipboardURITransferGetList(pTransfer);235 if (!pURIList)236 return VERR_WRONG_ORDER;237 238 322 const size_t cbFileGroupDescriptor = fUnicode ? sizeof(FILEGROUPDESCRIPTORW) : sizeof(FILEGROUPDESCRIPTORA); 239 323 const size_t cbFileDescriptor = fUnicode ? sizeof(FILEDESCRIPTORW) : sizeof(FILEDESCRIPTORA); 240 324 241 const UINT cItems = (UINT)pURIList->GetRootCount(); /** @todo UINT vs. uint64_t */ 325 const UINT cItems = (UINT)0; /** @todo UINT vs. uint64_t */ 326 if (!cItems) 327 return VERR_NOT_FOUND; 328 242 329 const size_t cbFGD = cbFileGroupDescriptor + (cbFileDescriptor * (cItems - 1)); 243 330 … … 254 341 255 342 char *pszFileSpec = NULL; 256 343 #if 0 257 344 for (UINT i = 0; i < cItems; i++) 258 345 { … … 326 413 #endif 327 414 } 415 #endif 328 416 329 417 if (pszFileSpec) … … 393 481 #endif 394 482 { 395 int rc = SharedClipboardURITransferPrepare(m_pTransfer); 396 if (RT_SUCCESS(rc)) 483 const bool fUnicode = lIndex == FormatIndex_FileDescriptorW; 484 485 LogFlowFunc(("FormatIndex_FileDescriptor%s\n", fUnicode ? "W" : "A")); 486 487 int rc; 488 489 /* The caller can call GetData() several times, so make sure we don't do the same transfer multiple times. */ 490 if (SharedClipboardURITransferGetStatus(m_pTransfer) == SHAREDCLIPBOARDURITRANSFERSTATUS_NONE) 397 491 { 398 const bool fUnicode = lIndex == FormatIndex_FileDescriptorW; 399 400 LogFlowFunc(("FormatIndex_FileDescriptor%s\n", fUnicode ? "W" : "A")); 401 402 /* Start the transfer asynchronously in a separate thread. */ 403 rc = SharedClipboardURITransferRun(m_pTransfer, true /* fAsync */); 492 rc = SharedClipboardURITransferPrepare(m_pTransfer); 404 493 if (RT_SUCCESS(rc)) 405 494 { 406 /* Wait for the meta data to arrive. */ 407 LogFlowFunc(("Waiting for meta data to arrive ...\n")); 408 rc = RTSemEventWait(m_EventMetaDataComplete, 30 * 1000 /* 30s timeout */); 495 /* Start the transfer asynchronously in a separate thread. */ 496 rc = SharedClipboardURITransferRun(m_pTransfer, &VBoxClipboardWinDataObject::readThread, this); 409 497 if (RT_SUCCESS(rc)) 410 498 { 411 HGLOBAL hGlobal;412 rc = createFileGroupDescriptorFromTransfer(m_pTransfer, fUnicode, &hGlobal);499 LogFunc(("Waiting for listing to arrive ...\n")); 500 rc = RTSemEventWait(m_EventListComplete, 5 * 60 * 1000 /* 5 min timeout */); 413 501 if (RT_SUCCESS(rc)) 414 502 { 415 pMedium->tymed = TYMED_HGLOBAL; 416 pMedium->hGlobal = hGlobal; 417 /* Note: hGlobal now is being owned by pMedium / the caller. */ 418 419 hr = S_OK; 503 LogFunc(("Listing complete\n")); 504 505 HGLOBAL hGlobal; 506 rc = createFileGroupDescriptorFromTransfer(m_pTransfer, fUnicode, &hGlobal); 507 if (RT_SUCCESS(rc)) 508 { 509 pMedium->tymed = TYMED_HGLOBAL; 510 pMedium->hGlobal = hGlobal; 511 /* Note: hGlobal now is being owned by pMedium / the caller. */ 512 513 hr = S_OK; 514 } 420 515 } 421 516 } 422 517 } 423 424 if (RT_FAILURE(rc))425 LogRel(("Shared Clipboard: Data object unable to receive meta data, rc=%Rrc\n", rc));426 518 } 519 else 520 rc = VERR_ALREADY_EXISTS; 521 522 if (RT_FAILURE(rc)) 523 LogRel(("Shared Clipboard: Data object unable to get data, rc=%Rrc\n", rc)); 524 427 525 break; 428 526 } … … 588 686 LogFlowFuncLeaveRC(VINF_SUCCESS); 589 687 return VINF_SUCCESS; 590 }591 592 DECLCALLBACK(void) VBoxClipboardWinDataObject::OnMetaDataComplete(PSHAREDCLIPBOARDURITRANSFER pTransfer)593 {594 LogFlowFuncEnter();595 596 AssertReturnVoid(pTransfer == m_pTransfer);597 598 int rc2 = RTSemEventSignal(m_EventMetaDataComplete);599 AssertRC(rc2);600 688 } 601 689 -
trunk/src/VBox/GuestHost/SharedClipboard/ClipboardStreamImpl-win.cpp
r79347 r79497 160 160 LogFlowThisFuncEnter(); 161 161 162 const SharedClipboardURIObject *pObj = SharedClipboardURITransferGetObject(m_pURITransfer, m_uObjIdx); 163 164 if (pObj->IsComplete()) 162 AssertPtr(m_pURITransfer->State.ObjCtx.pObjInfo); 163 164 const uint64_t cbSize = m_pURITransfer->State.ObjCtx.pObjInfo->cbObject; 165 uint64_t cbProcessed = m_pURITransfer->State.ObjCtx.cbProcessed; 166 167 if (cbProcessed == cbSize) 165 168 { 166 169 /* There can be 0-byte files. */ 167 AssertMsg( pObj->GetSize()== 0, ("Object is complete -- can't read from it anymore\n"));170 AssertMsg(cbSize == 0, ("Object is complete -- can't read from it anymore\n")); 168 171 if (nBytesRead) 169 172 *nBytesRead = 0; /** @todo If the file size is 0, already return at least 1 byte, else the whole operation will fail. */ … … 171 174 } 172 175 173 const uint64_t cbSize = pObj->GetSize();174 const uint64_t cbProcessed = pObj->GetProcessed();175 176 176 const uint32_t cbToRead = RT_MIN(cbSize - cbProcessed, nBytesToRead); 177 177 uint32_t cbRead = 0; … … 181 181 if (cbToRead) 182 182 { 183 rc = m_pURITransfer->ProviderIface.pfn ReadFileData(&m_pURITransfer->ProviderCtx,184 183 rc = m_pURITransfer->ProviderIface.pfnObjRead(&m_pURITransfer->ProviderCtx, m_pURITransfer->State.ObjCtx.uHandle, 184 pvBuffer, cbToRead, 0 /* fFlags */, &cbRead); 185 185 if (RT_SUCCESS(rc)) 186 186 { 187 // pObj->AddProcessed(cbRead); 188 189 if (pObj->IsComplete()) 187 cbProcessed += cbRead; 188 Assert(cbProcessed <= cbSize); 189 190 if (cbProcessed == cbSize) 190 191 m_pParent->OnTransferComplete(); 192 193 m_pURITransfer->State.ObjCtx.cbProcessed = cbProcessed; 191 194 } 192 195 } -
trunk/src/VBox/GuestHost/SharedClipboard/ClipboardURIList.cpp
r79366 r79497 294 294 AssertPtrReturn(pszPath, VERR_INVALID_POINTER); 295 295 296 char *pszPathURI; 297 int rc = SharedClipboardMetaDataConvertToFormat(pszPath, strlen(pszPath), SHAREDCLIPBOARDMETADATAFMT_URI_LIST, 298 (void **)&pszPathURI, NULL /* cbData */); 299 if (RT_SUCCESS(rc)) 300 { 301 rc = AppendURIPath(pszPathURI, fFlags); 302 RTStrFree(pszPathURI); 303 } 304 305 return rc; 296 RT_NOREF(fFlags); 297 298 return VERR_NOT_IMPLEMENTED; 306 299 } 307 300 -
trunk/src/VBox/GuestHost/SharedClipboard/clipboard-uri.cpp
r79366 r79497 23 23 24 24 #include <VBox/err.h> 25 #include <VBox/HostServices/VBoxClipboardSvc.h> 25 26 #include <VBox/GuestHost/SharedClipboard-uri.h> 26 27 27 28 28 29 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 29 static int sharedClipboardURITransferThreadCreate(PSHAREDCLIPBOARDURITRANSFER pTransfer );30 static int sharedClipboardURITransferThreadCreate(PSHAREDCLIPBOARDURITRANSFER pTransfer, PFNRTTHREAD pfnThreadFunc, void *pvUser); 30 31 static int sharedClipboardURITransferThreadDestroy(PSHAREDCLIPBOARDURITRANSFER pTransfer, RTMSINTERVAL uTimeoutMs); 31 static int sharedClipboardURITransferReadThread(RTTHREAD hThread, void *pvUser);32 32 static int sharedClipboardURITransferWriteThread(RTTHREAD hThread, void *pvUser); 33 33 static PSHAREDCLIPBOARDURITRANSFER sharedClipboardURICtxGetTransferInternal(PSHAREDCLIPBOARDURICTX pURI, uint32_t uIdx); 34 35 static void sharedClipboardURITransferMetaDataDestroyInternal(PSHAREDCLIPBOARDURITRANSFER pTransfer);36 34 #endif 37 35 38 36 39 37 /** 40 * Allocates a VBOXCLIPBOARD DATAHDRstructure.38 * Allocates a VBOXCLIPBOARDListHdr structure. 41 39 * 42 40 * @returns VBox status code. 43 * @param pp DataChunk Where to store the allocated VBOXCLIPBOARDDATAHDRstructure on success.44 */ 45 int SharedClipboardURI DataHdrAlloc(PVBOXCLIPBOARDDATAHDR *ppDataHdr)41 * @param ppListEntry Where to store the allocated VBOXCLIPBOARDListHdr structure on success. 42 */ 43 int SharedClipboardURIListHdrAlloc(PVBOXCLIPBOARDLISTHDR *ppListHdr) 46 44 { 47 45 int rc; 48 46 49 PVBOXCLIPBOARDDATAHDR pDataHdr = (PVBOXCLIPBOARDDATAHDR)RTMemAllocZ(sizeof(VBOXCLIPBOARDDATAHDR)); 50 if (pDataHdr) 51 { 52 PSHAREDCLIPBOARDMETADATAFMTDATA pMetaDataFmt 53 = (PSHAREDCLIPBOARDMETADATAFMTDATA)RTMemAllocZ(sizeof(SHAREDCLIPBOARDMETADATAFMTDATA)); 54 if (pMetaDataFmt) 55 { 56 char *pszFmt = NULL; 57 rc = RTStrAAppend(&pszFmt, "VBoxShClURIList"); /** @todo Make this more flexible. Later. */ 58 if (RT_SUCCESS(rc)) 59 { 60 pMetaDataFmt->uVer = 1; 61 pMetaDataFmt->pvFmt = pszFmt; 62 pMetaDataFmt->cbFmt = (uint32_t)strlen(pszFmt) + 1 /* Include terminating zero */; 63 64 pDataHdr->pvMetaFmt = pMetaDataFmt; 65 pDataHdr->cbMetaFmt = sizeof(SHAREDCLIPBOARDMETADATAFMTDATA) + pMetaDataFmt->cbFmt; 66 67 *ppDataHdr = pDataHdr; 68 } 69 } 70 else 71 rc = VERR_NO_MEMORY; 72 73 if (RT_FAILURE(rc)) 74 { 75 RTMemFree(pDataHdr); 76 pDataHdr = NULL; 77 } 47 PVBOXCLIPBOARDLISTHDR pListHdr = (PVBOXCLIPBOARDLISTHDR)RTMemAllocZ(sizeof(VBOXCLIPBOARDLISTHDR)); 48 if (pListHdr) 49 { 50 *ppListHdr = pListHdr; 51 rc = VINF_SUCCESS; 78 52 } 79 53 else … … 85 59 86 60 /** 87 * Frees a VBOXCLIPBOARD DATAHDRstructure.88 * 89 * @param p DataChunk VBOXCLIPBOARDDATAHDRstructure to free.90 */ 91 void SharedClipboardURI DataHdrFree(PVBOXCLIPBOARDDATAHDR pDataHdr)92 { 93 if (!p DataHdr)61 * Frees a VBOXCLIPBOARDListHdr structure. 62 * 63 * @param pListEntry VBOXCLIPBOARDListHdr structure to free. 64 */ 65 void SharedClipboardURIListHdrFree(PVBOXCLIPBOARDLISTHDR pListHdr) 66 { 67 if (!pListHdr) 94 68 return; 95 69 96 70 LogFlowFuncEnter(); 97 71 98 SharedClipboardURI DataHdrDestroy(pDataHdr);99 100 RTMemFree(p DataHdr);101 p DataHdr = NULL;102 } 103 104 /** 105 * Duplicates (allocates) a VBOXCLIPBOARD DATAHDRstructure.106 * 107 * @returns Duplicated VBOXCLIPBOARD DATAHDRstructure on success.108 * @param p DataHdr VBOXCLIPBOARDDATAHDRto duplicate.109 */ 110 PVBOXCLIPBOARD DATAHDR SharedClipboardURIDataHdrDup(PVBOXCLIPBOARDDATAHDR pDataHdr)111 { 112 AssertPtrReturn(p DataHdr, NULL);113 114 PVBOXCLIPBOARD DATAHDR pDataHdrDup = (PVBOXCLIPBOARDDATAHDR)RTMemAlloc(sizeof(VBOXCLIPBOARDDATAHDR));115 if (p DataHdrDup)116 { 117 *p DataHdrDup = *pDataHdr;118 119 if (p DataHdr->pvMetaFmt)72 SharedClipboardURIListHdrDestroy(pListHdr); 73 74 RTMemFree(pListHdr); 75 pListHdr = NULL; 76 } 77 78 /** 79 * Duplicates (allocates) a VBOXCLIPBOARDListHdr structure. 80 * 81 * @returns Duplicated VBOXCLIPBOARDListHdr structure on success. 82 * @param pListHdr VBOXCLIPBOARDListHdr to duplicate. 83 */ 84 PVBOXCLIPBOARDLISTHDR SharedClipboardURIListHdrDup(PVBOXCLIPBOARDLISTHDR pListHdr) 85 { 86 AssertPtrReturn(pListHdr, NULL); 87 88 PVBOXCLIPBOARDLISTHDR pListHdrDup = (PVBOXCLIPBOARDLISTHDR)RTMemAlloc(sizeof(VBOXCLIPBOARDLISTHDR)); 89 if (pListHdrDup) 90 { 91 *pListHdrDup = *pListHdr; 92 93 if (pListHdr->pszFilter) 120 94 { 121 p DataHdrDup->pvMetaFmt = RTMemDup(pDataHdr->pvMetaFmt, pDataHdr->cbMetaFmt);122 p DataHdrDup->cbMetaFmt = pDataHdr->cbMetaFmt;95 pListHdrDup->pszFilter = RTStrDup(pListHdr->pszFilter); 96 pListHdrDup->cbFilter = (uint32_t)strlen(pListHdrDup->pszFilter); 123 97 } 124 125 if (pDataHdr->pvChecksum) 98 } 99 100 return pListHdrDup; 101 } 102 103 /** 104 * Initializes an URI data header struct. 105 * 106 * @returns VBox status code. 107 * @param pListHdr Data header struct to initialize. 108 */ 109 int SharedClipboardURIListHdrInit(PVBOXCLIPBOARDLISTHDR pListHdr) 110 { 111 AssertPtrReturn(pListHdr, VERR_INVALID_POINTER); 112 113 SharedClipboardURIListHdrReset(pListHdr); 114 115 return VINF_SUCCESS; 116 } 117 118 /** 119 * Destroys an URI data header struct. 120 * 121 * @param pListHdr Data header struct to destroy. 122 */ 123 void SharedClipboardURIListHdrDestroy(PVBOXCLIPBOARDLISTHDR pListHdr) 124 { 125 if (!pListHdr) 126 return; 127 128 LogFlowFuncEnter(); 129 130 if (pListHdr->pszFilter) 131 { 132 Assert(pListHdr->cbFilter); 133 134 RTStrFree(pListHdr->pszFilter); 135 pListHdr->pszFilter = NULL; 136 pListHdr->cbFilter = 0; 137 } 138 } 139 140 /** 141 * Resets a VBOXCLIPBOARDListHdr structture. 142 * 143 * @returns VBox status code. 144 * @param pListHdr VBOXCLIPBOARDListHdr structture to reset. 145 */ 146 void SharedClipboardURIListHdrReset(PVBOXCLIPBOARDLISTHDR pListHdr) 147 { 148 AssertPtrReturnVoid(pListHdr); 149 150 LogFlowFuncEnter(); 151 152 RT_BZERO(pListHdr, sizeof(VBOXCLIPBOARDLISTHDR)); 153 } 154 155 /** 156 * Returns whether a given clipboard data header is valid or not. 157 * 158 * @returns \c true if valid, \c false if not. 159 * @param pListHdr Clipboard data header to validate. 160 */ 161 bool SharedClipboardURIListHdrIsValid(PVBOXCLIPBOARDLISTHDR pListHdr) 162 { 163 RT_NOREF(pListHdr); 164 return true; /** @todo Implement this. */ 165 } 166 167 /** 168 * Creates (allocates) and initializes a VBOXCLIPBOARDListEntry structure. 169 * 170 * @param ppDirData Where to return the created VBOXCLIPBOARDListEntry structure on success. 171 */ 172 int SharedClipboardURIListEntryAlloc(PVBOXCLIPBOARDLISTENTRY *ppListEntry) 173 { 174 PVBOXCLIPBOARDLISTENTRY pListEntry = (PVBOXCLIPBOARDLISTENTRY)RTMemAlloc(sizeof(VBOXCLIPBOARDLISTENTRY)); 175 if (!pListEntry) 176 return VERR_NO_MEMORY; 177 178 int rc = SharedClipboardURIListEntryInit(pListEntry); 179 if (RT_SUCCESS(rc)) 180 *ppListEntry = pListEntry; 181 182 return rc; 183 } 184 185 /** 186 * Frees a VBOXCLIPBOARDListEntry structure. 187 * 188 * @param pListEntry VBOXCLIPBOARDListEntry structure to free. 189 */ 190 void SharedClipboardURIListEntryFree(PVBOXCLIPBOARDLISTENTRY pListEntry) 191 { 192 if (!pListEntry) 193 return; 194 195 SharedClipboardURIListEntryDestroy(pListEntry); 196 RTMemFree(pListEntry); 197 } 198 199 /** 200 * Duplicates (allocates) a VBOXCLIPBOARDListEntry structure. 201 * 202 * @returns Duplicated VBOXCLIPBOARDListEntry structure on success. 203 * @param pListEntry VBOXCLIPBOARDListEntry to duplicate. 204 */ 205 PVBOXCLIPBOARDLISTENTRY SharedClipboardURIListEntryDup(PVBOXCLIPBOARDLISTENTRY pListEntry) 206 { 207 AssertPtrReturn(pListEntry, NULL); 208 209 PVBOXCLIPBOARDLISTENTRY pListEntryDup = (PVBOXCLIPBOARDLISTENTRY)RTMemAlloc(sizeof(VBOXCLIPBOARDLISTENTRY)); 210 if (pListEntryDup) 211 { 212 *pListEntryDup = *pListEntry; 213 214 if (pListEntry->pvInfo) 126 215 { 127 p DataHdrDup->pvChecksum = RTMemDup(pDataHdr->pvChecksum, pDataHdr->cbChecksum);128 p DataHdrDup->cbChecksum = pDataHdr->cbChecksum;216 pListEntryDup->pvInfo= RTMemDup(pListEntry->pvInfo, pListEntry->cbInfo); 217 pListEntryDup->cbInfo = pListEntry->cbInfo; 129 218 } 130 219 } 131 220 132 return pDataHdrDup; 133 } 134 135 /** 136 * Returns the size (in bytes) of the announced meta data. 137 * 138 * @returns Announced meta data size in bytes. 139 * @param pDataHdr Data header struct to get announced meta data size for. 140 */ 141 uint32_t SharedClipboardURIDataHdrGetMetaDataSize(PVBOXCLIPBOARDDATAHDR pDataHdr) 142 { 143 AssertPtrReturn(pDataHdr, 0); 144 145 return pDataHdr->cbMeta; 146 } 147 148 /** 149 * Initializes an URI data header struct. 150 * 151 * @returns VBox status code. 152 * @param pDataHdr Data header struct to initialize. 153 */ 154 int SharedClipboardURIDataHdrInit(PVBOXCLIPBOARDDATAHDR pDataHdr) 155 { 156 AssertPtrReturn(pDataHdr, VERR_INVALID_POINTER); 157 158 SharedClipboardURIDataHdrReset(pDataHdr); 221 return pListEntryDup; 222 } 223 224 /** 225 * Initializes a VBOXCLIPBOARDListEntry structure. 226 * 227 * @param pListEntry VBOXCLIPBOARDListEntry structure to initialize. 228 */ 229 int SharedClipboardURIListEntryInit(PVBOXCLIPBOARDLISTENTRY pListEntry) 230 { 231 RT_BZERO(pListEntry, sizeof(VBOXCLIPBOARDLISTENTRY)); 159 232 160 233 return VINF_SUCCESS; … … 162 235 163 236 /** 164 * Destroys an URI data header struct. 165 * 166 * @param pDataHdr Data header struct to destroy. 167 */ 168 void SharedClipboardURIDataHdrDestroy(PVBOXCLIPBOARDDATAHDR pDataHdr) 169 { 170 if (!pDataHdr) 171 return; 172 173 LogFlowFuncEnter(); 174 175 if (pDataHdr->pvMetaFmt) 176 { 177 Assert(pDataHdr->cbMetaFmt); 178 179 RTMemFree(pDataHdr->pvMetaFmt); 180 pDataHdr->pvMetaFmt = NULL; 181 pDataHdr->cbMetaFmt = 0; 182 } 183 184 if (pDataHdr->pvChecksum) 185 { 186 Assert(pDataHdr->cbChecksum); 187 188 RTMemFree(pDataHdr->pvChecksum); 189 pDataHdr->pvChecksum = NULL; 190 pDataHdr->cbChecksum = 0; 191 } 192 } 193 194 /** 195 * Resets a VBOXCLIPBOARDDATAHDR structture. 196 * 197 * @returns VBox status code. 198 * @param pDataHdr VBOXCLIPBOARDDATAHDR structture to reset. 199 */ 200 void SharedClipboardURIDataHdrReset(PVBOXCLIPBOARDDATAHDR pDataHdr) 201 { 202 AssertPtrReturnVoid(pDataHdr); 203 204 LogFlowFuncEnter(); 205 206 RT_BZERO(pDataHdr, sizeof(VBOXCLIPBOARDDATAHDR)); 207 } 208 209 /** 210 * Returns whether a given clipboard data header is valid or not. 237 * Initializes a VBOXCLIPBOARDListEntry structure. 238 * 239 * @param pListEntry VBOXCLIPBOARDListEntry structure to destroy. 240 */ 241 void SharedClipboardURIListEntryDestroy(PVBOXCLIPBOARDLISTENTRY pListEntry) 242 { 243 if (pListEntry->pvInfo) 244 { 245 RTMemFree(pListEntry->pvInfo); 246 pListEntry->pvInfo = NULL; 247 pListEntry->cbInfo = 0; 248 } 249 } 250 251 /** 252 * Returns whether a given clipboard data chunk is valid or not. 211 253 * 212 254 * @returns \c true if valid, \c false if not. 213 * @param pDataHdr Clipboard data header to validate. 214 */ 215 bool SharedClipboardURIDataHdrIsValid(PVBOXCLIPBOARDDATAHDR pDataHdr) 216 { 217 RT_NOREF(pDataHdr); 255 * @param pListEntry Clipboard data chunk to validate. 256 */ 257 bool SharedClipboardURIListEntryIsValid(PVBOXCLIPBOARDLISTENTRY pListEntry) 258 { 259 RT_NOREF(pListEntry); 260 261 /** @todo Verify checksum. */ 262 218 263 return true; /** @todo Implement this. */ 219 264 } 220 265 221 /** 222 * Creates (allocates) and initializes a VBOXCLIPBOARDDATACHUNK structure. 223 * 224 * @param ppDirData Where to return the created VBOXCLIPBOARDDATACHUNK structure on success. 225 */ 226 int SharedClipboardURIDataChunkAlloc(PVBOXCLIPBOARDDATACHUNK *ppDataChunk) 227 { 228 PVBOXCLIPBOARDDATACHUNK pDataChunk = (PVBOXCLIPBOARDDATACHUNK)RTMemAlloc(sizeof(VBOXCLIPBOARDDATACHUNK)); 229 if (!pDataChunk) 230 return VERR_NO_MEMORY; 231 232 int rc = SharedClipboardURIDataChunkInit(pDataChunk); 233 if (RT_SUCCESS(rc)) 234 *ppDataChunk = pDataChunk; 235 236 return rc; 237 } 238 239 /** 240 * Frees a VBOXCLIPBOARDDATACHUNK structure. 241 * 242 * @param pDataChunk VBOXCLIPBOARDDATACHUNK structure to free. 243 */ 244 void SharedClipboardURIDataChunkFree(PVBOXCLIPBOARDDATACHUNK pDataChunk) 245 { 246 if (!pDataChunk) 247 return; 248 249 SharedClipboardURIDataChunkDestroy(pDataChunk); 250 RTMemFree(pDataChunk); 251 } 252 253 /** 254 * Duplicates (allocates) a VBOXCLIPBOARDDATACHUNK structure. 255 * 256 * @returns Duplicated VBOXCLIPBOARDDATACHUNK structure on success. 257 * @param pDataChunk VBOXCLIPBOARDDATACHUNK to duplicate. 258 */ 259 PVBOXCLIPBOARDDATACHUNK SharedClipboardURIDataChunkDup(PVBOXCLIPBOARDDATACHUNK pDataChunk) 260 { 261 AssertPtrReturn(pDataChunk, NULL); 262 263 PVBOXCLIPBOARDDATACHUNK pDataChunkDup = (PVBOXCLIPBOARDDATACHUNK)RTMemAlloc(sizeof(VBOXCLIPBOARDDATACHUNK)); 264 if (pDataChunkDup) 265 { 266 *pDataChunkDup = *pDataChunk; 267 268 if (pDataChunk->pvData) 269 { 270 pDataChunkDup->pvData = RTMemDup(pDataChunk->pvData, pDataChunk->cbData); 271 pDataChunkDup->cbData = pDataChunk->cbData; 272 } 273 274 if (pDataChunk->pvChecksum) 275 { 276 pDataChunkDup->pvChecksum = RTMemDup(pDataChunk->pvChecksum, pDataChunk->cbChecksum); 277 pDataChunkDup->cbChecksum = pDataChunk->cbChecksum; 278 } 279 } 280 281 return pDataChunkDup; 282 } 283 284 /** 285 * Initializes a VBOXCLIPBOARDDATACHUNK structure. 286 * 287 * @param pDataChunk VBOXCLIPBOARDDATACHUNK structure to initialize. 288 */ 289 int SharedClipboardURIDataChunkInit(PVBOXCLIPBOARDDATACHUNK pDataChunk) 290 { 291 RT_BZERO(pDataChunk, sizeof(VBOXCLIPBOARDDATACHUNK)); 292 293 return VINF_SUCCESS; 294 } 295 296 /** 297 * Initializes a VBOXCLIPBOARDDATACHUNK structure. 298 * 299 * @param pDataChunk VBOXCLIPBOARDDATACHUNK structure to destroy. 300 */ 301 void SharedClipboardURIDataChunkDestroy(PVBOXCLIPBOARDDATACHUNK pDataChunk) 302 { 303 if (pDataChunk->pvData) 304 { 305 RTMemFree(pDataChunk->pvData); 306 pDataChunk->pvData = NULL; 307 pDataChunk->cbData = 0; 308 } 309 310 if (pDataChunk->pvChecksum) 311 { 312 RTMemFree(pDataChunk->pvChecksum); 313 pDataChunk->pvChecksum = NULL; 314 pDataChunk->cbChecksum = 0; 315 } 316 } 317 318 /** 319 * Returns whether a given clipboard data chunk is valid or not. 320 * 321 * @returns \c true if valid, \c false if not. 322 * @param pDataChunk Clipboard data chunk to validate. 323 */ 324 bool SharedClipboardURIDataChunkIsValid(PVBOXCLIPBOARDDATACHUNK pDataChunk) 325 { 326 RT_NOREF(pDataChunk); 327 328 /** @todo Verify checksum. */ 329 330 return true; /** @todo Implement this. */ 331 } 332 266 #if 0 333 267 /** 334 268 * Creates (allocates) and initializes a VBOXCLIPBOARDDIRDATA structure. … … 514 448 * @returns \c true if valid, \c false if not. 515 449 * @param pFileHdr Clipboard file header to validate. 516 * @param p DataHdr Data header to use for validation.517 */ 518 bool SharedClipboardURIFileHdrIsValid(PVBOXCLIPBOARDFILEHDR pFileHdr, PVBOXCLIPBOARD DATAHDR pDataHdr)450 * @param pListHdr Data header to use for validation. 451 */ 452 bool SharedClipboardURIFileHdrIsValid(PVBOXCLIPBOARDFILEHDR pFileHdr, PVBOXCLIPBOARDLISTHDR pListHdr) 519 453 { 520 454 if ( !pFileHdr->cbFilePath … … 525 459 return false; 526 460 527 if (pFileHdr->cbSize > p DataHdr->cbTotal)461 if (pFileHdr->cbSize > pListHdr->cbTotalSize) 528 462 return false; 529 463 … … 587 521 * @returns \c true if valid, \c false if not. 588 522 * @param pFileData Clipboard file data to validate. 589 * @param p DataHdr Data header to use for validation.590 */ 591 bool SharedClipboardURIFileDataIsValid(PVBOXCLIPBOARDFILEDATA pFileData, PVBOXCLIPBOARD DATAHDR pDataHdr)592 { 593 RT_NOREF(pFileData, p DataHdr);523 * @param pListHdr Data header to use for validation. 524 */ 525 bool SharedClipboardURIFileDataIsValid(PVBOXCLIPBOARDFILEDATA pFileData, PVBOXCLIPBOARDLISTHDR pListHdr) 526 { 527 RT_NOREF(pFileData, pListHdr); 594 528 return true; 595 529 } 530 #endif 596 531 597 532 /** … … 607 542 LogFlowFuncEnter(); 608 543 609 pObjCtx->pObj = NULL; 544 pObjCtx->uHandle = SHAREDCLIPBOARDOBJHANDLE_INVALID; 545 pObjCtx->pObjInfo = NULL; 610 546 611 547 return VINF_SUCCESS; … … 623 559 LogFlowFuncEnter(); 624 560 625 if (pObjCtx->pObj) 626 { 627 pObjCtx->pObj->Close(); 628 /* Note: Do *not* delete pObj here -- the associated URI list will do this. */ 629 } 630 631 pObjCtx->pObj = NULL; 632 } 633 634 /** 635 * Returns the URI object context's URI object. 636 * 637 * @returns Pointer to the URI object context's URI object. 638 * @param pObjCtx URI object context to return the URI object for. 639 */ 640 SharedClipboardURIObject *SharedClipboardURIObjCtxGetObj(PSHAREDCLIPBOARDCLIENTURIOBJCTX pObjCtx) 641 { 642 AssertPtrReturn(pObjCtx, NULL); 643 return pObjCtx->pObj; 561 pObjCtx->pObjInfo = NULL; 644 562 } 645 563 … … 653 571 { 654 572 return ( pObjCtx 655 && pObjCtx->pObj 656 && pObjCtx->pObj->IsComplete() == false 657 && pObjCtx->pObj->IsOpen()); 573 && pObjCtx->uHandle != SHAREDCLIPBOARDOBJHANDLE_INVALID 574 && pObjCtx->pObjInfo); 658 575 } 659 576 … … 686 603 LogFlowFunc(("enmDir=%RU32, enmSource=%RU32\n", pTransfer->State.enmDir, pTransfer->State.enmSource)); 687 604 688 pTransfer->State.pHeader = NULL; 689 pTransfer->State.pMeta = NULL; 690 pTransfer->pArea = NULL; /* Will be created later if needed. */ 605 pTransfer->pArea = NULL; /* Will be created later if needed. */ 691 606 692 607 pTransfer->Thread.hThread = NIL_RTTHREAD; 693 608 pTransfer->Thread.fCancelled = false; 694 609 pTransfer->Thread.fStarted = false; 610 pTransfer->Thread.fStop = false; 695 611 696 612 pTransfer->pvUser = NULL; … … 743 659 return rc; 744 660 745 SharedClipboardURIDataHdrDestroy(pTransfer->State.pHeader);746 SharedClipboardMetaDataDestroy(pTransfer->State.pMeta);747 748 661 if (pTransfer->pURIList) 749 662 { … … 760 673 SharedClipboardURIObjCtxDestroy(&pTransfer->State.ObjCtx); 761 674 762 RTMemFree(pTransfer);763 pTransfer = NULL;764 765 675 LogFlowFuncLeave(); 766 767 676 return VINF_SUCCESS; 677 } 678 679 int SharedClipboardURITransferOpen(PSHAREDCLIPBOARDURITRANSFER pTransfer) 680 { 681 int rc = VINF_SUCCESS; 682 683 if (pTransfer->ProviderIface.pfnTransferOpen) 684 rc = pTransfer->ProviderIface.pfnTransferOpen(&pTransfer->ProviderCtx); 685 686 LogFlowFuncLeaveRC(rc); 687 return rc; 688 } 689 690 int SharedClipboardURITransferClose(PSHAREDCLIPBOARDURITRANSFER pTransfer) 691 { 692 int rc = VINF_SUCCESS; 693 694 if (pTransfer->ProviderIface.pfnTransferClose) 695 rc = pTransfer->ProviderIface.pfnTransferClose(&pTransfer->ProviderCtx); 696 697 LogFlowFuncLeaveRC(rc); 698 return rc; 699 } 700 701 int SharedClipboardURITransferListOpen(PSHAREDCLIPBOARDURITRANSFER pTransfer, PVBOXCLIPBOARDLISTHDR pListHdr, 702 PVBOXCLIPBOARDLISTHANDLE phList) 703 { 704 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER); 705 AssertPtrReturn(pListHdr, VERR_INVALID_POINTER); 706 /* phList is optional. */ 707 708 int rc = VINF_SUCCESS; 709 710 VBOXCLIPBOARDLISTHANDLE hList = SHAREDCLIPBOARDLISTHANDLE_INVALID; 711 712 if (pTransfer->ProviderIface.pfnListOpen) 713 rc = pTransfer->ProviderIface.pfnListOpen(&pTransfer->ProviderCtx, pListHdr, &hList); 714 715 if (RT_SUCCESS(rc)) 716 { 717 AssertPtr(pTransfer->ProviderIface.pfnListHdrRead); 718 rc = pTransfer->ProviderIface.pfnListHdrRead(&pTransfer->ProviderCtx, hList, pListHdr); 719 } 720 721 if (RT_SUCCESS(rc)) 722 { 723 if (phList) 724 *phList = hList; 725 } 726 else if (pTransfer->ProviderIface.pfnListClose) 727 { 728 int rc2 = pTransfer->ProviderIface.pfnListClose(&pTransfer->ProviderCtx, hList); 729 AssertRC(rc2); 730 } 731 732 LogFlowFuncLeaveRC(rc); 733 return rc; 734 } 735 736 int SharedClipboardURITransferListClose(PSHAREDCLIPBOARDURITRANSFER pTransfer, VBOXCLIPBOARDLISTHANDLE hList) 737 { 738 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER); 739 740 int rc = VINF_SUCCESS; 741 742 if (pTransfer->ProviderIface.pfnListClose) 743 rc = pTransfer->ProviderIface.pfnListClose(&pTransfer->ProviderCtx, hList); 744 745 LogFlowFuncLeaveRC(rc); 746 return rc; 747 } 748 749 int SharedClipboardURITransferListRead(PSHAREDCLIPBOARDURITRANSFER pTransfer, VBOXCLIPBOARDLISTHANDLE hList, 750 PVBOXCLIPBOARDLISTENTRY pEntry) 751 { 752 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER); 753 754 int rc = VINF_SUCCESS; 755 756 if (pTransfer->ProviderIface.pfnListEntryRead) 757 rc = pTransfer->ProviderIface.pfnListEntryRead(&pTransfer->ProviderCtx, hList, pEntry); 758 759 LogFlowFuncLeaveRC(rc); 760 return rc; 761 } 762 763 int SharedClipboardURITransferListWrite(PSHAREDCLIPBOARDURITRANSFER pTransfer, VBOXCLIPBOARDLISTHANDLE hList, 764 PVBOXCLIPBOARDLISTENTRY pEntry) 765 { 766 int rc = VINF_SUCCESS; 767 768 if (pTransfer->ProviderIface.pfnListEntryWrite) 769 rc = pTransfer->ProviderIface.pfnListEntryWrite(&pTransfer->ProviderCtx, hList, pEntry); 770 771 LogFlowFuncLeaveRC(rc); 772 return rc; 773 } 774 775 bool SharedClipboardURITransferListHandleIsValid(PSHAREDCLIPBOARDURITRANSFER pTransfer, VBOXCLIPBOARDLISTHANDLE hList) 776 { 777 RT_NOREF(pTransfer, hList); 778 779 return true; /** @todo Implement this. */ 768 780 } 769 781 … … 791 803 SHAREDCLIPBOARDURITRANSFERCALLBACKDATA callbackData = { pTransfer, pTransfer->Callbacks.pvUser }; 792 804 pTransfer->Callbacks.pfnTransferPrepare(&callbackData); 793 }794 795 if (pTransfer->State.enmDir == SHAREDCLIPBOARDURITRANSFERDIR_READ)796 {797 if (pTransfer->ProviderIface.pfnPrepare)798 rc = pTransfer->ProviderIface.pfnPrepare(&pTransfer->ProviderCtx);799 #if 0800 rc = pTransfer->pURIList->SetFromURIData(SharedClipboardMetaDataRaw(pMeta),801 SharedClipboardMetaDataGetUsed(pMeta),802 SHAREDCLIPBOARDURILIST_FLAGS_NONE);803 /** @todo Verify pvMetaFmt. */804 #endif805 806 sharedClipboardURITransferMetaDataDestroyInternal(pTransfer);807 }808 else if (pTransfer->State.enmDir == SHAREDCLIPBOARDURITRANSFERDIR_WRITE)809 {810 if ( pTransfer->State.pMeta811 && pTransfer->pURIList)812 {813 const PSHAREDCLIPBOARDMETADATA pMeta = pTransfer->State.pMeta;814 815 rc = pTransfer->pURIList->AppendURIPathsFromList((char *)SharedClipboardMetaDataRaw(pMeta),816 SharedClipboardMetaDataGetUsed(pMeta),817 SHAREDCLIPBOARDURILIST_FLAGS_KEEP_OPEN);818 if (RT_SUCCESS(rc))819 {820 PVBOXCLIPBOARDDATAHDR pHeader;821 rc = SharedClipboardURIDataHdrAlloc(&pHeader);822 if (RT_SUCCESS(rc))823 {824 /* The total size also contains the size of the meta data. */825 uint64_t cbTotal = pMeta->cbUsed;826 cbTotal += pTransfer->pURIList->GetTotalBytes();827 828 pHeader->cbTotal = cbTotal;829 pHeader->cbMeta = (uint32_t)SharedClipboardMetaDataGetUsed(pMeta);830 pHeader->cObjects = pTransfer->pURIList->GetTotalCount();831 832 SharedClipboardURIDataHdrDestroy(pTransfer->State.pHeader);833 834 if (RT_SUCCESS(rc))835 {836 LogFlowFunc(("Writing cbTotal=%RU64, cbMeta=%RU32, cObj=%RU64\n",837 pHeader->cbTotal, pHeader->cbMeta, pHeader->cObjects));838 839 pTransfer->State.pHeader = pHeader;840 }841 else842 SharedClipboardURIDataHdrFree(pHeader);843 }844 }845 }846 else847 rc = VERR_WRONG_ORDER;848 }849 else850 {851 rc = VERR_NOT_IMPLEMENTED;852 AssertFailed();853 805 } 854 806 … … 1000 952 1001 953 /** 1002 * Runs (starts) an URI transfer , either in synchronous or asynchronous (threaded) mode.954 * Runs (starts) an URI transfer thread. 1003 955 * 1004 956 * @returns VBox status code. 1005 957 * @param pTransfer URI clipboard transfer to run. 1006 * @param fAsync Whether to run the transfer synchronously or asynchronously. 1007 */ 1008 int SharedClipboardURITransferRun(PSHAREDCLIPBOARDURITRANSFER pTransfer, bool fAsync) 958 * @param pfnThreadFunc Pointer to thread function to use. 959 * @param pvUser Pointer to user-provided data. 960 */ 961 int SharedClipboardURITransferRun(PSHAREDCLIPBOARDURITRANSFER pTransfer, PFNRTTHREAD pfnThreadFunc, void *pvUser) 1009 962 { 1010 963 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER); 1011 964 1012 int rc; 1013 1014 LogFlowFunc(("fAsync=%RTbool\n", fAsync)); 1015 1016 if (fAsync) 1017 { 1018 rc = sharedClipboardURITransferThreadCreate(pTransfer); 1019 } 1020 else 1021 { 1022 if (pTransfer->State.enmDir == SHAREDCLIPBOARDURITRANSFERDIR_READ) 1023 rc = SharedClipboardURITransferRead(pTransfer); 1024 else if (pTransfer->State.enmDir == SHAREDCLIPBOARDURITRANSFERDIR_WRITE) 1025 rc = SharedClipboardURITransferWrite(pTransfer); 1026 else 1027 rc = VERR_NOT_IMPLEMENTED; 1028 } 965 AssertMsgReturn(pTransfer->State.enmStatus == SHAREDCLIPBOARDURITRANSFERSTATUS_READY, 966 ("Wrong status (currently is %RU32)\n", pTransfer->State.enmStatus), VERR_WRONG_ORDER); 967 968 int rc = sharedClipboardURITransferThreadCreate(pTransfer, pfnThreadFunc, pvUser); 1029 969 1030 970 LogFlowFuncLeaveRC(rc); … … 1053 993 SET_CALLBACK(pfnTransferPrepare); 1054 994 SET_CALLBACK(pfnTransferStarted); 1055 SET_CALLBACK(pfn DataHeaderComplete);1056 SET_CALLBACK(pfn DataComplete);995 SET_CALLBACK(pfnListHeaderComplete); 996 SET_CALLBACK(pfnListEntryComplete); 1057 997 SET_CALLBACK(pfnTransferCanceled); 1058 998 SET_CALLBACK(pfnTransferError); … … 1209 1149 * @returns VBox status code. 1210 1150 * @param pTransfer URI clipboard transfer to create thread for. 1211 */ 1212 static int sharedClipboardURITransferThreadCreate(PSHAREDCLIPBOARDURITRANSFER pTransfer) 1151 * @param pfnThreadFunc Thread function to use for this transfer. 1152 * @param pvUser Pointer to user-provided data. 1153 */ 1154 static int sharedClipboardURITransferThreadCreate(PSHAREDCLIPBOARDURITRANSFER pTransfer, PFNRTTHREAD pfnThreadFunc, void *pvUser) 1155 1213 1156 { 1214 1157 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER); 1215 1158 1216 PFNRTTHREAD pfnRTThread = NULL;1217 1218 if (pTransfer->State.enmDir == SHAREDCLIPBOARDURITRANSFERDIR_READ)1219 pfnRTThread = sharedClipboardURITransferReadThread;1220 else if (pTransfer->State.enmDir == SHAREDCLIPBOARDURITRANSFERDIR_WRITE)1221 pfnRTThread = sharedClipboardURITransferWriteThread;1222 1223 AssertPtrReturn(pfnRTThread, VERR_NOT_SUPPORTED);1224 1225 1159 /* Spawn a worker thread, so that we don't block the window thread for too long. */ 1226 int rc = RTThreadCreate(&pTransfer->Thread.hThread, pfn RTThread,1227 p Transfer /* pvUser */, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE,1160 int rc = RTThreadCreate(&pTransfer->Thread.hThread, pfnThreadFunc, 1161 pvUser, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, 1228 1162 "shclp"); 1229 1163 if (RT_SUCCESS(rc)) … … 1232 1166 AssertRC(rc2); 1233 1167 1234 if (!pTransfer->Thread.fStarted) /* Did the thread fail to start? */ 1168 if (pTransfer->Thread.fStarted) /* Did the thread indicate that it started correctly? */ 1169 { 1170 pTransfer->State.enmStatus = SHAREDCLIPBOARDURITRANSFERSTATUS_RUNNING; 1171 } 1172 else 1235 1173 rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */ 1236 1174 } … … 1254 1192 return VINF_SUCCESS; 1255 1193 1194 LogFlowFuncEnter(); 1195 1196 /* Set stop indicator. */ 1197 pTransfer->Thread.fStop = true; 1198 1256 1199 int rcThread = VERR_WRONG_ORDER; 1257 1200 int rc = RTThreadWait(pTransfer->Thread.hThread, uTimeoutMs, &rcThread); … … 1263 1206 1264 1207 /** 1265 * Reads all URI objects using the connected provider.1266 *1267 * @returns VBox status code.1268 * @param pTransfer Transfer to read objects for.1269 */1270 int SharedClipboardURITransferRead(PSHAREDCLIPBOARDURITRANSFER pTransfer)1271 {1272 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);1273 1274 LogFlowFuncEnter();1275 1276 AssertMsgReturn(pTransfer->State.enmStatus == SHAREDCLIPBOARDURITRANSFERSTATUS_READY,1277 ("Read transfer has wrong state (%RU32)\n", pTransfer->State.enmStatus), VERR_WRONG_ORDER);1278 1279 pTransfer->State.enmStatus = SHAREDCLIPBOARDURITRANSFERSTATUS_RUNNING;1280 1281 if (pTransfer->Callbacks.pfnTransferStarted)1282 {1283 SHAREDCLIPBOARDURITRANSFERCALLBACKDATA callbackData = { pTransfer, pTransfer->Callbacks.pvUser };1284 pTransfer->Callbacks.pfnTransferStarted(&callbackData);1285 }1286 1287 int rc = SharedClipboardURITransferMetaDataRead(pTransfer, NULL /* pcbRead */);1288 if (RT_SUCCESS(rc))1289 {1290 rc = SharedClipboardURITransferReadObjects(pTransfer);1291 if (RT_SUCCESS(rc))1292 {1293 if (pTransfer->Callbacks.pfnTransferComplete)1294 {1295 SHAREDCLIPBOARDURITRANSFERCALLBACKDATA callbackData = { pTransfer, pTransfer->Callbacks.pvUser };1296 pTransfer->Callbacks.pfnTransferComplete(&callbackData, rc);1297 }1298 }1299 }1300 1301 if (RT_FAILURE(rc))1302 {1303 if (pTransfer->Callbacks.pfnTransferError)1304 {1305 SHAREDCLIPBOARDURITRANSFERCALLBACKDATA callbackData = { pTransfer, pTransfer->Callbacks.pvUser };1306 pTransfer->Callbacks.pfnTransferError(&callbackData, rc);1307 }1308 }1309 1310 pTransfer->State.enmStatus = SHAREDCLIPBOARDURITRANSFERSTATUS_NONE;1311 1312 LogFlowFuncLeaveRC(rc);1313 return rc;1314 }1315 1316 int SharedClipboardURITransferReadDir(PSHAREDCLIPBOARDURITRANSFER pTransfer, PSHAREDCLIPBOARDCLIENTURIOBJCTX pObjCtx)1317 {1318 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);1319 1320 RT_NOREF(pObjCtx);1321 1322 LogFlowFuncEnter();1323 1324 PVBOXCLIPBOARDDIRDATA pDirData;1325 AssertPtr(pTransfer->ProviderIface.pfnReadDirectory);1326 int rc = pTransfer->ProviderIface.pfnReadDirectory(&pTransfer->ProviderCtx, &pDirData);1327 if (RT_SUCCESS(rc))1328 {1329 SharedClipboardURIDirDataFree(pDirData);1330 }1331 1332 LogFlowFuncLeaveRC(rc);1333 return rc;1334 }1335 1336 int SharedClipboardURITransferReadFile(PSHAREDCLIPBOARDURITRANSFER pTransfer, PSHAREDCLIPBOARDCLIENTURIOBJCTX pObjCtx)1337 {1338 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);1339 1340 RT_NOREF(pObjCtx);1341 1342 LogFlowFuncEnter();1343 1344 PVBOXCLIPBOARDFILEHDR pFileHdr;1345 AssertPtr(pTransfer->ProviderIface.pfnReadFileHdr);1346 int rc = pTransfer->ProviderIface.pfnReadFileHdr(&pTransfer->ProviderCtx, &pFileHdr);1347 if (RT_SUCCESS(rc))1348 {1349 uint64_t cbToRead = pFileHdr->cbSize;1350 uint32_t cbRead;1351 1352 uint8_t pvBuf[_64K]; /** @todo Improve. */1353 uint32_t cbBuf = _64K;1354 1355 while (cbToRead)1356 {1357 AssertPtr(pTransfer->ProviderIface.pfnReadFileData);1358 rc = pTransfer->ProviderIface.pfnReadFileData(&pTransfer->ProviderCtx,1359 pvBuf, cbBuf, 0 /* fFlags */, &cbRead);1360 if (RT_FAILURE(rc))1361 break;1362 1363 /** @todo Validate data block checksum. */1364 1365 Assert(cbToRead >= cbRead);1366 cbToRead -= cbRead;1367 }1368 1369 SharedClipboardURIFileHdrFree(pFileHdr);1370 }1371 1372 LogFlowFuncLeaveRC(rc);1373 return rc;1374 }1375 1376 int SharedClipboardURITransferReadObject(PSHAREDCLIPBOARDURITRANSFER pTransfer, PSHAREDCLIPBOARDCLIENTURIOBJCTX pObjCtx)1377 {1378 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);1379 1380 RT_NOREF(pObjCtx);1381 1382 LogFlowFuncEnter();1383 1384 PVBOXCLIPBOARDOBJHDR pObjHdr;1385 AssertPtr(pTransfer->ProviderIface.pfnReadObjHdr);1386 int rc = pTransfer->ProviderIface.pfnReadObjHdr(&pTransfer->ProviderCtx, &pObjHdr);1387 if (RT_SUCCESS(rc))1388 {1389 switch (pObjHdr->enmType)1390 {1391 #if 01392 case Dir:1393 {1394 SHAREDCLIPBOARDCLIENTURIOBJCTX objCtx;1395 rc = SharedClipboardURITransferReadDir(pTransfer, &objCtx);1396 break;1397 }1398 1399 case File:1400 {1401 SHAREDCLIPBOARDCLIENTURIOBJCTX objCtx;1402 rc = SharedClipboardURITransferReadFile(pTransfer, &objCtx);1403 break;1404 }1405 #endif1406 default:1407 /** @todo Skip -- how? */1408 break;1409 }1410 }1411 1412 LogFlowFuncLeaveRC(rc);1413 return rc;1414 }1415 1416 /**1417 * Reads all URI objects using the connected provider.1418 *1419 * @returns VBox status code.1420 * @param pTransfer Transfer to read objects for.1421 */1422 int SharedClipboardURITransferReadObjects(PSHAREDCLIPBOARDURITRANSFER pTransfer)1423 {1424 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);1425 1426 LogFlowFuncEnter();1427 1428 const PVBOXCLIPBOARDDATAHDR pHdr = pTransfer->State.pHeader;1429 AssertPtrReturn(pHdr, VERR_WRONG_ORDER);1430 1431 int rc = VINF_SUCCESS;1432 1433 for (uint64_t i = 0; i < pHdr->cObjects; i++)1434 {1435 SHAREDCLIPBOARDCLIENTURIOBJCTX objCtx;1436 rc = SharedClipboardURITransferReadObject(pTransfer, &objCtx);1437 if (RT_FAILURE(rc))1438 break;1439 }1440 1441 LogFlowFuncLeaveRC(rc);1442 return rc;1443 }1444 1445 /**1446 * Thread for transferring (reading) URI objects from source to the target.1447 * For target to source transfers we utilize our own IDataObject / IStream implementations.1448 *1449 * @returns VBox status code.1450 * @param hThread Thread handle.1451 * @param pvUser User arguments; is PSHAREDCLIPBOARDURITRANSFER.1452 */1453 static int sharedClipboardURITransferReadThread(RTTHREAD hThread, void *pvUser)1454 {1455 AssertPtrReturn(pvUser, VERR_INVALID_POINTER);1456 1457 LogFlowFuncEnter();1458 1459 /* At the moment we only support one transfer at a time. */1460 PSHAREDCLIPBOARDURITRANSFER pTransfer = (PSHAREDCLIPBOARDURITRANSFER)pvUser;1461 AssertPtr(pTransfer);1462 1463 int rc = VINF_SUCCESS;1464 1465 if (RT_SUCCESS(rc))1466 pTransfer->Thread.fStarted = true;1467 1468 int rc2 = RTThreadUserSignal(hThread);1469 const bool fSignalled = RT_SUCCESS(rc2);1470 1471 if (RT_SUCCESS(rc))1472 rc = SharedClipboardURITransferRead(pTransfer);1473 1474 if (!fSignalled)1475 {1476 rc2 = RTThreadUserSignal(hThread);1477 AssertRC(rc2);1478 }1479 1480 LogFlowFuncLeaveRC(rc);1481 return rc;1482 }1483 1484 /**1485 * Creates the internal meta data buffer of an URI clipboard transfer.1486 *1487 * @returns VBox status code.1488 * @param pTransfer URI clipboard transfer to create internal meta data for.1489 * @param cbSize Size (in bytes) of meta data buffer to create. An existing meta data buffer1490 * will be resized accordingly.1491 */1492 static int sharedClipboardURITransferMetaDataCreateInternal(PSHAREDCLIPBOARDURITRANSFER pTransfer, uint32_t cbSize)1493 {1494 int rc;1495 1496 LogFlowFuncEnter();1497 1498 if (pTransfer->State.pMeta == NULL)1499 {1500 pTransfer->State.pMeta = (PSHAREDCLIPBOARDMETADATA)RTMemAlloc(sizeof(SHAREDCLIPBOARDMETADATA));1501 if (pTransfer->State.pMeta)1502 {1503 /** @todo Make meta data format handling more flexible. */1504 rc = SharedClipboardMetaDataInit(pTransfer->State.pMeta, SHAREDCLIPBOARDMETADATAFMT_URI_LIST);1505 }1506 else1507 rc = VERR_NO_MEMORY;1508 }1509 else1510 rc = SharedClipboardMetaDataResize(pTransfer->State.pMeta, cbSize);1511 1512 LogFlowFuncLeaveRC(rc);1513 return rc;1514 }1515 1516 /**1517 * Destroys a clipboard URI transfer's internal meta data.1518 *1519 * @param pTransfer URI clipboard transfer to destroy internal meta data of.1520 */1521 static void sharedClipboardURITransferMetaDataDestroyInternal(PSHAREDCLIPBOARDURITRANSFER pTransfer)1522 {1523 if (!pTransfer->State.pMeta)1524 return;1525 1526 LogFlowFuncEnter();1527 1528 /* We're done processing the meta data, so just destroy it. */1529 SharedClipboardMetaDataDestroy(pTransfer->State.pMeta);1530 1531 RTMemFree(pTransfer->State.pMeta);1532 pTransfer->State.pMeta = NULL;1533 }1534 1535 /**1536 * Adds meta data for a clipboard URI transfer, internal version.1537 *1538 * @returns VBox status code.1539 * @param pTransfer URI clipboard transfer to set meta data for.1540 * @param pvMeta Pointer to meta data buffer.1541 * @param cbMeta Size (in bytes) of meta data buffer.1542 */1543 static int sharedClipboardURITransferMetaDataAddInternal(PSHAREDCLIPBOARDURITRANSFER pTransfer,1544 const void *pvMeta, uint32_t cbMeta)1545 {1546 LogFlowFunc(("pvMeta=%p, cbMeta=%RU32\n", pvMeta, cbMeta));1547 1548 AssertPtrReturn(pTransfer->State.pHeader, VERR_WRONG_ORDER); /* Header must be present. */1549 AssertReturn(SharedClipboardMetaDataGetUsed(pTransfer->State.pMeta) + cbMeta <= pTransfer->State.pHeader->cbMeta,1550 VERR_BUFFER_OVERFLOW);1551 1552 int rc = SharedClipboardMetaDataAdd(pTransfer->State.pMeta, pvMeta, cbMeta);1553 1554 LogFlowFuncLeaveRC(rc);1555 return rc;1556 }1557 1558 /**1559 * Adds meta data for a clipboard URI transfer.1560 *1561 * @returns VBox status code.1562 * @param pTransfer URI clipboard transfer to set meta data for.1563 * @param pvMeta Pointer to meta data buffer.1564 * @param cbMeta Size (in bytes) of meta data buffer.1565 */1566 int SharedClipboardURITransferMetaDataAdd(PSHAREDCLIPBOARDURITRANSFER pTransfer, const void *pvMeta, uint32_t cbMeta)1567 {1568 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);1569 1570 LogFlowFuncEnter();1571 1572 int rc = sharedClipboardURITransferMetaDataCreateInternal(pTransfer, cbMeta);1573 if (RT_SUCCESS(rc))1574 rc = sharedClipboardURITransferMetaDataAddInternal(pTransfer, pvMeta, cbMeta);1575 1576 LogFlowFuncLeaveRC(rc);1577 return rc;1578 }1579 1580 /**1581 * Returns whether the meta data is in a complete state (e.g. completetely read / written) or not.1582 *1583 * @returns \c true if meta data is complete, \c false if not.1584 * @param pTransfer URI clipboard transfer to get completion status of meta data for.1585 */1586 bool SharedClipboardURITransferMetaDataIsComplete(PSHAREDCLIPBOARDURITRANSFER pTransfer)1587 {1588 AssertPtrReturn(pTransfer->State.pHeader, false);1589 AssertPtrReturn(pTransfer->State.pMeta, false);1590 1591 return SharedClipboardMetaDataGetUsed(pTransfer->State.pMeta) == pTransfer->State.pHeader->cbMeta;1592 }1593 1594 /**1595 * Reads meta for a clipboard URI transfer.1596 *1597 * @returns VBox status code.1598 * @param pTransfer URI clipboard transfer to read meta data for.1599 * @param pcbRead How much meta data (in bytes) was read on success.1600 */1601 int SharedClipboardURITransferMetaDataRead(PSHAREDCLIPBOARDURITRANSFER pTransfer, uint32_t *pcbRead)1602 {1603 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);1604 /* pcbRead is optional. */1605 1606 LogFlowFuncEnter();1607 1608 /* Destroy any former meta data. */1609 SharedClipboardMetaDataDestroy(pTransfer->State.pMeta);1610 1611 uint32_t cbReadTotal = 0;1612 1613 AssertPtr(pTransfer->ProviderIface.pfnReadDataHdr);1614 int rc = pTransfer->ProviderIface.pfnReadDataHdr(&pTransfer->ProviderCtx, &pTransfer->State.pHeader);1615 if (RT_SUCCESS(rc))1616 {1617 if (pTransfer->Callbacks.pfnDataHeaderComplete)1618 {1619 SHAREDCLIPBOARDURITRANSFERCALLBACKDATA callbackData = { pTransfer, pTransfer->Callbacks.pvUser };1620 pTransfer->Callbacks.pfnDataHeaderComplete(&callbackData);1621 }1622 1623 uint32_t cbMetaToRead = pTransfer->State.pHeader->cbMeta;1624 1625 uint32_t cbMeta = cbMetaToRead;1626 void *pvMeta = RTMemAlloc(cbMetaToRead);1627 1628 if (pvMeta)1629 {1630 AssertPtr(pTransfer->State.pHeader);1631 while (cbMetaToRead)1632 {1633 const uint32_t cbToRead = RT_MIN(cbMetaToRead, cbMeta);1634 1635 uint32_t cbMetaRead;1636 AssertPtr(pTransfer->ProviderIface.pfnReadDataChunk);1637 rc = pTransfer->ProviderIface.pfnReadDataChunk(&pTransfer->ProviderCtx,1638 pTransfer->State.pHeader, pvMeta, cbToRead,1639 0 /* fFlags */, &cbMetaRead);1640 if (RT_SUCCESS(rc))1641 rc = SharedClipboardURITransferMetaDataAdd(pTransfer, pvMeta, cbMetaRead);1642 1643 if (RT_FAILURE(rc))1644 break;1645 1646 Assert(cbMetaToRead >= cbMetaRead);1647 cbMetaToRead -= cbMetaRead;1648 1649 cbReadTotal += cbMetaRead;1650 }1651 1652 RTMemFree(pvMeta);1653 1654 if (RT_SUCCESS(rc))1655 {1656 rc = pTransfer->pURIList->SetFromURIData(SharedClipboardMetaDataMutableRaw(pTransfer->State.pMeta),1657 SharedClipboardMetaDataGetUsed(pTransfer->State.pMeta),1658 SHAREDCLIPBOARDURILIST_FLAGS_NONE);1659 if ( RT_SUCCESS(rc)1660 && pTransfer->Callbacks.pfnDataComplete)1661 {1662 SHAREDCLIPBOARDURITRANSFERCALLBACKDATA callbackData = { pTransfer, pTransfer->Callbacks.pvUser };1663 pTransfer->Callbacks.pfnDataComplete(&callbackData);1664 }1665 1666 if (pcbRead)1667 *pcbRead = cbReadTotal;1668 }1669 }1670 else1671 rc = VERR_NO_MEMORY;1672 }1673 1674 LogFlowFuncLeaveRC(rc);1675 return rc;1676 }1677 1678 /**1679 * Writes the actual meta data.1680 *1681 * @returns IPRT status code.1682 * @param pTransfer Transfer to write meta data for.1683 * @param pcbWritten How much bytes were written on success. Optional.1684 */1685 int SharedClipboardURITransferMetaDataWrite(PSHAREDCLIPBOARDURITRANSFER pTransfer, uint32_t *pcbWritten)1686 {1687 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);1688 /* pcbWritten is optional. */1689 1690 LogFlowFuncEnter();1691 1692 AssertPtrReturn(pTransfer->State.pHeader, VERR_WRONG_ORDER);1693 AssertPtrReturn(pTransfer->State.pMeta, VERR_WRONG_ORDER);1694 1695 uint32_t cbWrittenTotal = 0;1696 1697 AssertPtr(pTransfer->ProviderIface.pfnWriteDataHdr);1698 int rc = pTransfer->ProviderIface.pfnWriteDataHdr(&pTransfer->ProviderCtx, pTransfer->State.pHeader);1699 if (RT_SUCCESS(rc))1700 {1701 /* Sanity. */1702 Assert(pTransfer->State.pHeader->cbMeta == pTransfer->State.pMeta->cbUsed);1703 1704 uint32_t cbMetaToWrite = pTransfer->State.pHeader->cbMeta;1705 while (cbMetaToWrite)1706 {1707 uint32_t cbMetaWritten;1708 AssertPtr(pTransfer->ProviderIface.pfnWriteDataChunk);1709 rc = pTransfer->ProviderIface.pfnWriteDataChunk(&pTransfer->ProviderCtx, pTransfer->State.pHeader,1710 (uint8_t *)pTransfer->State.pMeta->pvMeta + cbWrittenTotal,1711 cbMetaToWrite, 0 /* fFlags */, &cbMetaWritten);1712 if (RT_FAILURE(rc))1713 break;1714 1715 Assert(cbMetaToWrite >= cbMetaWritten);1716 cbMetaToWrite -= cbMetaWritten;1717 1718 cbWrittenTotal += cbMetaWritten;1719 Assert(cbWrittenTotal <= pTransfer->State.pHeader->cbMeta);1720 }1721 1722 if (RT_SUCCESS(rc))1723 {1724 if (pcbWritten)1725 *pcbWritten = cbWrittenTotal;1726 1727 if (pTransfer->Callbacks.pfnDataComplete)1728 {1729 SHAREDCLIPBOARDURITRANSFERCALLBACKDATA callbackData = { pTransfer, pTransfer->Callbacks.pvUser };1730 pTransfer->Callbacks.pfnDataComplete(&callbackData);1731 }1732 }1733 }1734 1735 LogFlowFuncLeaveRC(rc);1736 return rc;1737 }1738 1739 /**1740 * Writes all URI objects using the connected provider.1741 *1742 * @returns VBox status code.1743 * @param pTransfer Transfer to write objects for.1744 */1745 int SharedClipboardURITransferWriteObjects(PSHAREDCLIPBOARDURITRANSFER pTransfer)1746 {1747 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);1748 1749 LogFlowFuncEnter();1750 1751 int rc = VINF_SUCCESS;1752 1753 AssertPtrReturn(pTransfer->pURIList, VERR_WRONG_ORDER);1754 1755 while (!pTransfer->pURIList->IsEmpty())1756 {1757 SharedClipboardURIObject *pObj = pTransfer->pURIList->First();1758 AssertPtrBreakStmt(pObj, rc = VERR_INVALID_POINTER);1759 1760 switch (pObj->GetType())1761 {1762 case SharedClipboardURIObject::Type_Directory:1763 {1764 RTCString strPath = pObj->GetDestPathAbs();1765 LogFlowFunc(("strDir=%s (%zu), fMode=0x%x\n",1766 strPath.c_str(), strPath.length(), pObj->GetMode()));1767 1768 VBOXCLIPBOARDDIRDATA dirData;1769 SharedClipboardURIDirDataInit(&dirData);1770 1771 dirData.pszPath = RTStrDup(strPath.c_str());1772 dirData.cbPath = (uint32_t)strlen(dirData.pszPath);1773 1774 AssertPtr(pTransfer->ProviderIface.pfnWriteDirectory);1775 rc = pTransfer->ProviderIface.pfnWriteDirectory(&pTransfer->ProviderCtx, &dirData);1776 1777 SharedClipboardURIDirDataDestroy(&dirData);1778 break;1779 }1780 1781 case SharedClipboardURIObject::Type_File:1782 {1783 AssertBreakStmt(pObj->IsOpen(), rc = VERR_INVALID_STATE);1784 1785 RTCString strPath = pObj->GetDestPathAbs();1786 1787 LogFlowFunc(("strFile=%s (%zu), cbSize=%RU64, fMode=0x%x\n", strPath.c_str(), strPath.length(),1788 pObj->GetSize(), pObj->GetMode()));1789 1790 VBOXCLIPBOARDFILEHDR fileHdr;1791 SharedClipboardURIFileHdrInit(&fileHdr);1792 1793 fileHdr.pszFilePath = RTStrDup(strPath.c_str());1794 fileHdr.cbFilePath = (uint32_t)strlen(fileHdr.pszFilePath);1795 fileHdr.cbSize = pObj->GetSize();1796 fileHdr.fFlags = 0;1797 fileHdr.fMode = pObj->GetMode();1798 1799 AssertPtr(pTransfer->ProviderIface.pfnWriteFileHdr);1800 rc = pTransfer->ProviderIface.pfnWriteFileHdr(&pTransfer->ProviderCtx, &fileHdr);1801 SharedClipboardURIFileHdrDestroy(&fileHdr);1802 1803 if (RT_FAILURE(rc))1804 break;1805 1806 uint32_t cbData = _64K; /** @todo Improve. */1807 void *pvData = RTMemAlloc(cbData);1808 1809 AssertPtrBreakStmt(pvData, rc = VERR_NO_MEMORY);1810 1811 while (!pObj->IsComplete())1812 {1813 uint32_t cbRead;1814 rc = pObj->Read(pvData, cbData, &cbRead);1815 if (RT_SUCCESS(rc))1816 {1817 uint32_t cbToRead = cbRead;1818 AssertPtr(pTransfer->ProviderIface.pfnWriteFileData);1819 rc = pTransfer->ProviderIface.pfnWriteFileData(&pTransfer->ProviderCtx,1820 pvData, cbToRead, 0 /* fFlags */, &cbRead);1821 }1822 1823 if (RT_FAILURE(rc))1824 break;1825 }1826 1827 RTMemFree(pvData);1828 pvData = NULL;1829 break;1830 }1831 1832 default:1833 AssertFailed();1834 break;1835 }1836 1837 if (RT_FAILURE(rc))1838 break;1839 1840 /* Only remove current object on success. */1841 pTransfer->pURIList->RemoveFirst();1842 }1843 1844 LogFlowFuncLeaveRC(rc);1845 return rc;1846 }1847 1848 /**1849 * Thread for transferring (writing) URI objects from source to the target.1850 * For target to source transfers we utilize our own IDataObject / IStream implementations.1851 *1852 * @returns VBox status code.1853 * @param hThread Thread handle.1854 * @param pvUser User arguments; is PSHAREDCLIPBOARDURITRANSFER.1855 */1856 static int sharedClipboardURITransferWriteThread(RTTHREAD hThread, void *pvUser)1857 {1858 AssertPtrReturn(pvUser, VERR_INVALID_POINTER);1859 1860 LogFlowFuncEnter();1861 1862 /* At the moment we only support one transfer at a time. */1863 PSHAREDCLIPBOARDURITRANSFER pTransfer = (PSHAREDCLIPBOARDURITRANSFER)pvUser;1864 1865 int rc = VINF_SUCCESS;1866 1867 if (RT_SUCCESS(rc))1868 pTransfer->Thread.fStarted = true;1869 1870 int rc2 = RTThreadUserSignal(hThread);1871 const bool fSignalled = RT_SUCCESS(rc2);1872 1873 if (RT_SUCCESS(rc))1874 rc = SharedClipboardURITransferWrite(pTransfer);1875 1876 if (!fSignalled)1877 {1878 rc2 = RTThreadUserSignal(hThread);1879 AssertRC(rc2);1880 }1881 1882 LogFlowFuncLeaveRC(rc);1883 return rc;1884 }1885 1886 /**1887 * Main function to write a clipboard URI transfer.1888 *1889 * @returns VBox status code.1890 * @param pURI URI clipboard context to write.1891 */1892 int SharedClipboardURITransferWrite(PSHAREDCLIPBOARDURITRANSFER pTransfer)1893 {1894 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);1895 1896 LogFlowFuncEnter();1897 1898 AssertMsgReturn(pTransfer->State.enmStatus == SHAREDCLIPBOARDURITRANSFERSTATUS_READY,1899 ("Write transfer has wrong state (%RU32)\n", pTransfer->State.enmStatus), VERR_WRONG_ORDER);1900 1901 pTransfer->State.enmStatus = SHAREDCLIPBOARDURITRANSFERSTATUS_RUNNING;1902 1903 if (pTransfer->Callbacks.pfnTransferStarted)1904 {1905 SHAREDCLIPBOARDURITRANSFERCALLBACKDATA callbackData = { pTransfer, pTransfer->Callbacks.pvUser };1906 pTransfer->Callbacks.pfnTransferStarted(&callbackData);1907 }1908 1909 int rc = SharedClipboardURITransferMetaDataWrite(pTransfer, NULL /* pcbWritten */);1910 if (RT_SUCCESS(rc))1911 {1912 rc = SharedClipboardURITransferWriteObjects(pTransfer);1913 if (RT_SUCCESS(rc))1914 {1915 if (pTransfer->Callbacks.pfnTransferComplete)1916 {1917 SHAREDCLIPBOARDURITRANSFERCALLBACKDATA callbackData = { pTransfer, pTransfer->Callbacks.pvUser };1918 pTransfer->Callbacks.pfnTransferComplete(&callbackData, rc);1919 }1920 }1921 }1922 1923 if (RT_FAILURE(rc))1924 {1925 if (pTransfer->Callbacks.pfnTransferError)1926 {1927 SHAREDCLIPBOARDURITRANSFERCALLBACKDATA callbackData = { pTransfer, pTransfer->Callbacks.pvUser };1928 pTransfer->Callbacks.pfnTransferError(&callbackData, rc);1929 }1930 }1931 1932 pTransfer->State.enmStatus = SHAREDCLIPBOARDURITRANSFERSTATUS_NONE;1933 1934 LogFlowFuncLeaveRC(rc);1935 return rc;1936 }1937 1938 /**1939 1208 * Initializes a clipboard URI transfer. 1940 1209 * … … 1946 1215 AssertPtrReturn(pURI, VERR_INVALID_POINTER); 1947 1216 1948 LogFlowFunc Enter();1217 LogFlowFunc(("%p\n", pURI)); 1949 1218 1950 1219 int rc = RTCritSectInit(&pURI->CritSect); … … 1974 1243 AssertPtrReturnVoid(pURI); 1975 1244 1976 LogFlowFunc Enter();1245 LogFlowFunc(("%p\n", pURI)); 1977 1246 1978 1247 RTCritSectDelete(&pURI->CritSect); … … 1982 1251 { 1983 1252 SharedClipboardURITransferDestroy(pTransfer); 1253 1984 1254 RTListNodeRemove(&pTransfer->Node); 1255 1256 RTMemFree(pTransfer); 1257 pTransfer = NULL; 1985 1258 } 1986 1259 … … 2049 1322 { 2050 1323 RTListNodeRemove(&pTransfer->Node); 1324 1325 RTMemFree(pTransfer); 1326 pTransfer = NULL; 2051 1327 } 2052 1328 … … 2125 1401 RTListNodeRemove(&pTransfer->Node); 2126 1402 1403 RTMemFree(pTransfer); 1404 pTransfer = NULL; 1405 2127 1406 Assert(pURI->cTransfers); 2128 1407 pURI->cTransfers--; … … 2143 1422 AssertPtrReturn(pURI, true); 2144 1423 2145 LogFlowFunc(("cRunning=%RU32 \n", pURI->cRunning));1424 LogFlowFunc(("cRunning=%RU32, cMaxRunning=%RU32\n", pURI->cRunning, pURI->cMaxRunning)); 2146 1425 2147 1426 Assert(pURI->cRunning <= pURI->cMaxRunning); … … 2149 1428 } 2150 1429 1430 /** 1431 * Copies file system objinfo from IPRT to Shared Clipboard format. 1432 * 1433 * @param pDst The Shared Clipboard structure to convert data to. 1434 * @param pSrc The IPRT structure to convert data from. 1435 */ 1436 void SharedClipboardFsObjFromIPRT(PSHAREDCLIPBOARDFSOBJINFO pDst, PCRTFSOBJINFO pSrc) 1437 { 1438 pDst->cbObject = pSrc->cbObject; 1439 pDst->cbAllocated = pSrc->cbAllocated; 1440 pDst->AccessTime = pSrc->AccessTime; 1441 pDst->ModificationTime = pSrc->ModificationTime; 1442 pDst->ChangeTime = pSrc->ChangeTime; 1443 pDst->BirthTime = pSrc->BirthTime; 1444 pDst->Attr.fMode = pSrc->Attr.fMode; 1445 /* Clear bits which we don't pass through for security reasons. */ 1446 pDst->Attr.fMode &= ~(RTFS_UNIX_ISUID | RTFS_UNIX_ISGID | RTFS_UNIX_ISTXT); 1447 RT_ZERO(pDst->Attr.u); 1448 switch (pSrc->Attr.enmAdditional) 1449 { 1450 default: 1451 case RTFSOBJATTRADD_NOTHING: 1452 pDst->Attr.enmAdditional = SHAREDCLIPBOARDFSOBJATTRADD_NOTHING; 1453 break; 1454 1455 case RTFSOBJATTRADD_UNIX: 1456 pDst->Attr.enmAdditional = SHAREDCLIPBOARDFSOBJATTRADD_UNIX; 1457 pDst->Attr.u.Unix.uid = pSrc->Attr.u.Unix.uid; 1458 pDst->Attr.u.Unix.gid = pSrc->Attr.u.Unix.gid; 1459 pDst->Attr.u.Unix.cHardlinks = pSrc->Attr.u.Unix.cHardlinks; 1460 pDst->Attr.u.Unix.INodeIdDevice = pSrc->Attr.u.Unix.INodeIdDevice; 1461 pDst->Attr.u.Unix.INodeId = pSrc->Attr.u.Unix.INodeId; 1462 pDst->Attr.u.Unix.fFlags = pSrc->Attr.u.Unix.fFlags; 1463 pDst->Attr.u.Unix.GenerationId = pSrc->Attr.u.Unix.GenerationId; 1464 pDst->Attr.u.Unix.Device = pSrc->Attr.u.Unix.Device; 1465 break; 1466 1467 case RTFSOBJATTRADD_EASIZE: 1468 pDst->Attr.enmAdditional = SHAREDCLIPBOARDFSOBJATTRADD_EASIZE; 1469 pDst->Attr.u.EASize.cb = pSrc->Attr.u.EASize.cb; 1470 break; 1471 } 1472 } 1473 -
trunk/src/VBox/GuestHost/SharedClipboard/clipboard-win.cpp
r79366 r79497 944 944 * @returns VBox status code. 945 945 * @param pDropFiles Pointer to DROPFILES structure to convert. 946 * @param pTransfer Transfer where to add the string list to. 947 */ 948 int VBoxClipboardWinDropFilesToTransfer(DROPFILES *pDropFiles, PSHAREDCLIPBOARDURITRANSFER pTransfer) 946 * @param papszList Where to store the allocated string list. 947 * @param pcbList Where to store the size (in bytes) of the allocated string list. 948 */ 949 int VBoxClipboardWinDropFilesToStringList(DROPFILES *pDropFiles, char **papszList, uint32_t *pcbList) 949 950 { 950 951 AssertPtrReturn(pDropFiles, VERR_INVALID_POINTER); 951 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER); 952 AssertPtrReturn(papszList, VERR_INVALID_POINTER); 953 AssertPtrReturn(pcbList, VERR_INVALID_POINTER); 952 954 953 955 /* Do we need to do Unicode stuff? */ … … 1028 1030 LogRel(("Shared Clipboard: Adding guest file '%s'\n", pszFileUtf8)); 1029 1031 1032 #if 0 1030 1033 char *pszFileURI; 1031 1034 uint32_t cchFileURI; … … 1042 1045 RTStrFree(pszFileURI); 1043 1046 } 1047 #endif 1044 1048 } 1045 1049 … … 1068 1072 cFiles, cchFiles, cbFiles, pszFiles)); 1069 1073 1070 rc = SharedClipboardURITransferMetaDataAdd(pTransfer, pszFiles, cbFiles); 1071 } 1072 1073 LogFlowFunc(("Building CF_HDROP list rc=%Rrc, pszFiles=0x%p, cFiles=%RU16, cchFiles=%RU32\n", 1074 rc, pszFiles, cFiles, cchFiles)); 1075 1076 if (pszFiles) 1077 RTStrFree(pszFiles); 1078 1074 *papszList = pszFiles; 1075 *pcbList = cbFiles; 1076 } 1077 else 1078 { 1079 if (pszFiles) 1080 RTStrFree(pszFiles); 1081 } 1082 1083 LogFlowFuncLeaveRC(rc); 1079 1084 return rc; 1080 1085 } -
trunk/src/VBox/HostServices/SharedClipboard/Makefile.kmk
r79347 r79497 35 35 VBoxSharedClipboard_SOURCES = \ 36 36 VBoxSharedClipboardSvc.cpp \ 37 $(PATH_ROOT)/src/VBox/HostServices/common/message.cpp \ 37 38 $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/clipboard-common.cpp 38 39 VBoxSharedClipboard_SOURCES.win = \ … … 49 50 VBoxSharedClipboardSvc-utils.cpp \ 50 51 $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardArea.cpp \ 51 $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardMetaData.cpp \52 52 $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardPath.cpp \ 53 53 $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardURIList.cpp \ -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-internal.h
r79366 r79497 22 22 #endif 23 23 24 #include <algorithm> 25 #include <list> 26 #include <map> 27 24 28 #include <iprt/list.h> 25 29 … … 27 31 #include <VBox/log.h> 28 32 33 #include <VBox/HostServices/Service.h> 29 34 #include <VBox/GuestHost/SharedClipboard.h> 30 35 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST … … 32 37 # include <VBox/GuestHost/SharedClipboard-uri.h> 33 38 #endif 39 40 using namespace HGCM; 34 41 35 42 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST … … 46 53 #endif /* VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */ 47 54 55 typedef struct _VBOXCLIPBOARDCLIENTMSG 56 { 57 /** Stored message type. */ 58 uint32_t m_uMsg; 59 /** Number of stored HGCM parameters. */ 60 uint32_t m_cParms; 61 /** Stored HGCM parameters. */ 62 PVBOXHGCMSVCPARM m_paParms; 63 } VBOXCLIPBOARDCLIENTMSG, *PVBOXCLIPBOARDCLIENTMSG; 64 65 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 66 typedef struct VBOXCLIPBOARDCLIENTURISTATE 67 { 68 /** Whether to start a new transfer. */ 69 bool fTransferStart; 70 /** Directory of the transfer to start. */ 71 SHAREDCLIPBOARDURITRANSFERDIR enmTransferDir; 72 } VBOXCLIPBOARDCLIENTURISTATE, *PVBOXCLIPBOARDCLIENTURISTATE; 73 #endif /* VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */ 74 48 75 /** 49 76 * Structure for keeping generic client state data within the Shared Clipboard host service. 50 77 * This structure needs to be serializable by SSM. 51 78 */ 52 struct VBOXCLIPBOARDCLIENTSTATE79 typedef struct VBOXCLIPBOARDCLIENTSTATE 53 80 { 54 81 struct VBOXCLIPBOARDCLIENTSTATE *pNext; … … 72 99 bool fHostMsgFormats; 73 100 101 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 102 /** The client's URI state. */ 103 VBOXCLIPBOARDCLIENTURISTATE URI; 104 #endif 105 74 106 struct { 75 107 VBOXHGCMCALLHANDLE callHandle; … … 92 124 uint32_t u32AvailableFormats; 93 125 uint32_t u32RequestedFormat; 94 }; 95 typedef struct VBOXCLIPBOARDCLIENTSTATE *PVBOXCLIPBOARDCLIENTSTATE; 126 127 /** The client's message queue (FIFO). */ 128 RTCList<VBOXCLIPBOARDCLIENTMSG *> queueMsg; 129 } VBOXCLIPBOARDCLIENTSTATE, *PVBOXCLIPBOARDCLIENTSTATE; 96 130 97 131 /** … … 103 137 VBOXCLIPBOARDCLIENTSTATE State; 104 138 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 139 /** URI context data. */ 105 140 SHAREDCLIPBOARDURICTX URI; 106 141 #endif 107 142 } VBOXCLIPBOARDCLIENTDATA, *PVBOXCLIPBOARDCLIENTDATA; 143 144 typedef struct _VBOXCLIPBOARDCLIENT 145 { 146 /** The client's HGCM client ID. */ 147 uint32_t uClientID; 148 /** Pointer to the client'data, owned by HGCM. */ 149 PVBOXCLIPBOARDCLIENTDATA pData; 150 /** Optional protocol version the client uses. Set to 0 by default. */ 151 uint32_t uProtocolVer; 152 /** Flag indicating whether this client currently is deferred mode, 153 * meaning that it did not return to the caller yet. */ 154 bool fDeferred; 155 /** Structure for keeping the client's deferred state. 156 * A client is in a deferred state when it asks for the next HGCM message, 157 * but the service can't provide it yet. That way a client will block (on the guest side, does not return) 158 * until the service can complete the call. */ 159 struct 160 { 161 /** The client's HGCM call handle. Needed for completing a deferred call. */ 162 VBOXHGCMCALLHANDLE hHandle; 163 /** Message type (function number) to use when completing the deferred call. */ 164 uint32_t uType; 165 /** Parameter count to use when completing the deferred call. */ 166 uint32_t cParms; 167 /** Parameters to use when completing the deferred call. */ 168 PVBOXHGCMSVCPARM paParms; 169 } Deferred; 170 } VBOXCLIPBOARDCLIENT, *PVBOXCLIPBOARDCLIENT; 171 172 /** Map holding pointers to drag and drop clients. Key is the (unique) HGCM client ID. */ 173 typedef std::map<uint32_t, VBOXCLIPBOARDCLIENT *> ClipboardClientMap; 174 175 /** Simple queue (list) which holds deferred (waiting) clients. */ 176 typedef std::list<uint32_t> ClipboardClientQueue; 108 177 109 178 /* … … 114 183 int vboxSvcClipboardReportMsg(PVBOXCLIPBOARDCLIENTDATA pClientData, uint32_t uMsg, uint32_t uFormats); 115 184 int vboxSvcClipboardSetSource(PVBOXCLIPBOARDCLIENTDATA pClientData, SHAREDCLIPBOARDSOURCE enmSource); 185 186 int vboxSvcClipboardClientDefer(PVBOXCLIPBOARDCLIENT pClient, 187 VBOXHGCMCALLHANDLE hHandle, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 188 int vboxSvcClipboardClientComplete(PVBOXCLIPBOARDCLIENT pClient, VBOXHGCMCALLHANDLE hHandle, int rc); 189 int vboxSvcClipboardClientDeferredComplete(PVBOXCLIPBOARDCLIENT pClient, int rc); 190 int vboxSvcClipboardClientDeferredSetMsgInfo(PVBOXCLIPBOARDCLIENT pClient, uint32_t uMsg, uint32_t cParms); 191 192 void vboxSvcClipboardMsgQueueReset(PVBOXCLIPBOARDCLIENTSTATE pState); 193 PVBOXCLIPBOARDCLIENTMSG vboxSvcClipboardMsgAlloc(uint32_t uMsg, uint32_t cParms); 194 void vboxSvcClipboardMsgFree(PVBOXCLIPBOARDCLIENTMSG pMsg); 195 int vboxSvcClipboardMsgAdd(PVBOXCLIPBOARDCLIENTSTATE pState, PVBOXCLIPBOARDCLIENTMSG pMsg, bool fAppend); 196 int vboxSvcClipboardMsgGetNextInfo(PVBOXCLIPBOARDCLIENTSTATE pState, uint32_t *puType, uint32_t *pcParms); 197 int vboxSvcClipboardMsgGetNext(PVBOXCLIPBOARDCLIENTSTATE pState, 198 uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 116 199 117 200 # ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST … … 139 222 140 223 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 141 int VBoxSvcClipboardProviderImplURIReadDataHdr(PSHAREDCLIPBOARDPROVIDERCTX pCtx, PVBOXCLIPBOARDDATAHDR *ppDataHdr); 142 int VBoxSvcClipboardProviderImplURIWriteDataHdr(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const PVBOXCLIPBOARDDATAHDR pDataHdr); 143 int VBoxSvcClipboardProviderImplURIReadDataChunk(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const PVBOXCLIPBOARDDATAHDR pDataHdr, void *pvChunk, uint32_t cbChunk, uint32_t fFlags, uint32_t *pcbRead); 144 int VBoxSvcClipboardProviderImplURIWriteDataChunk(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const PVBOXCLIPBOARDDATAHDR pDataHdr, const void *pvChunk, uint32_t cbChunk, uint32_t fFlags, uint32_t *pcbWritten); 145 int VBoxSvcClipboardProviderImplURIReadDir(PSHAREDCLIPBOARDPROVIDERCTX pCtx, PVBOXCLIPBOARDDIRDATA *ppDirData); 146 int VBoxSvcClipboardProviderImplURIWriteDir(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const PVBOXCLIPBOARDDIRDATA pDirData); 147 int VBoxSvcClipboardProviderImplURIReadFileHdr(PSHAREDCLIPBOARDPROVIDERCTX pCtx, PVBOXCLIPBOARDFILEHDR *ppFileHdr); 148 int VBoxSvcClipboardProviderImplURIWriteFileHdr(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const PVBOXCLIPBOARDFILEHDR pFileHdr); 149 int VBoxSvcClipboardProviderImplURIReadFileData(PSHAREDCLIPBOARDPROVIDERCTX pCtx, void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbRead); 150 int VBoxSvcClipboardProviderImplURIWriteFileData(PSHAREDCLIPBOARDPROVIDERCTX pCtx, void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbWritten); 224 int vboxSvcClipboardURITransferOpen(PSHAREDCLIPBOARDPROVIDERCTX pCtx); 225 int vboxSvcClipboardURITransferClose(PSHAREDCLIPBOARDPROVIDERCTX pCtx); 226 227 int vboxSvcClipboardURIListOpen(PSHAREDCLIPBOARDPROVIDERCTX pCtx, 228 PVBOXCLIPBOARDLISTHDR pListHdr, PVBOXCLIPBOARDLISTHANDLE phList); 229 int vboxSvcClipboardURIListClose(PSHAREDCLIPBOARDPROVIDERCTX pCtx, VBOXCLIPBOARDLISTHANDLE hList); 230 int vboxSvcClipboardURIListHdrRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx, VBOXCLIPBOARDLISTHANDLE hList, 231 PVBOXCLIPBOARDLISTHDR pListHdr); 232 int vboxSvcClipboardURIListHdrWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx, VBOXCLIPBOARDLISTHANDLE hList, 233 PVBOXCLIPBOARDLISTHDR pListHdr); 234 int vboxSvcClipboardURIListEntryRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx, VBOXCLIPBOARDLISTHANDLE hList, 235 PVBOXCLIPBOARDLISTENTRY pListEntry); 236 int vboxSvcClipboardURIListEntryWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx, VBOXCLIPBOARDLISTHANDLE hList, 237 PVBOXCLIPBOARDLISTENTRY pListEntry); 238 239 int vboxSvcClipboardURIObjOpen(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const char *pszPath, 240 PVBOXCLIPBOARDCREATEPARMS pCreateParms, PSHAREDCLIPBOARDOBJHANDLE phObj); 241 int vboxSvcClipboardURIObjClose(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDOBJHANDLE hObj); 242 int vboxSvcClipboardURIObjRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDOBJHANDLE hObj, 243 void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbRead); 244 int vboxSvcClipboardURIObjWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDOBJHANDLE hObj, 245 void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbWritten); 151 246 152 247 DECLCALLBACK(void) VBoxSvcClipboardURITransferPrepareCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData); … … 159 254 int VBoxClipboardSvcImplURITransferCreate(PVBOXCLIPBOARDCLIENTDATA pClientData, PSHAREDCLIPBOARDURITRANSFER pTransfer); 160 255 int VBoxClipboardSvcImplURITransferDestroy(PVBOXCLIPBOARDCLIENTDATA pClientData, PSHAREDCLIPBOARDURITRANSFER pTransfer); 161 162 void VBoxClipboardSvcImplURIOnDataHeaderComplete(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData);163 256 #endif 164 257 -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-uri.cpp
r79367 r79497 42 42 extern void *g_pvExtension; 43 43 44 extern ClipboardClientQueue g_listClientsDeferred; 45 44 46 45 47 /********************************************************************************************************************************* … … 47 49 *********************************************************************************************************************************/ 48 50 49 int VBoxSvcClipboardProviderImplURIReadDataHdr(PSHAREDCLIPBOARDPROVIDERCTX pCtx, PVBOXCLIPBOARDDATAHDR *ppDataHdr) 50 { 51 DECLCALLBACK(int) vboxSvcClipboardURITransferOpen(PSHAREDCLIPBOARDPROVIDERCTX pCtx) 52 { 53 RT_NOREF(pCtx); 54 55 LogFlowFuncLeave(); 56 return VINF_SUCCESS; 57 } 58 59 DECLCALLBACK(int) vboxSvcClipboardURITransferClose(PSHAREDCLIPBOARDPROVIDERCTX pCtx) 60 { 61 RT_NOREF(pCtx); 62 63 LogFlowFuncLeave(); 64 return VINF_SUCCESS; 65 } 66 67 DECLCALLBACK(int) vboxSvcClipboardURIListOpen(PSHAREDCLIPBOARDPROVIDERCTX pCtx, 68 PVBOXCLIPBOARDLISTHDR pListHdr, PVBOXCLIPBOARDLISTHANDLE phList) 69 { 70 RT_NOREF(pCtx, pListHdr, phList); 71 72 LogFlowFuncEnter(); 73 74 int rc = VINF_SUCCESS; 75 76 LogFlowFuncLeaveRC(rc); 77 return rc; 78 } 79 80 DECLCALLBACK(int) vboxSvcClipboardURIListClose(PSHAREDCLIPBOARDPROVIDERCTX pCtx, VBOXCLIPBOARDLISTHANDLE hList) 81 { 82 RT_NOREF(pCtx, hList); 83 84 LogFlowFuncEnter(); 85 86 int rc = VINF_SUCCESS; 87 88 LogFlowFuncLeaveRC(rc); 89 return rc; 90 } 91 92 DECLCALLBACK(int) vboxSvcClipboardURIListHdrRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx, 93 VBOXCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTHDR pListHdr) 94 { 95 RT_NOREF(pCtx, hList, pListHdr); 96 97 LogFlowFuncEnter(); 98 99 PVBOXCLIPBOARDCLIENT pClient = (PVBOXCLIPBOARDCLIENT)pCtx->pvUser; 100 AssertPtr(pClient); 101 102 int rc; 103 104 PVBOXCLIPBOARDCLIENTMSG pMsg = vboxSvcClipboardMsgAlloc(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_HDR_READ, 105 VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR_READ); 106 if (pMsg) 107 { 108 rc = vboxSvcClipboardMsgAdd(&pClient->pData->State, pMsg, true /* fAppend */); 109 if (RT_SUCCESS(rc)) 110 rc = vboxSvcClipboardClientDeferredComplete(pClient, VINF_SUCCESS); 111 } 112 else 113 rc = VERR_NO_MEMORY; 114 115 if (RT_SUCCESS(rc)) 116 { 117 PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload; 118 rc = SharedClipboardURITransferEventWait(pCtx->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_HDR_READ, 119 30 * 1000 /* Timeout in ms */, &pPayload); 120 if (RT_SUCCESS(rc)) 121 { 122 Assert(pPayload->cbData == sizeof(VBOXCLIPBOARDLISTHDR)); 123 //*ppListHdr = (PVBOXCLIPBOARDLISTHDR)pPayload->pvData; 124 125 RTMemFree(pPayload); 126 } 127 } 128 129 LogFlowFuncLeaveRC(rc); 130 return rc; 131 } 132 133 DECLCALLBACK(int) vboxSvcClipboardURIListHdrWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx, 134 VBOXCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTHDR pListHdr) 135 { 136 RT_NOREF(pCtx, hList, pListHdr); 137 138 LogFlowFuncEnter(); 139 140 return VERR_NOT_IMPLEMENTED; 141 } 142 143 DECLCALLBACK(int) vboxSvcClipboardURIListEntryRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx, 144 VBOXCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTENTRY pListEntry) 145 { 146 RT_NOREF(pCtx, hList, pListEntry); 147 51 148 LogFlowFuncEnter(); 52 149 … … 55 152 56 153 PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload; 57 int rc = SharedClipboardURITransferEventWait(pCtx->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_ METADATA_HDR,154 int rc = SharedClipboardURITransferEventWait(pCtx->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_ENTRY_READ, 58 155 30 * 1000 /* Timeout in ms */, &pPayload); 59 156 if (RT_SUCCESS(rc)) 60 157 { 61 Assert(pPayload->cbData == sizeof(VBOXCLIPBOARDDATAHDR)); 62 *ppDataHdr = (PVBOXCLIPBOARDDATAHDR)pPayload->pvData; 63 64 RTMemFree(pPayload); 65 } 66 67 LogFlowFuncLeaveRC(rc); 68 return rc; 69 } 70 71 int VBoxSvcClipboardProviderImplURIWriteDataHdr(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const PVBOXCLIPBOARDDATAHDR pDataHdr) 72 { 73 RT_NOREF(pCtx, pDataHdr); 158 Assert(pPayload->cbData == sizeof(VBOXCLIPBOARDLISTENTRY)); 159 160 PVBOXCLIPBOARDLISTENTRY pListEntry = (PVBOXCLIPBOARDLISTENTRY)pPayload->pvData; 161 AssertPtr(pListEntry); 162 163 /* const uint32_t cbToRead = RT_MIN(cbChunk, pListEntry->cbData); 164 165 memcpy(pvChunk, pListEntry->pvData, cbToRead);*/ 166 167 SharedClipboardURITransferPayloadFree(pPayload); 168 169 /* if (pcbRead) 170 *pcbRead = cbToRead;*/ 171 } 172 173 LogFlowFuncLeaveRC(rc); 174 return rc; 175 } 176 177 DECLCALLBACK(int) vboxSvcClipboardURIListEntryWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx, 178 VBOXCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTENTRY pListEntry) 179 { 180 RT_NOREF(pCtx, hList, pListEntry); 74 181 75 182 LogFlowFuncEnter(); … … 78 185 } 79 186 80 int VBoxSvcClipboardProviderImplURIReadDataChunk(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const PVBOXCLIPBOARDDATAHDR pDataHdr, 81 void *pvChunk, uint32_t cbChunk, uint32_t fFlags, uint32_t *pcbRead) 82 { 83 RT_NOREF(pDataHdr, fFlags); 84 85 LogFlowFuncEnter(); 86 87 PVBOXCLIPBOARDCLIENTDATA pClientData = (PVBOXCLIPBOARDCLIENTDATA)pCtx->pvUser; 88 AssertPtr(pClientData); 89 90 PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload; 91 int rc = SharedClipboardURITransferEventWait(pCtx->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_METADATA_CHUNK, 92 30 * 1000 /* Timeout in ms */, &pPayload); 93 if (RT_SUCCESS(rc)) 94 { 95 Assert(pPayload->cbData == sizeof(VBOXCLIPBOARDDATACHUNK)); 96 97 const uint32_t cbToRead = RT_MIN(cbChunk, pPayload->cbData); 98 99 memcpy(pvChunk, pPayload->pvData, cbToRead); 100 101 SharedClipboardURITransferPayloadFree(pPayload); 102 103 if (pcbRead) 104 *pcbRead = cbToRead; 105 } 106 107 LogFlowFuncLeaveRC(rc); 108 return rc; 109 } 110 111 int VBoxSvcClipboardProviderImplURIWriteDataChunk(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const PVBOXCLIPBOARDDATAHDR pDataHdr, 112 const void *pvChunk, uint32_t cbChunk, uint32_t fFlags, uint32_t *pcbWritten) 113 { 114 RT_NOREF(pCtx, pDataHdr, pvChunk, cbChunk, fFlags, pcbWritten); 187 int vboxSvcClipboardURIObjOpen(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const char *pszPath, 188 PVBOXCLIPBOARDCREATEPARMS pCreateParms, PSHAREDCLIPBOARDOBJHANDLE phObj) 189 { 190 RT_NOREF(pCtx, pszPath, pCreateParms, phObj); 115 191 116 192 LogFlowFuncEnter(); … … 119 195 } 120 196 121 int VBoxSvcClipboardProviderImplURIReadDir(PSHAREDCLIPBOARDPROVIDERCTX pCtx, PVBOXCLIPBOARDDIRDATA *ppDirData) 122 { 123 RT_NOREF(pCtx, ppDirData); 197 int vboxSvcClipboardURIObjClose(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDOBJHANDLE hObj) 198 { 199 RT_NOREF(pCtx, hObj); 200 201 LogFlowFuncEnter(); 202 203 int rc = VINF_SUCCESS; 204 205 PVBOXCLIPBOARDCONTEXT pThisCtx = (PVBOXCLIPBOARDCONTEXT)pCtx->pvUser; 206 AssertPtr(pThisCtx); 207 208 LogFlowFuncLeaveRC(rc); 209 return rc; 210 } 211 212 int vboxSvcClipboardURIObjRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDOBJHANDLE hObj, 213 void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbRead) 214 { 215 RT_NOREF(pCtx, pCtx, hObj, pvData, cbData, fFlags, pcbRead); 124 216 125 217 LogFlowFuncEnter(); … … 128 220 } 129 221 130 int VBoxSvcClipboardProviderImplURIWriteDir(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const PVBOXCLIPBOARDDIRDATA pDirData) 131 { 132 RT_NOREF(pCtx, pDirData); 133 134 LogFlowFuncEnter(); 135 136 return VERR_NOT_IMPLEMENTED; 137 } 138 139 int VBoxSvcClipboardProviderImplURIReadFileHdr(PSHAREDCLIPBOARDPROVIDERCTX pCtx, PVBOXCLIPBOARDFILEHDR *ppFileHdr) 140 { 141 RT_NOREF(pCtx, ppFileHdr); 142 143 LogFlowFuncEnter(); 144 145 return VERR_NOT_IMPLEMENTED; 146 } 147 148 int VBoxSvcClipboardProviderImplURIWriteFileHdr(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const PVBOXCLIPBOARDFILEHDR pFileHdr) 149 { 150 RT_NOREF(pCtx, pFileHdr); 151 152 LogFlowFuncEnter(); 153 154 return VERR_NOT_IMPLEMENTED; 155 } 156 157 int VBoxSvcClipboardProviderImplURIReadFileData(PSHAREDCLIPBOARDPROVIDERCTX pCtx, void *pvData, uint32_t cbData, uint32_t fFlags, 158 uint32_t *pcbRead) 159 { 160 RT_NOREF(pCtx, pvData, cbData, fFlags, pcbRead); 161 162 LogFlowFuncEnter(); 163 164 return VERR_NOT_IMPLEMENTED; 165 } 166 167 int VBoxSvcClipboardProviderImplURIWriteFileData(PSHAREDCLIPBOARDPROVIDERCTX pCtx, void *pvData, uint32_t cbData, uint32_t fFlags, 168 uint32_t *pcbWritten) 169 { 170 RT_NOREF(pCtx, pvData, cbData, fFlags, pcbWritten); 222 int vboxSvcClipboardURIObjWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDOBJHANDLE hObj, 223 void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbWritten) 224 { 225 RT_NOREF(pCtx, pCtx, hObj, pvData, cbData, fFlags, pcbWritten); 171 226 172 227 LogFlowFuncEnter(); … … 184 239 LogFlowFuncEnter(); 185 240 186 LogFlowFuncEnter();187 188 241 AssertPtrReturnVoid(pData); 189 242 … … 191 244 AssertPtrReturnVoid(pClientData); 192 245 246 PSHAREDCLIPBOARDURITRANSFER pTransfer = pData->pTransfer; 247 AssertPtrReturnVoid(pTransfer); 248 249 /* Register needed events. */ 250 int rc2 = SharedClipboardURITransferEventRegister(pData->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_HDR_READ); 251 AssertRC(rc2); 252 rc2 = SharedClipboardURITransferEventRegister(pData->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_ENTRY_READ); 253 AssertRC(rc2); 254 255 #if 0 193 256 /* Tell the guest that it can start sending URI data. */ 194 int rc2 = vboxSvcClipboardReportMsg(pClientData, VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA,195 VBOX_SHARED_CLIPBOARD_FMT_URI_LIST);257 rc2 = vboxSvcClipboardReportMsg(pClientData, VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_TRANSFER_START, 258 0 /* u32Formats == 0 means reading data */); 196 259 AssertRC(rc2); 197 198 rc2 = SharedClipboardURITransferEventRegister(pData->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_METADATA_HDR); 199 AssertRC(rc2); 200 rc2 = SharedClipboardURITransferEventRegister(pData->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_METADATA_CHUNK); 201 AssertRC(rc2); 202 } 203 204 DECLCALLBACK(void) VBoxSvcClipboardURIDataHeaderCompleteCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData) 260 #endif 261 } 262 263 DECLCALLBACK(void) VBoxSvcClipboardURITransferCompleteCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData, int rc) 264 { 265 LogFlowFuncEnter(); 266 267 RT_NOREF(pData, rc); 268 269 LogRel2(("Shared Clipboard: Transfer complete\n")); 270 } 271 272 DECLCALLBACK(void) VBoxSvcClipboardURITransferCanceledCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData) 205 273 { 206 274 LogFlowFuncEnter(); 207 275 208 276 RT_NOREF(pData); 209 } 210 211 DECLCALLBACK(void) VBoxSvcClipboardURIDataCompleteCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData) 212 { 213 LogFlowFuncEnter(); 214 215 VBoxClipboardSvcImplURIOnDataHeaderComplete(pData); 216 } 217 218 DECLCALLBACK(void) VBoxSvcClipboardURITransferCompleteCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData, int rc) 277 278 LogRel2(("Shared Clipboard: Transfer canceled\n")); 279 } 280 281 DECLCALLBACK(void) VBoxSvcClipboardURITransferErrorCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData, int rc) 219 282 { 220 283 LogFlowFuncEnter(); … … 222 285 RT_NOREF(pData, rc); 223 286 224 LogRel2(("Shared Clipboard: Transfer complete\n"));225 }226 227 DECLCALLBACK(void) VBoxSvcClipboardURITransferCanceledCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData)228 {229 LogFlowFuncEnter();230 231 RT_NOREF(pData);232 233 LogRel2(("Shared Clipboard: Transfer canceled\n"));234 }235 236 DECLCALLBACK(void) VBoxSvcClipboardURITransferErrorCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData, int rc)237 {238 LogFlowFuncEnter();239 240 RT_NOREF(pData, rc);241 242 287 LogRel(("Shared Clipboard: Transfer failed with %Rrc\n", rc)); 243 288 } 244 289 245 290 /** 246 * Gets an URI dataheader from HGCM service parameters.291 * Gets an URI list header from HGCM service parameters. 247 292 * 248 293 * @returns VBox status code. 249 294 * @param cParms Number of HGCM parameters supplied in \a paParms. 250 295 * @param paParms Array of HGCM parameters. 251 * @param pDataHdr Where to store the result. 296 * @param phList Where to store the list handle. 297 * @param pListHdr Where to store the list header. 252 298 */ 253 int VBoxSvcClipboardURIGetDataHdr(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDDATAHDR pDataHdr) 299 int VBoxSvcClipboardURIGetListHdr(uint32_t cParms, VBOXHGCMSVCPARM paParms[], 300 PVBOXCLIPBOARDLISTHANDLE phList, PVBOXCLIPBOARDLISTHDR pListHdr) 254 301 { 255 302 int rc; 256 303 257 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_ WRITE_DATA_HDR)304 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR_WRITE) 258 305 { 259 306 /* Note: Context ID (paParms[0]) not used yet. */ 260 rc = HGCMSvcGetU32(&paParms[1], &pDataHdr->uFlags); 261 if (RT_SUCCESS(rc)) 262 rc = HGCMSvcGetU32(&paParms[2], &pDataHdr->uScreenId); 263 if (RT_SUCCESS(rc)) 264 rc = HGCMSvcGetU64(&paParms[3], &pDataHdr->cbTotal); 265 if (RT_SUCCESS(rc)) 266 rc = HGCMSvcGetU32(&paParms[4], &pDataHdr->cbMeta); 267 if (RT_SUCCESS(rc)) 268 rc = HGCMSvcGetU32(&paParms[5], &pDataHdr->cbMetaFmt); 269 if (RT_SUCCESS(rc)) 270 rc = HGCMSvcGetPv(&paParms[6], &pDataHdr->pvMetaFmt, &pDataHdr->cbMetaFmt); 271 if (RT_SUCCESS(rc)) 272 rc = HGCMSvcGetU64(&paParms[7], &pDataHdr->cObjects); 273 if (RT_SUCCESS(rc)) 274 rc = HGCMSvcGetU32(&paParms[8], &pDataHdr->enmCompression); 275 if (RT_SUCCESS(rc)) 276 rc = HGCMSvcGetU32(&paParms[9], (uint32_t *)&pDataHdr->enmChecksumType); 277 if (RT_SUCCESS(rc)) 278 rc = HGCMSvcGetU32(&paParms[10], &pDataHdr->cbChecksum); 279 if (RT_SUCCESS(rc)) 280 rc = HGCMSvcGetPv(&paParms[11], &pDataHdr->pvChecksum, &pDataHdr->cbChecksum); 281 282 LogFlowFunc(("fFlags=0x%x, cbMeta=%RU32, cbTotalSize=%RU64, cObj=%RU64\n", 283 pDataHdr->uFlags, pDataHdr->cbMeta, pDataHdr->cbTotal, pDataHdr->cObjects)); 307 rc = HGCMSvcGetU64(&paParms[1], phList); 308 if (RT_SUCCESS(rc)) 309 rc = HGCMSvcGetU64(&paParms[2], &pListHdr->cTotalObjects); 310 if (RT_SUCCESS(rc)) 311 rc = HGCMSvcGetU64(&paParms[3], &pListHdr->cbTotalSize); 312 if (RT_SUCCESS(rc)) 313 rc = HGCMSvcGetU32(&paParms[4], &pListHdr->enmCompression); 314 if (RT_SUCCESS(rc)) 315 rc = HGCMSvcGetU32(&paParms[5], (uint32_t *)&pListHdr->enmChecksumType); 284 316 285 317 if (RT_SUCCESS(rc)) … … 297 329 298 330 /** 299 * Sets an URI dataheader to HGCM service parameters.331 * Sets an URI list header to HGCM service parameters. 300 332 * 301 333 * @returns VBox status code. 302 334 * @param cParms Number of HGCM parameters supplied in \a paParms. 303 335 * @param paParms Array of HGCM parameters. 304 * @param p DataHdr Pointer to data to set to the HGCM parameters.336 * @param pListHdr Pointer to data to set to the HGCM parameters. 305 337 */ 306 int VBoxSvcClipboardURISet DataHdr(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDDATAHDR pDataHdr)338 int VBoxSvcClipboardURISetListHdr(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDLISTHDR pListHdr) 307 339 { 308 340 int rc; 309 341 310 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_ READ_DATA_HDR)342 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR_READ) 311 343 { 312 344 /** @todo Set pvMetaFmt + cbMetaFmt. */ … … 314 346 315 347 /* Note: Context ID (paParms[0]) not used yet. */ 316 HGCMSvcSetU32(&paParms[1], pDataHdr->uFlags); 317 HGCMSvcSetU32(&paParms[2], pDataHdr->uScreenId); 318 HGCMSvcSetU64(&paParms[3], pDataHdr->cbTotal); 319 HGCMSvcSetU32(&paParms[4], pDataHdr->cbMeta); 320 HGCMSvcSetU32(&paParms[5], pDataHdr->cbMetaFmt); 321 HGCMSvcSetPv (&paParms[6], pDataHdr->pvMetaFmt, pDataHdr->cbMetaFmt); 322 HGCMSvcSetU64(&paParms[7], pDataHdr->cObjects); 323 HGCMSvcSetU32(&paParms[8], pDataHdr->enmCompression); 324 HGCMSvcSetU32(&paParms[9], (uint32_t)pDataHdr->enmChecksumType); 325 HGCMSvcSetU32(&paParms[10], pDataHdr->cbChecksum); 326 HGCMSvcSetPv (&paParms[11], pDataHdr->pvChecksum, pDataHdr->cbChecksum); 327 328 LogFlowFunc(("fFlags=0x%x, cbMeta=%RU32, cbTotalSize=%RU64, cObj=%RU64\n", 329 pDataHdr->uFlags, pDataHdr->cbMeta, pDataHdr->cbTotal, pDataHdr->cObjects)); 348 HGCMSvcSetU32(&paParms[1], pListHdr->fList); 349 HGCMSvcSetU32(&paParms[2], pListHdr->fFeatures); 350 HGCMSvcSetU32(&paParms[3], pListHdr->cbFilter); 351 HGCMSvcSetPv (&paParms[4], pListHdr->pszFilter, pListHdr->cbFilter); 352 HGCMSvcSetU64(&paParms[5], pListHdr->cTotalObjects); 353 HGCMSvcSetU64(&paParms[6], pListHdr->cbTotalSize); 354 HGCMSvcSetU32(&paParms[7], pListHdr->enmCompression); 355 HGCMSvcSetU32(&paParms[8], (uint32_t)pListHdr->enmChecksumType); 330 356 331 357 rc = VINF_SUCCESS; … … 339 365 340 366 /** 341 * Gets an URI data chunkfrom HGCM service parameters.367 * Gets an URI list entry from HGCM service parameters. 342 368 * 343 369 * @returns VBox status code. 344 370 * @param cParms Number of HGCM parameters supplied in \a paParms. 345 371 * @param paParms Array of HGCM parameters. 346 * @param pDataChunk Where to store the result. 372 * @param phList Where to store the list handle. 373 * @param pListEntry Where to store the list entry. 347 374 */ 348 int VBoxSvcClipboardURIGetDataChunk(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDDATACHUNK pDataChunk) 375 int VBoxSvcClipboardURIGetListEntry(uint32_t cParms, VBOXHGCMSVCPARM paParms[], 376 PVBOXCLIPBOARDLISTHANDLE phList, PVBOXCLIPBOARDLISTENTRY pListEntry) 349 377 { 350 378 int rc; 351 379 352 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_ WRITE_DATA_CHUNK)380 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY_WRITE) 353 381 { 354 382 /* Note: Context ID (paParms[0]) not used yet. */ 355 rc = HGCMSvcGetU 32(&paParms[1], &pDataChunk->cbData);356 if (RT_SUCCESS(rc)) 357 rc = HGCMSvcGet Pv(&paParms[2], &pDataChunk->pvData, &pDataChunk->cbData);358 if (RT_SUCCESS(rc)) 359 rc = HGCMSvcGetU32(&paParms[3], &p DataChunk->cbChecksum);360 if (RT_SUCCESS(rc)) 361 rc = HGCMSvcGetPv(&paParms[4], &p DataChunk->pvChecksum, &pDataChunk->cbChecksum);362 363 if (RT_SUCCESS(rc)) 364 { 365 if (!SharedClipboardURI DataChunkIsValid(pDataChunk))383 rc = HGCMSvcGetU64(&paParms[1], phList); 384 if (RT_SUCCESS(rc)) 385 rc = HGCMSvcGetU32(&paParms[2], &pListEntry->fInfo); 386 if (RT_SUCCESS(rc)) 387 rc = HGCMSvcGetU32(&paParms[3], &pListEntry->cbInfo); 388 if (RT_SUCCESS(rc)) 389 rc = HGCMSvcGetPv(&paParms[4], &pListEntry->pvInfo, &pListEntry->cbInfo); 390 391 if (RT_SUCCESS(rc)) 392 { 393 if (!SharedClipboardURIListEntryIsValid(pListEntry)) 366 394 rc = VERR_INVALID_PARAMETER; 367 395 } … … 380 408 * @param cParms Number of HGCM parameters supplied in \a paParms. 381 409 * @param paParms Array of HGCM parameters. 382 * @param p DataChunkPointer to data to set to the HGCM parameters.410 * @param pListEntry Pointer to data to set to the HGCM parameters. 383 411 */ 384 int VBoxSvcClipboardURISet DataChunk(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDDATACHUNK pDataChunk)412 int VBoxSvcClipboardURISetListEntry(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDLISTENTRY pListEntry) 385 413 { 386 414 int rc; 387 415 388 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_ READ_DATA_CHUNK)416 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY_READ) 389 417 { 390 418 /** @todo Calculate chunk checksum. */ 391 419 392 420 /* Note: Context ID (paParms[0]) not used yet. */ 393 HGCMSvcSetU32(&paParms[1], pDataChunk->cbData); 394 HGCMSvcSetPv (&paParms[2], pDataChunk->pvData, pDataChunk->cbData); 395 HGCMSvcSetU32(&paParms[3], pDataChunk->cbChecksum); 396 HGCMSvcSetPv (&paParms[4], pDataChunk->pvChecksum, pDataChunk->cbChecksum); 421 HGCMSvcSetU32(&paParms[1], pListEntry->fInfo); 422 HGCMSvcSetU32(&paParms[2], pListEntry->cbInfo); 423 HGCMSvcSetPv (&paParms[3], pListEntry->pvInfo, pListEntry->cbInfo); 397 424 398 425 rc = VINF_SUCCESS; … … 405 432 } 406 433 407 /** 408 * Gets an URI directory entry from HGCM service parameters. 409 * 410 * @returns VBox status code. 411 * @param cParms Number of HGCM parameters supplied in \a paParms. 412 * @param paParms Array of HGCM parameters. 413 * @param pDirData Where to store the result. 414 */ 415 int VBoxSvcClipboardURIGetDir(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDDIRDATA pDirData) 416 { 434 int VBoxSvcClipboardURIGetError(uint32_t cParms, VBOXHGCMSVCPARM paParms[], int *pRc) 435 { 436 AssertPtrReturn(paParms, VERR_INVALID_PARAMETER); 437 AssertPtrReturn(pRc, VERR_INVALID_PARAMETER); 438 417 439 int rc; 418 440 419 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_ WRITE_DIR)441 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_ERROR) 420 442 { 421 443 /* Note: Context ID (paParms[0]) not used yet. */ 422 rc = HGCMSvcGetU32(&paParms[1], &pDirData->cbPath); 423 if (RT_SUCCESS(rc)) 424 rc = HGCMSvcGetPv(&paParms[2], (void **)&pDirData->pszPath, &pDirData->cbPath); 425 if (RT_SUCCESS(rc)) 426 rc = HGCMSvcGetU32(&paParms[3], &pDirData->fMode); 427 428 LogFlowFunc(("pszPath=%s, cbPath=%RU32, fMode=0x%x\n", pDirData->pszPath, pDirData->cbPath, pDirData->fMode)); 429 430 if (RT_SUCCESS(rc)) 431 { 432 if (!SharedClipboardURIDirDataIsValid(pDirData)) 433 rc = VERR_INVALID_PARAMETER; 434 } 435 } 436 else 437 rc = VERR_INVALID_PARAMETER; 438 439 LogFlowFuncLeaveRC(rc); 440 return rc; 441 } 442 443 /** 444 * Sets an URI directory entry to HGCM service parameters. 445 * 446 * @returns VBox status code. 447 * @param cParms Number of HGCM parameters supplied in \a paParms. 448 * @param paParms Array of HGCM parameters. 449 * @param pDirData Pointer to data to set to the HGCM parameters. 450 */ 451 int VBoxSvcClipboardURISetDir(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDDIRDATA pDirData) 452 { 453 int rc; 454 455 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_READ_DIR) 456 { 457 /* Note: Context ID (paParms[0]) not used yet. */ 458 HGCMSvcSetU32(&paParms[1], pDirData->cbPath); 459 HGCMSvcSetPv (&paParms[2], pDirData->pszPath, pDirData->cbPath); 460 HGCMSvcSetU32(&paParms[3], pDirData->fMode); 461 462 rc = VINF_SUCCESS; 463 } 464 else 465 rc = VERR_INVALID_PARAMETER; 466 467 LogFlowFuncLeaveRC(rc); 468 return rc; 469 } 470 471 /** 472 * Reads an URI file header from HGCM service parameters. 473 * 474 * @returns VBox status code. 475 * @param cParms Number of HGCM parameters supplied in \a paParms. 476 * @param paParms Array of HGCM parameters. 477 * @param pFileHdr Where to store the result. 478 */ 479 int VBoxSvcClipboardURIGetFileHdr(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDFILEHDR pFileHdr) 480 { 481 int rc; 482 483 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_FILE_HDR) 484 { 485 /* Note: Context ID (paParms[0]) not used yet. */ 486 rc = HGCMSvcGetU32(&paParms[1], &pFileHdr->cbFilePath); 487 if (RT_SUCCESS(rc)) 488 rc = HGCMSvcGetPv(&paParms[2], (void **)&pFileHdr->pszFilePath, &pFileHdr->cbFilePath); 489 if (RT_SUCCESS(rc)) 490 rc = HGCMSvcGetU32(&paParms[3], &pFileHdr->fFlags); 491 if (RT_SUCCESS(rc)) 492 rc = HGCMSvcGetU32(&paParms[4], &pFileHdr->fMode); 493 if (RT_SUCCESS(rc)) 494 rc = HGCMSvcGetU64(&paParms[5], &pFileHdr->cbSize); 495 496 LogFlowFunc(("pszPath=%s, cbPath=%RU32, fMode=0x%x, cbSize=%RU64\n", 497 pFileHdr->pszFilePath, pFileHdr->cbFilePath, pFileHdr->fMode, pFileHdr->cbSize)); 498 } 499 else 500 rc = VERR_INVALID_PARAMETER; 501 502 LogFlowFuncLeaveRC(rc); 503 return rc; 504 } 505 506 /** 507 * Sets an URI file header to HGCM service parameters. 508 * 509 * @returns VBox status code. 510 * @param cParms Number of HGCM parameters supplied in \a paParms. 511 * @param paParms Array of HGCM parameters. 512 * @param pFileHdr Pointer to data to set to the HGCM parameters. 513 */ 514 int VBoxSvcClipboardURISetFileHdr(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDFILEHDR pFileHdr) 515 { 516 int rc; 517 518 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_READ_FILE_HDR) 519 { 520 /* Note: Context ID (paParms[0]) not used yet. */ 521 HGCMSvcSetU32(&paParms[1], pFileHdr->cbFilePath); 522 HGCMSvcSetPv (&paParms[2], pFileHdr->pszFilePath, pFileHdr->cbFilePath); 523 HGCMSvcSetU32(&paParms[3], pFileHdr->fFlags); 524 HGCMSvcSetU32(&paParms[4], pFileHdr->fMode); 525 HGCMSvcSetU64(&paParms[5], pFileHdr->cbSize); 526 527 rc = VINF_SUCCESS; 528 } 529 else 530 rc = VERR_INVALID_PARAMETER; 531 532 LogFlowFuncLeaveRC(rc); 533 return rc; 534 } 535 536 /** 537 * Gets an URI file data chunk from HGCM service parameters. 538 * 539 * @returns VBox status code. 540 * @param cParms Number of HGCM parameters supplied in \a paParms. 541 * @param paParms Array of HGCM parameters. 542 * @param pFileData Where to store the result. 543 */ 544 int VBoxSvcClipboardURIGetFileData(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDFILEDATA pFileData) 545 { 546 int rc; 547 548 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_FILE_DATA) 549 { 550 /* Note: Context ID (paParms[0]) not used yet. */ 551 rc = HGCMSvcGetU32(&paParms[1], &pFileData->cbData); 552 if (RT_SUCCESS(rc)) 553 rc = HGCMSvcGetPv(&paParms[2], &pFileData->pvData, &pFileData->cbData); 554 if (RT_SUCCESS(rc)) 555 rc = HGCMSvcGetU32(&paParms[3], &pFileData->cbChecksum); 556 if (RT_SUCCESS(rc)) 557 rc = HGCMSvcGetPv(&paParms[4], &pFileData->pvChecksum, &pFileData->cbChecksum); 558 559 LogFlowFunc(("pvData=0x%p, cbData=%RU32\n", pFileData->pvData, pFileData->cbData)); 560 } 561 else 562 rc = VERR_INVALID_PARAMETER; 563 564 LogFlowFuncLeaveRC(rc); 565 return rc; 566 } 567 568 /** 569 * Sets an URI file data chunk to HGCM service parameters. 570 * 571 * @returns VBox status code. 572 * @param cParms Number of HGCM parameters supplied in \a paParms. 573 * @param paParms Array of HGCM parameters. 574 * @param pFileData Pointer to data to set to the HGCM parameters. 575 */ 576 int VBoxSvcClipboardURISetFileData(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDFILEDATA pFileData) 577 { 578 int rc; 579 580 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_READ_FILE_DATA) 581 { 582 /* Note: Context ID (paParms[0]) not used yet. */ 583 HGCMSvcSetU32(&paParms[1], pFileData->cbData); 584 HGCMSvcSetPv (&paParms[2], pFileData->pvData, pFileData->cbData); 585 HGCMSvcSetU32(&paParms[3], pFileData->cbChecksum); 586 HGCMSvcSetPv (&paParms[4], pFileData->pvChecksum, pFileData->cbChecksum); 587 588 rc = VINF_SUCCESS; 444 rc = HGCMSvcGetU32(&paParms[1], (uint32_t *)pRc); /** @todo int vs. uint32_t !!! */ 589 445 } 590 446 else … … 599 455 * 600 456 * @returns VBox status code. 601 * @param u32ClientID Client ID of the client which called this handler.602 * @param pvClient Pointer to client-specific data block.457 * @param pClient Pointer to associated client. 458 * @param callHandle The client's call handle of this call. 603 459 * @param u32Function Function number being called. 604 460 * @param cParms Number of function parameters supplied. 605 461 * @param paParms Array function parameters supplied. 606 462 * @param tsArrival Timestamp of arrival. 607 * @param pfAsync Returns \c true if the response needs to be being asynchronous or \c false if not,608 463 */ 609 int vboxSvcClipboardURIHandler( uint32_t u32ClientID,610 void *pvClient,464 int vboxSvcClipboardURIHandler(PVBOXCLIPBOARDCLIENT pClient, 465 VBOXHGCMCALLHANDLE callHandle, 611 466 uint32_t u32Function, 612 467 uint32_t cParms, 613 468 VBOXHGCMSVCPARM paParms[], 614 uint64_t tsArrival, 615 bool *pfAsync) 616 { 617 RT_NOREF(u32ClientID, paParms, tsArrival, pfAsync); 618 619 LogFlowFunc(("u32ClientID=%RU32, u32Function=%RU32, cParms=%RU32, g_pfnExtension=%p\n", 620 u32ClientID, u32Function, cParms, g_pfnExtension)); 621 622 const PVBOXCLIPBOARDCLIENTDATA pClientData = (PVBOXCLIPBOARDCLIENTDATA)pvClient; 469 uint64_t tsArrival) 470 { 471 RT_NOREF(paParms, tsArrival); 472 473 LogFlowFunc(("uClient=%RU32, u32Function=%RU32, cParms=%RU32, g_pfnExtension=%p\n", 474 pClient->uClientID, u32Function, cParms, g_pfnExtension)); 475 476 const PVBOXCLIPBOARDCLIENTDATA pClientData = pClient->pData; 623 477 AssertPtrReturn(pClientData, VERR_INVALID_POINTER); 624 478 625 479 /* Check if we've the right mode set. */ 626 480 if (!vboxSvcClipboardURIMsgIsAllowed(vboxSvcClipboardGetMode(), u32Function)) 481 { 482 LogFunc(("Wrong clipboard mode, denying access\n")); 627 483 return VERR_ACCESS_DENIED; 484 } 628 485 629 486 /* A (valid) service extension is needed because VBoxSVC needs to keep track of the … … 638 495 } 639 496 640 if (!SharedClipboardURICtxGetTotalTransfers(&pClientData->URI)) 641 { 642 LogFunc(("No transfers found\n")); 643 return VERR_WRONG_ORDER; 644 } 645 646 const uint32_t uTransferID = 0; /* Only one transfer is supported at the moment. */ 647 648 const PSHAREDCLIPBOARDURITRANSFER pTransfer = SharedClipboardURICtxGetTransfer(&pClientData->URI, uTransferID); 649 if (!pTransfer) 650 { 651 LogFunc(("Transfer with ID %RU32 not found\n", uTransferID)); 652 return VERR_WRONG_ORDER; 653 } 654 655 bool fWriteToProvider = false; /* Whether to (also) dispatch the HGCM data to the transfer provider. */ 656 657 int rc = VERR_INVALID_PARAMETER; /* Play safe. */ 658 497 int rc = VINF_SUCCESS; 498 499 /* 500 * Pre-check: For certain messages we need to make sure that a (right) transfer is present. 501 */ 502 PSHAREDCLIPBOARDURITRANSFER pTransfer = NULL; 659 503 switch (u32Function) 660 504 { 661 case VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_DATA_HDR: 662 { 663 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_DATA_HDR\n")); 664 665 VBOXCLIPBOARDDATAHDR dataHdr; 666 rc = VBoxSvcClipboardURISetDataHdr(cParms, paParms, &dataHdr); 667 break; 668 } 669 670 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DATA_HDR: 671 { 672 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DATA_HDR\n")); 673 674 VBOXCLIPBOARDDATAHDR dataHdr; 675 rc = SharedClipboardURIDataHdrInit(&dataHdr); 676 if (RT_SUCCESS(rc)) 677 { 678 rc = VBoxSvcClipboardURIGetDataHdr(cParms, paParms, &dataHdr); 505 case VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG: 506 RT_FALL_THROUGH(); 507 case VBOX_SHARED_CLIPBOARD_GUEST_FN_TRANSFER_REPORT: 508 break; 509 default: 510 { 511 if (!SharedClipboardURICtxGetTotalTransfers(&pClientData->URI)) 512 { 513 LogFunc(("No transfers found\n")); 514 rc = VERR_WRONG_ORDER; 515 break; 516 } 517 518 const uint32_t uTransferID = 0; /* Only one transfer per client is supported at the moment. */ 519 520 pTransfer = SharedClipboardURICtxGetTransfer(&pClientData->URI, uTransferID); 521 if (!pTransfer) 522 { 523 LogFunc(("Transfer with ID %RU32 not found\n", uTransferID)); 524 rc = VERR_WRONG_ORDER; 525 } 526 break; 527 } 528 } 529 530 if (RT_FAILURE(rc)) 531 return rc; 532 533 rc = VERR_INVALID_PARAMETER; /* Play safe. */ 534 535 switch (u32Function) 536 { 537 case VBOX_SHARED_CLIPBOARD_GUEST_FN_TRANSFER_REPORT: 538 { 539 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_TRANSFER_REPORT\n")); 540 541 if (!SharedClipboardURICtxTransfersMaximumReached(&pClientData->URI)) 542 { 543 SharedClipboardURICtxTransfersCleanup(&pClientData->URI); 544 545 SHAREDCLIPBOARDURITRANSFERDIR enmDir = SHAREDCLIPBOARDURITRANSFERDIR_READ; 546 547 PSHAREDCLIPBOARDURITRANSFER pTransfer; 548 rc = SharedClipboardURITransferCreate(enmDir, 549 SHAREDCLIPBOARDSOURCE_REMOTE, &pTransfer); 679 550 if (RT_SUCCESS(rc)) 680 551 { 681 void *pvData = SharedClipboardURIDataHdrDup(&dataHdr); 682 uint32_t cbData = sizeof(VBOXCLIPBOARDDATAHDR); 552 rc = vboxSvcClipboardURIAreaRegister(&pClientData->State, pTransfer); 553 if (RT_SUCCESS(rc)) 554 { 555 SHAREDCLIPBOARDPROVIDERCREATIONCTX creationCtx; 556 RT_ZERO(creationCtx); 557 558 creationCtx.enmSource = pClientData->State.enmSource; 559 560 RT_ZERO(creationCtx.Interface); 561 creationCtx.Interface.pfnTransferOpen = vboxSvcClipboardURITransferOpen; 562 creationCtx.Interface.pfnTransferClose = vboxSvcClipboardURITransferClose; 563 creationCtx.Interface.pfnListOpen = vboxSvcClipboardURIListOpen; 564 creationCtx.Interface.pfnListClose = vboxSvcClipboardURIListClose; 565 creationCtx.Interface.pfnObjOpen = vboxSvcClipboardURIObjOpen; 566 creationCtx.Interface.pfnObjClose = vboxSvcClipboardURIObjClose; 567 568 if (enmDir == SHAREDCLIPBOARDURITRANSFERDIR_READ) 569 { 570 creationCtx.Interface.pfnListHdrRead = vboxSvcClipboardURIListHdrRead; 571 creationCtx.Interface.pfnListEntryRead = vboxSvcClipboardURIListEntryRead; 572 creationCtx.Interface.pfnObjRead = vboxSvcClipboardURIObjRead; 573 } 574 else 575 { 576 AssertFailed(); 577 } 578 579 creationCtx.pvUser = pClient; 580 581 /* Register needed callbacks so that we can wait for the meta data to arrive here. */ 582 SHAREDCLIPBOARDURITRANSFERCALLBACKS Callbacks; 583 RT_ZERO(Callbacks); 584 585 Callbacks.pvUser = pClientData; 586 587 Callbacks.pfnTransferPrepare = VBoxSvcClipboardURITransferPrepareCallback; 588 Callbacks.pfnTransferComplete = VBoxSvcClipboardURITransferCompleteCallback; 589 Callbacks.pfnTransferCanceled = VBoxSvcClipboardURITransferCanceledCallback; 590 Callbacks.pfnTransferError = VBoxSvcClipboardURITransferErrorCallback; 591 592 SharedClipboardURITransferSetCallbacks(pTransfer, &Callbacks); 593 594 rc = SharedClipboardURITransferProviderCreate(pTransfer, &creationCtx); 595 if (RT_SUCCESS(rc)) 596 rc = SharedClipboardURICtxTransferAdd(&pClientData->URI, pTransfer); 597 } 598 599 if (RT_SUCCESS(rc)) 600 { 601 rc = VBoxClipboardSvcImplURITransferCreate(pClientData, pTransfer); 602 if (RT_SUCCESS(rc)) 603 rc = VBoxClipboardSvcImplFormatAnnounce(pClientData, VBOX_SHARED_CLIPBOARD_FMT_URI_LIST); 604 } 605 606 if (RT_FAILURE(rc)) 607 { 608 VBoxClipboardSvcImplURITransferDestroy(pClientData, pTransfer); 609 SharedClipboardURITransferDestroy(pTransfer); 610 } 611 } 612 } 613 else 614 rc = VERR_SHCLPB_MAX_TRANSFERS_REACHED; 615 616 LogFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_TRANSFER_REPORT: %Rrc\n", rc)); 617 618 if (RT_FAILURE(rc)) 619 LogRel(("Shared Clipboard: Initializing transfer failed with %Rrc\n", rc)); 620 621 break; 622 } 623 624 case VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG: 625 { 626 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_GET_HOST_MSG) 627 { 628 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG\n")); 629 rc = vboxSvcClipboardMsgGetNextInfo(&pClientData->State, 630 &paParms[0].u.uint32 /* uMsg */, &paParms[1].u.uint32 /* cParms */); 631 632 /* No (new) messages available or some error occurred? */ 633 if ( rc == VERR_NO_DATA 634 || RT_FAILURE(rc)) 635 { 636 uint32_t fFlags = 0; 637 int rc2 = HGCMSvcGetU32(&paParms[2], &fFlags); 638 if ( RT_SUCCESS(rc2) 639 && fFlags) /* Blocking flag set? */ 640 { 641 /* Defer client returning. */ 642 rc = VINF_HGCM_ASYNC_EXECUTE; 643 } 644 else 645 rc = VERR_INVALID_PARAMETER; 646 647 LogFlowFunc(("Message queue is empty, returning %Rrc to guest\n", rc)); 648 } 649 } 650 break; 651 } 652 653 case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_OPEN: 654 { 655 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_OPEN\n")); 656 rc = VINF_SUCCESS; 657 break; 658 } 659 660 case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_CLOSE: 661 { 662 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_CLOSE\n")); 663 rc = VINF_SUCCESS; 664 break; 665 } 666 667 case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_READ: 668 { 669 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_LIST_HDR\n")); 670 671 VBOXCLIPBOARDLISTHANDLE hList; 672 VBOXCLIPBOARDLISTHDR hdrList; 673 rc = VBoxSvcClipboardURIGetListHdr(cParms, paParms, &hList, &hdrList); 674 if (RT_SUCCESS(rc)) 675 { 676 if (RT_SUCCESS(rc)) 677 rc = VBoxSvcClipboardURISetListHdr(cParms, paParms, &hdrList); 678 } 679 break; 680 } 681 682 case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_WRITE: 683 { 684 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_LIST_HDR\n")); 685 686 VBOXCLIPBOARDLISTHDR hdrList; 687 rc = SharedClipboardURIListHdrInit(&hdrList); 688 if (RT_SUCCESS(rc)) 689 { 690 VBOXCLIPBOARDLISTHANDLE hList; 691 rc = VBoxSvcClipboardURIGetListHdr(cParms, paParms, &hList, &hdrList); 692 if (RT_SUCCESS(rc)) 693 { 694 void *pvData = SharedClipboardURIListHdrDup(&hdrList); 695 uint32_t cbData = sizeof(VBOXCLIPBOARDLISTHDR); 683 696 684 697 PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload; 685 rc = SharedClipboardURITransferPayloadAlloc(SHAREDCLIPBOARDURITRANSFEREVENTTYPE_ METADATA_HDR,698 rc = SharedClipboardURITransferPayloadAlloc(SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_HDR_READ, 686 699 pvData, cbData, &pPayload); 687 700 if (RT_SUCCESS(rc)) 688 701 { 689 rc = SharedClipboardURITransferEventSignal(pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_ METADATA_HDR,702 rc = SharedClipboardURITransferEventSignal(pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_HDR_READ, 690 703 pPayload); 691 704 } … … 695 708 } 696 709 697 case VBOX_SHARED_CLIPBOARD_GUEST_FN_ READ_DATA_CHUNK:698 { 699 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_ DATA_CHUNK\n"));700 break; 701 } 702 703 case VBOX_SHARED_CLIPBOARD_GUEST_FN_ WRITE_DATA_CHUNK:704 { 705 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_ DATA_CHUNK\n"));706 707 VBOXCLIPBOARD DATACHUNK dataChunk;708 rc = SharedClipboardURI DataChunkInit(&dataChunk);710 case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_ENTRY_READ: 711 { 712 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_LIST_ENTRY\n")); 713 break; 714 } 715 716 case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_ENTRY_WRITE: 717 { 718 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_LIST_ENTRY\n")); 719 720 VBOXCLIPBOARDLISTENTRY entryList; 721 rc = SharedClipboardURIListEntryInit(&entryList); 709 722 if (RT_SUCCESS(rc)) 710 723 { 711 rc = VBoxSvcClipboardURIGetDataChunk(cParms, paParms, &dataChunk); 724 VBOXCLIPBOARDLISTHANDLE hList; 725 rc = VBoxSvcClipboardURIGetListEntry(cParms, paParms, &hList, &entryList); 712 726 if (RT_SUCCESS(rc)) 713 727 { 714 void *pvData = SharedClipboardURI DataChunkDup(&dataChunk);715 uint32_t cbData = sizeof(VBOXCLIPBOARD DATACHUNK);728 void *pvData = SharedClipboardURIListEntryDup(&entryList); 729 uint32_t cbData = sizeof(VBOXCLIPBOARDLISTENTRY); 716 730 717 731 PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload; 718 rc = SharedClipboardURITransferPayloadAlloc(SHAREDCLIPBOARDURITRANSFEREVENTTYPE_ METADATA_CHUNK,732 rc = SharedClipboardURITransferPayloadAlloc(SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_ENTRY_READ, 719 733 pvData, cbData, &pPayload); 720 734 if (RT_SUCCESS(rc)) 721 735 { 722 rc = SharedClipboardURITransferEventSignal(pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_ METADATA_CHUNK,736 rc = SharedClipboardURITransferEventSignal(pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_ENTRY_READ, 723 737 pPayload); 724 738 } … … 728 742 break; 729 743 } 730 731 case VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_DIR: 732 { 733 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_DIR\n")); 734 735 VBOXCLIPBOARDDIRDATA data; 736 rc = VBoxSvcClipboardURISetDir(cParms, paParms, &data); 737 break; 738 } 739 744 #if 0 740 745 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DIR: 741 746 { … … 906 911 break; 907 912 } 908 909 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_CANCEL: 910 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_CANCEL\n")); 911 AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED); 912 break; 913 914 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_ERROR: 915 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_ERROR\n")); 916 AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED); 917 break; 913 #endif 914 case VBOX_SHARED_CLIPBOARD_GUEST_FN_CANCEL: 915 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_CANCEL\n")); 916 917 LogRel2(("Shared Clipboard: Transfer canceled\n")); 918 break; 919 920 case VBOX_SHARED_CLIPBOARD_GUEST_FN_ERROR: 921 { 922 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_ERROR\n")); 923 924 int rcGuest; 925 rc = VBoxSvcClipboardURIGetError(cParms,paParms, &rcGuest); 926 if (RT_SUCCESS(rc)) 927 LogRel(("Shared Clipboard: Transfer error: %Rrc\n", rcGuest)); 928 break; 929 } 918 930 919 931 default: … … 922 934 } 923 935 924 if (fWriteToProvider) 925 rc = VINF_SUCCESS; 926 927 if (RT_SUCCESS(rc)) 928 { 929 if (fWriteToProvider) 930 { 931 SHAREDCLIPBOARDPROVIDERWRITEPARMS writeParms; 932 RT_ZERO(writeParms); 933 934 writeParms.u.HostService.uMsg = u32Function; 935 writeParms.u.HostService.cParms = cParms; 936 writeParms.u.HostService.paParms = paParms; 937 938 //rc = pTransfer->pProvider->OnWrite(&writeParms); 939 } 940 } 941 942 LogFlowFuncLeaveRC(rc); 936 if (rc == VINF_HGCM_ASYNC_EXECUTE) 937 { 938 try 939 { 940 vboxSvcClipboardClientDefer(pClient, callHandle, u32Function, cParms, paParms); 941 g_listClientsDeferred.push_back(pClient->uClientID); 942 } 943 catch (std::bad_alloc &) 944 { 945 rc = VERR_NO_MEMORY; 946 /* Don't report to guest. */ 947 } 948 } 949 else if (pClient) 950 { 951 int rc2 = vboxSvcClipboardClientComplete(pClient, callHandle, rc); 952 AssertRC(rc2); 953 } 954 955 LogFlowFunc(("Returning uClient=%RU32, rc=%Rrc\n", pClient->uClientID, rc)); 943 956 return rc; 944 957 } … … 958 971 RT_NOREF(cParms, paParms); 959 972 960 int rc = VERR_ INVALID_PARAMETER; /* Play safe. */973 int rc = VERR_NOT_IMPLEMENTED; /* Play safe. */ 961 974 962 975 switch (u32Function) 963 976 { 964 977 case VBOX_SHARED_CLIPBOARD_HOST_FN_CANCEL: 965 AssertFailed(); /** @todo Implement this.*/978 /** @todo */ 966 979 break; 967 980 968 981 case VBOX_SHARED_CLIPBOARD_HOST_FN_ERROR: 969 AssertFailed(); /** @todo Implement this.*/982 /** @todo */ 970 983 break; 971 984 972 985 default: 973 AssertMsgFailed(("Not implemented\n"));974 986 break; 975 987 … … 1006 1018 1007 1019 parms.uID = NIL_SHAREDCLIPBOARDAREAID; 1008 1009 if (pTransfer->State.pMeta)1010 {1011 parms.u.fn_register.pvData = SharedClipboardMetaDataMutableRaw(pTransfer->State.pMeta);1012 parms.u.fn_register.cbData = (uint32_t)SharedClipboardMetaDataGetUsed(pTransfer->State.pMeta);1013 }1014 1020 1015 1021 /* As the meta data is now complete, register a new clipboard on the host side. */ -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-uri.h
r79347 r79497 22 22 #endif 23 23 24 //int vboxSvcClipboardURIAnnounce(uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 25 26 int vboxSvcClipboardURIHandler(uint32_t u32ClientID, void *pvClient, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[], uint64_t tsArrival, bool *pfAsync); 24 int vboxSvcClipboardURIHandler(PVBOXCLIPBOARDCLIENT pClient, VBOXHGCMCALLHANDLE callHandle, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[], uint64_t tsArrival); 27 25 int vboxSvcClipboardURIHostHandler(uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 28 26 -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-utils.cpp
r79347 r79497 52 52 switch (uMsg) 53 53 { 54 case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_READ_DATA_HDR: 55 RT_FALL_THROUGH(); 56 case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_READ_DATA_CHUNK: 57 RT_FALL_THROUGH(); 58 case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_READ_DIR: 59 RT_FALL_THROUGH(); 60 case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_READ_FILE_HDR: 61 RT_FALL_THROUGH(); 62 case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_READ_FILE_DATA: 54 case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_OPEN: 55 RT_FALL_THROUGH(); 56 case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_CLOSE: 57 RT_FALL_THROUGH(); 58 case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_READ: 59 RT_FALL_THROUGH(); 60 case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_ENTRY_READ: 61 RT_FALL_THROUGH(); 62 case VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_OPEN: 63 RT_FALL_THROUGH(); 64 case VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_CLOSE: 65 RT_FALL_THROUGH(); 66 case VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_READ: 67 fAllowed = fHostToGuest; 68 break; 69 70 case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_WRITE: 71 RT_FALL_THROUGH(); 72 case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_ENTRY_WRITE: 73 RT_FALL_THROUGH(); 74 case VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_WRITE: 63 75 fAllowed = fGuestToHost; 64 76 break; 65 77 66 case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_WRITE_DATA_HDR: 67 RT_FALL_THROUGH(); 68 case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_WRITE_DATA_CHUNK: 69 RT_FALL_THROUGH(); 70 case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_WRITE_DIR: 71 RT_FALL_THROUGH(); 72 case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_WRITE_FILE_HDR: 73 RT_FALL_THROUGH(); 74 case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_WRITE_FILE_DATA: 75 fAllowed = fHostToGuest; 76 break; 77 78 case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_CANCEL: 79 RT_FALL_THROUGH(); 80 case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_ERROR: 78 case VBOX_SHARED_CLIPBOARD_GUEST_FN_TRANSFER_REPORT: 79 RT_FALL_THROUGH(); 80 case VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG: 81 RT_FALL_THROUGH(); 82 case VBOX_SHARED_CLIPBOARD_GUEST_FN_CANCEL: 83 RT_FALL_THROUGH(); 84 case VBOX_SHARED_CLIPBOARD_GUEST_FN_ERROR: 81 85 fAllowed = fHostToGuest || fGuestToHost; 82 86 break; … … 90 94 } 91 95 92 int vboxSvcClipboardURIReportMsg(PVBOXCLIPBOARDCLIENTDATA pClientData, uint32_t uMsg, uint32_t u Formats)96 int vboxSvcClipboardURIReportMsg(PVBOXCLIPBOARDCLIENTDATA pClientData, uint32_t uMsg, uint32_t uParm) 93 97 { 94 98 AssertPtrReturn(pClientData, VERR_INVALID_POINTER); 95 99 96 RT_NOREF(uFormats);97 98 if (!vboxSvcClipboardURIMsgIsAllowed(vboxSvcClipboardGetMode(), uMsg))99 return VERR_ACCESS_DENIED;100 101 100 int rc = VINF_SUCCESS; 102 101 103 102 switch (uMsg) 104 103 { 105 case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_READ_DATA_HDR: 106 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_READ_DATA_HDR\n")); 107 break; 108 case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_WRITE_DATA_HDR: 109 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_WRITE_DATA_HDR\n")); 110 break; 111 case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_READ_DATA_CHUNK: 112 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_READ_DATA_CHUNK\n")); 113 break; 114 case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_WRITE_DATA_CHUNK: 115 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_WRITE_DATA_CHUNK\n")); 116 break; 117 case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_READ_DIR: 118 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_READ_DIR\n")); 119 break; 120 case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_WRITE_DIR: 121 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_WRITE_DIR\n")); 122 break; 123 case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_READ_FILE_HDR: 124 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_READ_FILE_HDR\n")); 125 break; 126 case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_WRITE_FILE_HDR: 127 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_WRITE_FILE_HDR\n")); 128 break; 129 case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_READ_FILE_DATA: 130 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_READ_FILE_DATA\n")); 131 break; 132 case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_WRITE_FILE_DATA: 133 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_WRITE_FILE_DATA\n")); 134 break; 135 case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_CANCEL: 136 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_CANCEL\n")); 137 break; 138 case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_ERROR: 139 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_ERROR\n")); 140 break; 104 case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_TRANSFER_START: 105 { 106 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_TRANSFER_START\n")); 107 108 if ( vboxSvcClipboardGetMode() != VBOX_SHARED_CLIPBOARD_MODE_HOST_TO_GUEST 109 && vboxSvcClipboardGetMode() != VBOX_SHARED_CLIPBOARD_MODE_BIDIRECTIONAL) 110 { 111 LogFlowFunc(("Wrong clipboard mode, skipping\n")); 112 break; 113 } 114 115 pClientData->State.URI.fTransferStart = true; 116 pClientData->State.URI.enmTransferDir = (SHAREDCLIPBOARDURITRANSFERDIR)uParm; 117 break; 118 119 } 141 120 142 121 default: … … 150 129 } 151 130 152 static bool s_fReqHdr = false;153 154 131 bool vboxSvcClipboardURIReturnMsg(PVBOXCLIPBOARDCLIENTDATA pClientData, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 155 132 { … … 158 135 bool fHandled = false; 159 136 160 /* For now we only support one transfer at a time. */ 161 PSHAREDCLIPBOARDURITRANSFER pTransfer = SharedClipboardURICtxGetTransfer(&pClientData->URI, 0 /* Index */); 162 if (!pTransfer) 163 return fHandled; 137 if ( pClientData->State.URI.fTransferStart 138 && cParms >= 2) 139 { 140 HGCMSvcSetU32(&paParms[0], VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_TRANSFER_START); 141 HGCMSvcSetU32(&paParms[1], pClientData->State.URI.enmTransferDir); 142 pClientData->State.URI.fTransferStart = false; 143 144 fHandled = true; 145 } 164 146 165 147 #if 1 … … 175 157 { 176 158 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_DATA_HDR\n")); 177 rc = VBoxSvcClipboardURIWrite DataHdr(cParms, paParms, pTransfer->State.pHeader);159 rc = VBoxSvcClipboardURIWriteListHdr(cParms, paParms, pTransfer->State.pHeader); 178 160 if (RT_SUCCESS(rc)) 179 161 { 180 162 /* We're done witht the data header, destroy it. */ 181 SharedClipboardURI DataHdrFree(pTransfer->State.pHeader);163 SharedClipboardURIListHdrFree(pTransfer->State.pHeader); 182 164 pTransfer->State.pHeader = NULL; 183 165 … … 198 180 Assert(cbRead <= cbBuf); 199 181 200 VBOXCLIPBOARD DATACHUNK dataChunk;201 RT_ZERO( dataChunk);202 dataChunk.pvData = pvBuf;203 dataChunk.cbData = cbRead;204 205 rc = VBoxSvcClipboardURIWrite DataChunk(cParms, paParms, &dataChunk);182 VBOXCLIPBOARDListEntry ListEntry; 183 RT_ZERO(ListEntry); 184 ListEntry.pvData = pvBuf; 185 ListEntry.cbData = cbRead; 186 187 rc = VBoxSvcClipboardURIWriteListEntry(cParms, paParms, &ListEntry); 206 188 } 207 189 … … 234 216 case SharedClipboardURIObject::Type_Directory: 235 217 { 236 rc = VBoxSvcClipboardURIWriteDir(cParms, paParms, & dataChunk);218 rc = VBoxSvcClipboardURIWriteDir(cParms, paParms, &ListEntry); 237 219 break; 238 220 } -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-win.cpp
r79366 r79497 49 49 #endif 50 50 51 /** Static window class name. */52 static char s_szClipWndClassName[] = VBOX_CLIPBOARD_WNDCLASS_NAME;53 54 51 55 52 /********************************************************************************************************************************* … … 69 66 VBOXCLIPBOARDWINCTX Win; 70 67 }; 71 72 /* Only one client is supported. There seems to be no need for more clients. */73 static VBOXCLIPBOARDCONTEXT g_ctx;74 68 75 69 … … 151 145 } 152 146 153 static LRESULT CALLBACK vboxClipboardSvcWinWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 154 { 147 static LRESULT CALLBACK vboxClipboardSvcWinWndProcMain(PVBOXCLIPBOARDCONTEXT pCtx, 148 HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 149 { 150 AssertPtr(pCtx); 151 155 152 LRESULT lresultRc = 0; 156 153 157 const PVBOXCLIPBOARDCONTEXT pCtx = &g_ctx; 158 const PVBOXCLIPBOARDWINCTX pWinCtx = &pCtx->Win; 159 160 switch (msg) 154 const PVBOXCLIPBOARDWINCTX pWinCtx = &pCtx->Win; 155 156 switch (uMsg) 161 157 { 162 158 case WM_CLIPBOARDUPDATE: … … 165 161 if (pWinCtx->hWndClipboardOwnerUs != hWndClipboardOwner) 166 162 { 167 LogFunc(("WM_CLIPBOARDUPDATE: hWnd OldClipboardOwner=%p, hWndNewClipboardOwner=%p\n",163 LogFunc(("WM_CLIPBOARDUPDATE: hWndClipboardOwnerUs=%p, hWndNewClipboardOwner=%p\n", 168 164 pWinCtx->hWndClipboardOwnerUs, hWndClipboardOwner)); 169 165 … … 179 175 { 180 176 LogFunc(("WM_CHANGECBCHAIN\n")); 181 lresultRc = VBoxClipboardWinHandleWMChangeCBChain(pWinCtx, h wnd, msg, wParam, lParam);177 lresultRc = VBoxClipboardWinHandleWMChangeCBChain(pWinCtx, hWnd, uMsg, wParam, lParam); 182 178 } break; 183 179 … … 186 182 LogFunc(("WM_DRAWCLIPBOARD\n")); 187 183 188 if (GetClipboardOwner() != h wnd)184 if (GetClipboardOwner() != hWnd) 189 185 { 190 186 /* Clipboard was updated by another application, retrieve formats and report back. */ … … 194 190 } 195 191 196 lresultRc = VBoxClipboardWinChainPassToNext(pWinCtx, msg, wParam, lParam);192 lresultRc = VBoxClipboardWinChainPassToNext(pWinCtx, uMsg, wParam, lParam); 197 193 198 194 } break; … … 226 222 int rc = vboxClipboardSvcWinRequestData(pCtx, fFormat, 30 * 1000 /* 30s timeout */); 227 223 228 LogF unc(("vboxClipboardReadDataFromClient rc = %Rrc, pv %p, cb %d, u32Format %d\n",229 rc, pCtx->pClientData->State.data.pv, pCtx->pClientData->State.data.cb,230 pCtx->pClientData->State.data.u32Format));224 LogFlowFunc(("rc=%Rrc, pv=%p, cb=%RU32, u32Format=%RU32\n", 225 rc, pCtx->pClientData->State.data.pv, pCtx->pClientData->State.data.cb, 226 pCtx->pClientData->State.data.u32Format)); 231 227 232 228 if ( RT_SUCCESS (rc) … … 237 233 HANDLE hMem = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, pCtx->pClientData->State.data.cb); 238 234 239 LogF unc(("hMem%p\n", hMem));235 LogFlowFunc(("hMem=%p\n", hMem)); 240 236 241 237 if (hMem) … … 243 239 void *pMem = GlobalLock(hMem); 244 240 245 LogF unc(("pMem %p, GlobalSize %d\n", pMem, GlobalSize(hMem)));241 LogFlowFunc(("pMem=%p, GlobalSize=%zu\n", pMem, GlobalSize(hMem))); 246 242 247 243 if (pMem) 248 244 { 249 LogF unc(("WM_RENDERFORMAT setting data\n"));245 LogFlowFunc(("WM_RENDERFORMAT: Setting data\n")); 250 246 251 247 if (pCtx->pClientData->State.data.pv) … … 268 264 HANDLE hClip = SetClipboardData(cfFormat, hMem); 269 265 270 LogF unc(("vboxClipboardHostEvent hClip%p\n", hClip));266 LogFlowFunc(("hClip=%p\n", hClip)); 271 267 272 268 if (hClip) … … 295 291 LogFunc(("WM_RENDERALLFORMATS\n")); 296 292 297 int rc = VBoxClipboardWinHandleWMRenderAllFormats(pWinCtx, h wnd);293 int rc = VBoxClipboardWinHandleWMRenderAllFormats(pWinCtx, hWnd); 298 294 AssertRC(rc); 299 295 } break; … … 309 305 * because host clipboard has more priority. 310 306 */ 311 LogFunc(("VBOX_CLIPBOARD_WM_SET_FORMATS ignored \n"));307 LogFunc(("VBOX_CLIPBOARD_WM_SET_FORMATS ignored; pClientData=%p\n", pCtx->pClientData)); 312 308 break; 313 309 } … … 317 313 if (fFormats != VBOX_SHARED_CLIPBOARD_FMT_NONE) /* Could arrive with some older GA versions. */ 318 314 { 319 int rc = VBoxClipboardWinOpen(h wnd);315 int rc = VBoxClipboardWinOpen(hWnd); 320 316 if (RT_SUCCESS(rc)) 321 317 { … … 369 365 370 366 default: 371 { 372 LogFunc(("WM_ %p\n", msg)); 373 lresultRc = DefWindowProc(hwnd, msg, wParam, lParam); 374 } 375 } 376 377 LogFunc(("WM_ rc %d\n", lresultRc)); 378 return lresultRc; 367 break; 368 } 369 370 LogFlowFunc(("hWnd=%p, WM_ %u\n", hWnd, uMsg)); 371 return DefWindowProc(hWnd, uMsg, wParam, lParam); 372 } 373 374 /** 375 * Static helper function for having a per-client proxy window instances. 376 */ 377 static LRESULT CALLBACK vboxClipboardSvcWinWndProcInstance(HWND hWnd, UINT uMsg, 378 WPARAM wParam, LPARAM lParam) 379 { 380 LONG_PTR pUserData = GetWindowLongPtr(hWnd, GWLP_USERDATA); 381 AssertPtrReturn(pUserData, 0); 382 383 PVBOXCLIPBOARDCONTEXT pCtx = reinterpret_cast<PVBOXCLIPBOARDCONTEXT>(pUserData); 384 if (pCtx) 385 return vboxClipboardSvcWinWndProcMain(pCtx, hWnd, uMsg, wParam, lParam); 386 387 return 0; 388 } 389 390 /** 391 * Static helper function for routing Windows messages to a specific 392 * proxy window instance. 393 */ 394 static LRESULT CALLBACK vboxClipboardSvcWinWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 395 { 396 /* Note: WM_NCCREATE is not the first ever message which arrives, but 397 * early enough for us. */ 398 if (uMsg == WM_NCCREATE) 399 { 400 LogFlowFunc(("WM_NCCREATE\n")); 401 402 LPCREATESTRUCT pCS = (LPCREATESTRUCT)lParam; 403 AssertPtr(pCS); 404 SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)pCS->lpCreateParams); 405 SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)vboxClipboardSvcWinWndProcInstance); 406 407 return vboxClipboardSvcWinWndProcInstance(hWnd, uMsg, wParam, lParam); 408 } 409 410 /* No window associated yet. */ 411 return DefWindowProc(hWnd, uMsg, wParam, lParam); 379 412 } 380 413 381 414 DECLCALLBACK(int) vboxClipboardSvcWinThread(RTTHREAD hThreadSelf, void *pvUser) 382 415 { 383 RT_NOREF(hThreadSelf, pvUser);384 385 /* Create a window and make it a clipboard viewer. */386 int rc = VINF_SUCCESS;387 388 416 LogFlowFuncEnter(); 389 417 390 const PVBOXCLIPBOARDCONTEXT pCtx = &g_ctx; 418 bool fThreadSignalled = false; 419 420 const PVBOXCLIPBOARDCONTEXT pCtx = (PVBOXCLIPBOARDCONTEXT)pvUser; 421 AssertPtr(pCtx); 391 422 const PVBOXCLIPBOARDWINCTX pWinCtx = &pCtx->Win; 392 423 … … 401 432 wc.hInstance = hInstance; 402 433 wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND + 1); 403 wc.lpszClassName = s_szClipWndClassName; 434 435 /* Register an unique wnd class name. */ 436 char szWndClassName[32]; 437 RTStrPrintf2(szWndClassName, sizeof(szWndClassName), 438 "%s-%RU64", VBOX_CLIPBOARD_WNDCLASS_NAME, RTThreadGetNative(hThreadSelf)); 439 wc.lpszClassName = szWndClassName; 440 441 int rc; 404 442 405 443 ATOM atomWindowClass = RegisterClass(&wc); 406 407 444 if (atomWindowClass == 0) 408 445 { … … 412 449 else 413 450 { 414 /* Create the window. */451 /* Create a window and make it a clipboard viewer. */ 415 452 pWinCtx->hWnd = CreateWindowEx(WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT | WS_EX_TOPMOST, 416 s _szClipWndClassName, s_szClipWndClassName,453 szWndClassName, szWndClassName, 417 454 WS_POPUPWINDOW, 418 -200, -200, 100, 100, NULL, NULL, hInstance, NULL);455 -200, -200, 100, 100, NULL, NULL, hInstance, pCtx /* lpParam */); 419 456 if (pWinCtx->hWnd == NULL) 420 457 { … … 447 484 } 448 485 #endif 486 487 int rc2 = RTThreadUserSignal(hThreadSelf); 488 AssertRC(rc2); 489 490 fThreadSignalled = true; 491 449 492 MSG msg; 450 493 BOOL msgret = 0; … … 454 497 DispatchMessage(&msg); 455 498 } 499 456 500 /* 457 * Window procedure can return error, 458 * but this is exceptional situation 459 * that should be identified in testing 460 */ 501 * Window procedure can return error, * but this is exceptional situation that should be 502 * identified in testing. 503 */ 461 504 Assert(msgret >= 0); 462 505 LogFunc(("Message loop finished. GetMessage returned %d, message id: %d \n", msgret, msg.message)); … … 473 516 if (atomWindowClass != 0) 474 517 { 475 UnregisterClass(s _szClipWndClassName, hInstance);518 UnregisterClass(szWndClassName, hInstance); 476 519 atomWindowClass = 0; 520 } 521 522 if (!fThreadSignalled) 523 { 524 int rc2 = RTThreadUserSignal(hThreadSelf); 525 AssertRC(rc2); 477 526 } 478 527 … … 498 547 if (pCtx->pClientData) 499 548 { 500 uint32_t uFormats;549 VBOXCLIPBOARDFORMATS uFormats = VBOX_SHARED_CLIPBOARD_FMT_NONE; 501 550 rc = VBoxClipboardWinGetFormats(&pCtx->Win, &uFormats); 502 if (RT_SUCCESS(rc)) 551 if ( RT_SUCCESS(rc) 552 && uFormats != VBOX_SHARED_CLIPBOARD_FMT_NONE 553 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 554 /* For URI handling we don't need to sync the format. */ 555 && !(uFormats & VBOX_SHARED_CLIPBOARD_FMT_URI_LIST) 556 #endif 557 ) 558 { 503 559 vboxSvcClipboardReportMsg(pCtx->pClientData, VBOX_SHARED_CLIPBOARD_HOST_MSG_REPORT_FORMATS, uFormats); 560 } 504 561 } 505 562 else /* If we don't have any client data (yet), bail out. */ … … 516 573 int VBoxClipboardSvcImplInit(void) 517 574 { 518 RT_ZERO(g_ctx); /* Be careful not messing up non-POD types! */ 519 520 /* Check that new Clipboard API is available. */ 521 VBoxClipboardWinCheckAndInitNewAPI(&g_ctx.Win.newAPI); 522 523 int rc = RTSemEventCreate(&g_ctx.hRenderEvent); 524 if (RT_SUCCESS(rc)) 525 { 526 rc = RTThreadCreate(&g_ctx.hThread, vboxClipboardSvcWinThread, NULL, _64K /* Stack size */, 527 RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "SHCLIP"); 528 } 529 530 if (RT_FAILURE(rc)) 531 RTSemEventDestroy(g_ctx.hRenderEvent); 575 /* Initialization is done in VBoxClipboardSvcImplConnect(). */ 576 return VINF_SUCCESS; 577 } 578 579 void VBoxClipboardSvcImplDestroy(void) 580 { 581 /* Destruction is done in VBoxClipboardSvcImplDisconnect(). */ 582 } 583 584 int VBoxClipboardSvcImplConnect(PVBOXCLIPBOARDCLIENTDATA pClientData, bool fHeadless) 585 { 586 RT_NOREF(fHeadless); 587 588 AssertPtrReturn(pClientData, VERR_INVALID_POINTER); 589 590 LogFlowFuncEnter(); 591 592 int rc; 593 594 PVBOXCLIPBOARDCONTEXT pCtx = (PVBOXCLIPBOARDCONTEXT)RTMemAllocZ(sizeof(VBOXCLIPBOARDCONTEXT)); 595 if (pCtx) 596 { 597 /* Check that new Clipboard API is available. */ 598 rc = VBoxClipboardWinCheckAndInitNewAPI(&pCtx->Win.newAPI); 599 if (RT_SUCCESS(rc)) 600 { 601 rc = RTSemEventCreate(&pCtx->hRenderEvent); 602 if (RT_SUCCESS(rc)) 603 { 604 rc = RTThreadCreate(&pCtx->hThread, vboxClipboardSvcWinThread, pCtx /* pvUser */, _64K /* Stack size */, 605 RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "SHCLIP"); 606 if (RT_SUCCESS(rc)) 607 { 608 int rc2 = RTThreadUserWait(pCtx->hThread, 30 * 1000 /* Timeout in ms */); 609 AssertRC(rc2); 610 } 611 } 612 613 if (RT_FAILURE(rc)) 614 RTSemEventDestroy(pCtx->hRenderEvent); 615 } 616 617 pClientData->State.pCtx = pCtx; 618 pClientData->State.pCtx->pClientData = pClientData; 619 620 /* Sync the host clipboard content with the client. */ 621 rc = VBoxClipboardSvcImplSync(pClientData); 622 } 623 else 624 rc = VERR_NO_MEMORY; 532 625 533 626 LogFlowFuncLeaveRC(rc); … … 535 628 } 536 629 537 void VBoxClipboardSvcImplDestroy(void)538 {539 LogFlowFuncEnter();540 541 if (g_ctx.Win.hWnd)542 {543 PostMessage(g_ctx.Win.hWnd, WM_CLOSE, 0, 0);544 }545 546 int rc = RTSemEventDestroy(g_ctx.hRenderEvent);547 AssertRC(rc);548 549 /* Wait for the window thread to terminate. */550 rc = RTThreadWait(g_ctx.hThread, 30 * 1000 /* Timeout in ms */, NULL);551 if (RT_FAILURE(rc))552 LogRel(("Shared Clipboard: Waiting for window thread termination failed with rc=%Rrc\n", rc));553 554 g_ctx.hThread = NIL_RTTHREAD;555 }556 557 int VBoxClipboardSvcImplConnect(PVBOXCLIPBOARDCLIENTDATA pClientData, bool fHeadless)558 {559 RT_NOREF(fHeadless);560 561 LogFlowFuncEnter();562 563 if (g_ctx.pClientData != NULL)564 {565 /* One client only. */566 return VERR_NOT_SUPPORTED;567 }568 569 pClientData->State.pCtx = &g_ctx;570 571 pClientData->State.pCtx->pClientData = pClientData;572 573 /* Sync the host clipboard content with the client. */574 VBoxClipboardSvcImplSync(pClientData);575 576 return VINF_SUCCESS;577 }578 579 630 int VBoxClipboardSvcImplSync(PVBOXCLIPBOARDCLIENTDATA pClientData) 580 631 { … … 585 636 int VBoxClipboardSvcImplDisconnect(PVBOXCLIPBOARDCLIENTDATA pClientData) 586 637 { 587 RT_NOREF(pClientData);638 AssertPtrReturn(pClientData, VERR_INVALID_POINTER); 588 639 589 640 LogFlowFuncEnter(); 590 641 591 g_ctx.pClientData = NULL; 592 593 return VINF_SUCCESS; 642 int rc = VINF_SUCCESS; 643 644 PVBOXCLIPBOARDCONTEXT pCtx = pClientData->State.pCtx; 645 if (pCtx) 646 { 647 if (pCtx->Win.hWnd) 648 PostMessage(pCtx->Win.hWnd, WM_CLOSE, 0 /* wParam */, 0 /* lParam */); 649 650 rc = RTSemEventDestroy(pCtx->hRenderEvent); 651 if (RT_SUCCESS(rc)) 652 { 653 if (pCtx->hThread != NIL_RTTHREAD) 654 { 655 LogFunc(("Waiting for thread to terminate ...\n")); 656 657 /* Wait for the window thread to terminate. */ 658 rc = RTThreadWait(pCtx->hThread, 30 * 1000 /* Timeout in ms */, NULL); 659 if (RT_FAILURE(rc)) 660 LogRel(("Shared Clipboard: Waiting for window thread termination failed with rc=%Rrc\n", rc)); 661 662 pCtx->hThread = NIL_RTTHREAD; 663 } 664 } 665 666 if (RT_SUCCESS(rc)) 667 { 668 RTMemFree(pCtx); 669 pCtx = NULL; 670 671 pClientData->State.pCtx = NULL; 672 } 673 } 674 675 LogFlowFuncLeaveRC(rc); 676 return rc; 594 677 } 595 678 … … 597 680 { 598 681 AssertPtrReturn(pClientData, VERR_INVALID_POINTER); 599 AssertPtrReturn(pClientData->State.pCtx, VERR_INVALID_POINTER); 682 683 PVBOXCLIPBOARDCONTEXT pCtx = pClientData->State.pCtx; 684 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 685 686 LogFlowFunc(("u32Formats=0x%x, hWnd=%p\n", u32Formats, pCtx->Win.hWnd)); 600 687 601 688 /* 602 * The guest announce sformats. Forward to the window thread.689 * The guest announced formats. Forward to the window thread. 603 690 */ 604 PostMessage(pClientData->State.pCtx->Win.hWnd, VBOX_CLIPBOARD_WM_SET_FORMATS, 0, u32Formats); 691 PostMessage(pCtx->Win.hWnd, VBOX_CLIPBOARD_WM_SET_FORMATS, 692 0 /* wParam */, u32Formats /* lParam */); 605 693 606 694 return VINF_SUCCESS; … … 770 858 771 859 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 772 void VBoxClipboardSvcImplURIOnDataHeaderComplete(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData) 773 { 860 int VBoxClipboardSvcImplURITransferCreate(PVBOXCLIPBOARDCLIENTDATA pClientData, PSHAREDCLIPBOARDURITRANSFER pTransfer) 861 { 862 RT_NOREF(pClientData, pTransfer); 863 774 864 LogFlowFuncEnter(); 775 865 776 AssertPtrReturnVoid(pData); 777 778 PSHAREDCLIPBOARDURITRANSFER pTransfer = pData->pTransfer; 779 AssertPtrReturnVoid(pTransfer); 780 781 SharedClipboardWinURITransferCtx *pTransferCtx = (SharedClipboardWinURITransferCtx *)pTransfer->pvUser; 782 AssertPtrReturnVoid(pTransferCtx); 783 784 /* Notify the Windows implementation's data object that the meta data has been read successfully. */ 785 if (pTransferCtx->pDataObj) 786 pTransferCtx->pDataObj->OnMetaDataComplete(pTransfer); 787 } 788 789 int VBoxClipboardSvcImplURITransferCreate(PVBOXCLIPBOARDCLIENTDATA pClientData, PSHAREDCLIPBOARDURITRANSFER pTransfer) 790 { 791 RT_NOREF(pClientData, pTransfer); 792 866 return VINF_SUCCESS; 867 } 868 869 int VBoxClipboardSvcImplURITransferDestroy(PVBOXCLIPBOARDCLIENTDATA pClientData, PSHAREDCLIPBOARDURITRANSFER pTransfer) 870 { 793 871 LogFlowFuncEnter(); 794 872 873 VBoxClipboardWinURITransferDestroy(&pClientData->State.pCtx->Win, pTransfer); 874 795 875 return VINF_SUCCESS; 796 876 } 797 798 int VBoxClipboardSvcImplURITransferDestroy(PVBOXCLIPBOARDCLIENTDATA pClientData, PSHAREDCLIPBOARDURITRANSFER pTransfer)799 {800 LogFlowFuncEnter();801 802 VBoxClipboardWinURITransferDestroy(&pClientData->State.pCtx->Win, pTransfer);803 804 return VINF_SUCCESS;805 }806 877 #endif /* VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */ 807 878 -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc.cpp
r79366 r79497 136 136 #include <VBox/log.h> 137 137 138 #include <VBox/HostServices/Service.h> 138 139 #include <VBox/HostServices/VBoxClipboardSvc.h> 139 140 #include <VBox/HostServices/VBoxClipboardExt.h> … … 151 152 # include "VBoxSharedClipboardSvc-uri.h" 152 153 #endif 154 155 using namespace HGCM; 153 156 154 157 … … 172 175 void *g_pvExtension; 173 176 174 static PVBOXCLIPBOARDCLIENTDATA g_pClientData;175 176 177 /* Serialization of data reading and format announcements from the RDP client. */ 177 178 static bool g_fReadingData = false; … … 181 182 /** Is the clipboard running in headless mode? */ 182 183 static bool g_fHeadless = false; 184 185 /** Map of all connected clients. */ 186 ClipboardClientMap g_mapClients; 187 188 /** List of all clients which are queued up (deferred return) and ready 189 * to process new commands. The key is the (unique) client ID. */ 190 ClipboardClientQueue g_listClientsDeferred; 183 191 184 192 … … 252 260 int rc2 = RTCritSectLeave(&g_CritSect); 253 261 AssertRC(rc2); 262 } 263 264 /** 265 * Resets a client's state message queue. 266 * 267 * @param pState Pointer to the client's state structure to reset message queue for. 268 */ 269 void vboxSvcClipboardMsgQueueReset(PVBOXCLIPBOARDCLIENTSTATE pState) 270 { 271 LogFlowFuncEnter(); 272 273 while (!pState->queueMsg.isEmpty()) 274 { 275 RTMemFree(pState->queueMsg.last()); 276 pState->queueMsg.removeLast(); 277 } 278 } 279 280 /** 281 * Allocates a new clipboard message. 282 * 283 * @returns Allocated clipboard message, or NULL on failure. 284 * @param uMsg Message type of message to allocate. 285 * @param cParms Number of HGCM parameters to allocate. 286 */ 287 PVBOXCLIPBOARDCLIENTMSG vboxSvcClipboardMsgAlloc(uint32_t uMsg, uint32_t cParms) 288 { 289 PVBOXCLIPBOARDCLIENTMSG pMsg = (PVBOXCLIPBOARDCLIENTMSG)RTMemAlloc(sizeof(VBOXCLIPBOARDCLIENTMSG)); 290 if (pMsg) 291 { 292 pMsg->m_paParms = (PVBOXHGCMSVCPARM)RTMemAllocZ(sizeof(VBOXHGCMSVCPARM) * cParms); 293 if (pMsg->m_paParms) 294 { 295 pMsg->m_cParms = cParms; 296 pMsg->m_uMsg = uMsg; 297 298 return pMsg; 299 } 300 } 301 302 RTMemFree(pMsg); 303 return NULL; 304 } 305 306 /** 307 * Frees a formerly allocated clipboard message. 308 * 309 * @param pMsg Clipboard message to free. 310 * The pointer will be invalid after calling this function. 311 */ 312 void vboxSvcClipboardMsgFree(PVBOXCLIPBOARDCLIENTMSG pMsg) 313 { 314 if (!pMsg) 315 return; 316 317 if (pMsg->m_paParms) 318 RTMemFree(pMsg->m_paParms); 319 320 RTMemFree(pMsg); 321 pMsg = NULL; 322 } 323 324 /** 325 * Adds a new message to a client'S message queue. 326 * 327 * @returns IPRT status code. 328 * @param pState Pointer to the client's state structure to add new message to. 329 * @param pMsg Pointer to message to add. The queue then owns the pointer. 330 * @param fAppend Whether to append or prepend the message to the queue. 331 */ 332 int vboxSvcClipboardMsgAdd(PVBOXCLIPBOARDCLIENTSTATE pState, PVBOXCLIPBOARDCLIENTMSG pMsg, bool fAppend) 333 { 334 AssertPtrReturn(pMsg, VERR_INVALID_POINTER); 335 336 LogFlowFunc(("uMsg=%RU32, cParms=%RU32, fAppend=%RTbool\n", pMsg->m_uMsg, pMsg->m_cParms, fAppend)); 337 338 if (fAppend) 339 pState->queueMsg.append(pMsg); 340 else 341 pState->queueMsg.prepend(pMsg); 342 343 /** @todo Catch / handle OOM? */ 344 345 return VINF_SUCCESS; 346 } 347 348 /** 349 * Retrieves information about the next message in the queue. 350 * 351 * @returns IPRT status code. VERR_NO_DATA if no next message is available. 352 * @param pState Pointer to the client's state structure to get message info for. 353 * @param puType Where to store the message type. 354 * @param pcParms Where to store the message parameter count. 355 */ 356 int vboxSvcClipboardMsgGetNextInfo(PVBOXCLIPBOARDCLIENTSTATE pState, uint32_t *puType, uint32_t *pcParms) 357 { 358 AssertPtrReturn(puType, VERR_INVALID_POINTER); 359 AssertPtrReturn(pcParms, VERR_INVALID_POINTER); 360 361 int rc; 362 363 if (pState->queueMsg.isEmpty()) 364 { 365 rc = VERR_NO_DATA; 366 } 367 else 368 { 369 PVBOXCLIPBOARDCLIENTMSG pMsg = pState->queueMsg.first(); 370 AssertPtr(pMsg); 371 372 *puType = pMsg->m_uMsg; 373 *pcParms = pMsg->m_cParms; 374 375 rc = VINF_SUCCESS; 376 } 377 378 LogFlowFunc(("Returning puMsg=%RU32, pcParms=%RU32, rc=%Rrc\n", *puType, *pcParms, rc)); 379 return rc; 380 } 381 382 /** 383 * Retrieves the next queued up message and removes it from the queue on success. 384 * Will return VERR_NO_DATA if no next message is available. 385 * 386 * @returns IPRT status code. 387 * @param pState Pointer to the client's state structure to get message for. 388 * @param uMsg Message type to retrieve. 389 * @param cParms Number of parameters the \@a paParms array can store. 390 * @param paParms Where to store the message parameters. 391 */ 392 int vboxSvcClipboardMsgGetNext(PVBOXCLIPBOARDCLIENTSTATE pState, 393 uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 394 { 395 LogFlowFunc(("uMsg=%RU32, cParms=%RU32\n", uMsg, cParms)); 396 397 /* Check for pending messages in our queue. */ 398 if (pState->queueMsg.isEmpty()) 399 return VERR_NO_DATA; 400 401 /* Get the current message. */ 402 PVBOXCLIPBOARDCLIENTMSG pMsg = pState->queueMsg.first(); 403 AssertPtr(pMsg); 404 405 int rc = VINF_SUCCESS; 406 407 /* Fetch the current message info. */ 408 if (pMsg->m_uMsg != uMsg) 409 { 410 LogFunc(("Stored message type (%RU32) does not match request (%RU32)\n", pMsg->m_uMsg, uMsg)); 411 rc = VERR_INVALID_PARAMETER; 412 } 413 else if (pMsg->m_cParms > cParms) 414 { 415 LogFunc(("Stored parameter count (%RU32) exceeds request buffer (%RU32)\n", pMsg->m_cParms, cParms)); 416 rc = VERR_INVALID_PARAMETER; 417 } 418 419 if (RT_SUCCESS(rc)) 420 { 421 rc = Message::CopyParms(paParms, cParms, pMsg->m_paParms, pMsg->m_cParms, true /* fDeepCopy */); 422 423 /** @todo Only remove on success? */ 424 pState->queueMsg.removeFirst(); /* Remove the current message from the queue. */ 425 } 426 else 427 { 428 vboxSvcClipboardMsgQueueReset(pState); 429 /** @todo Cleanup, send notification to guest. */ 430 } 431 432 LogFlowFunc(("Message processed with rc=%Rrc\n", rc)); 433 return rc; 254 434 } 255 435 … … 469 649 static DECLCALLBACK(int) svcUnload(void *) 470 650 { 651 LogFlowFuncEnter(); 652 471 653 VBoxClipboardSvcImplDestroy(); 654 655 ClipboardClientMap::iterator itClient = g_mapClients.begin(); 656 while (itClient != g_mapClients.end()) 657 { 658 RTMemFree(itClient->second); 659 g_mapClients.erase(itClient); 660 661 itClient = g_mapClients.begin(); 662 } 663 472 664 RTCritSectDelete(&g_CritSect); 665 473 666 return VINF_SUCCESS; 474 667 } … … 482 675 RT_NOREF(u32ClientID); 483 676 484 PVBOXCLIPBOARDCLIENTDATA pClientData = (PVBOXCLIPBOARDCLIENTDATA)pvClient;485 486 677 LogFunc(("u32ClientID=%RU32\n", u32ClientID)); 678 679 ClipboardClientMap::iterator itClient = g_mapClients.find(u32ClientID); 680 if (itClient == g_mapClients.end()) 681 { 682 AssertFailed(); /* Should never happen. */ 683 return VERR_NOT_FOUND; 684 } 685 686 PVBOXCLIPBOARDCLIENT pClient = itClient->second; 687 AssertPtr(pClient); 688 PVBOXCLIPBOARDCLIENTDATA pClientData = pClient->pData; 689 AssertPtr(pClientData); 690 691 /* Sanity. */ 692 Assert(pClientData == (PVBOXCLIPBOARDCLIENTDATA)pvClient); 487 693 488 694 vboxSvcClipboardReportMsg(pClientData, VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT, 0); /** @todo r=andy Why is this necessary? The client already disconnected ... */ … … 503 709 vboxSvcClipboardClientStateDestroy(&pClientData->State); 504 710 505 g_pClientData = NULL; 711 RTMemFree(itClient->second); 712 g_mapClients.erase(itClient); 506 713 507 714 return VINF_SUCCESS; … … 512 719 RT_NOREF(fRequestor, fRestoring); 513 720 514 PVBOXCLIPBOARDCLIENTDATA pClientData = (PVBOXCLIPBOARDCLIENTDATA)pvClient;515 516 721 LogFlowFunc(("u32ClientID=%RU32\n", u32ClientID)); 517 722 518 /* If there is already a client connected then we want to release it first. */ 519 if (g_pClientData != NULL) 520 { 521 uint32_t uOldClientID = g_pClientData->State.u32ClientID; 522 if (uOldClientID) 523 { 524 svcDisconnect(NULL, uOldClientID, g_pClientData); 525 526 /* And free the resources in the HGCM subsystem. */ 527 g_pHelpers->pfnDisconnectClient(g_pHelpers->pvInstance, uOldClientID); 723 int rc = VINF_SUCCESS; 724 725 if (g_mapClients.find(u32ClientID) != g_mapClients.end()) 726 { 727 rc = VERR_ALREADY_EXISTS; 728 AssertFailed(); /* Should never happen. */ 729 } 730 731 if (RT_SUCCESS(rc)) 732 { 733 PVBOXCLIPBOARDCLIENT pClient = (PVBOXCLIPBOARDCLIENT)RTMemAllocZ(sizeof(VBOXCLIPBOARDCLIENT)); 734 if (RT_SUCCESS(rc)) 735 { 736 pClient->uClientID = u32ClientID; 737 pClient->pData = (PVBOXCLIPBOARDCLIENTDATA)pvClient; 738 739 /* Reset the client state. */ 740 vboxSvcClipboardClientStateReset(&pClient->pData->State); 741 742 /* (Re-)initialize the client state. */ 743 vboxSvcClipboardClientStateInit(&pClient->pData->State, u32ClientID); 744 745 rc = VBoxClipboardSvcImplConnect(pClient->pData, VBoxSvcClipboardGetHeadless()); 746 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 747 if (RT_SUCCESS(rc)) 748 rc = SharedClipboardURICtxInit(&pClient->pData->URI); 749 #endif 750 g_mapClients[u32ClientID] = pClient; /** @todo Can this throw? */ 528 751 } 529 }530 531 /* Reset the client state. */532 vboxSvcClipboardClientStateReset(&pClientData->State);533 534 /* (Re-)initialize the client state. */535 vboxSvcClipboardClientStateInit(&pClientData->State, u32ClientID);536 537 int rc = VBoxClipboardSvcImplConnect(pClientData, VBoxSvcClipboardGetHeadless());538 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST539 if (RT_SUCCESS(rc))540 rc = SharedClipboardURICtxInit(&pClientData->URI);541 #endif542 543 if (RT_SUCCESS(rc))544 {545 g_pClientData = pClientData;546 752 } 547 753 … … 559 765 uint64_t tsArrival) 560 766 { 561 RT_NOREF(u32ClientID, tsArrival);767 RT_NOREF(u32ClientID, pvClient, tsArrival); 562 768 563 769 int rc = VINF_SUCCESS; … … 566 772 u32ClientID, u32Function, cParms, paParms)); 567 773 568 PVBOXCLIPBOARDCLIENTDATA pClientData = (PVBOXCLIPBOARDCLIENTDATA)pvClient; 774 ClipboardClientMap::iterator itClient = g_mapClients.find(u32ClientID); 775 if (itClient == g_mapClients.end()) 776 { 777 AssertFailed(); /* Should never happen. */ 778 return; 779 } 780 781 PVBOXCLIPBOARDCLIENT pClient = itClient->second; 782 AssertPtr(pClient); 783 PVBOXCLIPBOARDCLIENTDATA pClientData = pClient->pData; 784 AssertPtr(pClientData); 569 785 570 786 #ifdef DEBUG … … 578 794 #endif 579 795 580 bool f AsynchronousProcessing= false;796 bool fDefer = false; 581 797 582 798 switch (u32Function) 583 799 { 584 case VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG :800 case VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD: 585 801 { 586 802 /* The quest requests a host message. */ 587 LogFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG \n"));588 589 if (cParms != VBOX_SHARED_CLIPBOARD_CPARMS_GET_HOST_MSG )803 LogFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD\n")); 804 805 if (cParms != VBOX_SHARED_CLIPBOARD_CPARMS_GET_HOST_MSG_OLD) 590 806 { 591 807 rc = VERR_INVALID_PARAMETER; … … 610 826 { 611 827 /* No event available at the time. Process asynchronously. */ 612 f AsynchronousProcessing= true;828 fDefer = true; 613 829 614 830 pClientData->State.fAsync = true; … … 655 871 rc = vboxSvcClipboardSetSource(pClientData, SHAREDCLIPBOARDSOURCE_REMOTE); 656 872 657 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 873 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST_DISABLED 658 874 if ( RT_SUCCESS(rc) 659 875 && (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_URI_LIST)) … … 677 893 678 894 RT_ZERO(creationCtx.Interface); 679 creationCtx.Interface.pfnReadDataHdr = VBoxSvcClipboardProviderImplURIReadDataHdr; 680 creationCtx.Interface.pfnReadDataChunk = VBoxSvcClipboardProviderImplURIReadDataChunk; 681 creationCtx.Interface.pfnReadDirectory = VBoxSvcClipboardProviderImplURIReadDir; 682 creationCtx.Interface.pfnReadFileHdr = VBoxSvcClipboardProviderImplURIReadFileHdr; 683 creationCtx.Interface.pfnReadFileData = VBoxSvcClipboardProviderImplURIReadFileData; 684 685 creationCtx.pvUser = pClientData; 895 RT_ZERO(creationCtx.Interface); 896 creationCtx.Interface.pfnTransferOpen = vboxSvcClipboardURITransferOpen; 897 creationCtx.Interface.pfnTransferClose = vboxSvcClipboardURITransferClose; 898 creationCtx.Interface.pfnListOpen = vboxSvcClipboardURIListOpen; 899 creationCtx.Interface.pfnListClose = vboxSvcClipboardURIListClose; 900 creationCtx.Interface.pfnListHdrRead = vboxSvcClipboardURIListHdrRead; 901 creationCtx.Interface.pfnListEntryRead = vboxSvcClipboardURIListEntryRead; 902 creationCtx.Interface.pfnObjOpen = vboxSvcClipboardURIObjOpen; 903 creationCtx.Interface.pfnObjClose = vboxSvcClipboardURIObjClose; 904 creationCtx.Interface.pfnObjRead = vboxSvcClipboardURIObjRead; 905 906 creationCtx.pvUser = pClient; 686 907 687 908 /* Register needed callbacks so that we can wait for the meta data to arrive here. */ … … 692 913 693 914 Callbacks.pfnTransferPrepare = VBoxSvcClipboardURITransferPrepareCallback; 694 Callbacks.pfnDataHeaderComplete = VBoxSvcClipboardURIDataHeaderCompleteCallback;695 Callbacks.pfnDataComplete = VBoxSvcClipboardURIDataCompleteCallback;696 915 Callbacks.pfnTransferComplete = VBoxSvcClipboardURITransferCompleteCallback; 697 916 Callbacks.pfnTransferCanceled = VBoxSvcClipboardURITransferCanceledCallback; … … 728 947 if (RT_SUCCESS(rc)) 729 948 { 730 if ( g_pfnExtension)949 if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_URI_LIST) 731 950 { 732 VBOXCLIPBOARDEXTPARMS parms; 733 RT_ZERO(parms); 734 parms.u32Format = u32Formats; 735 736 g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_FORMAT_ANNOUNCE, &parms, sizeof (parms)); 951 /* Tell the guest that we want to start a (reading) transfer. */ 952 rc = vboxSvcClipboardReportMsg(pClientData, VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_TRANSFER_START, 953 0 /* u32Formats == 0 means reading data */); 954 955 /* Note: Announcing the actual format will be done in the 956 host service URI handler (vboxSvcClipboardURIHandler). */ 737 957 } 738 739 rc = VBoxClipboardSvcImplFormatAnnounce(pClientData, u32Formats); 958 else /* Announce simple formats to the OS-specific service implemenation. */ 959 { 960 if (g_pfnExtension) 961 { 962 VBOXCLIPBOARDEXTPARMS parms; 963 RT_ZERO(parms); 964 parms.u32Format = u32Formats; 965 966 g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_FORMAT_ANNOUNCE, &parms, sizeof (parms)); 967 } 968 969 rc = VBoxClipboardSvcImplFormatAnnounce(pClientData, u32Formats); 970 } 740 971 } 741 972 } … … 797 1028 RT_ZERO(creationCtx.Interface); 798 1029 799 creationCtx.Interface.pfnWriteDataHdr = VBoxSvcClipboardProviderImplURIWriteDataHdr; 800 creationCtx.Interface.pfnWriteDataChunk = VBoxSvcClipboardProviderImplURIWriteDataChunk; 801 creationCtx.Interface.pfnWriteDirectory = VBoxSvcClipboardProviderImplURIWriteDir; 802 creationCtx.Interface.pfnWriteFileHdr = VBoxSvcClipboardProviderImplURIWriteFileHdr; 803 creationCtx.Interface.pfnWriteFileData = VBoxSvcClipboardProviderImplURIWriteFileData; 1030 creationCtx.Interface.pfnListHdrWrite = vboxSvcClipboardURIListHdrWrite; 1031 creationCtx.Interface.pfnListEntryWrite = vboxSvcClipboardURIListEntryWrite; 1032 creationCtx.Interface.pfnObjWrite = vboxSvcClipboardURIObjWrite; 804 1033 805 1034 creationCtx.pvUser = pClientData; … … 853 1082 if (g_fDelayedAnnouncement) 854 1083 { 855 vboxSvcClipboardReportMsg( g_pClientData, VBOX_SHARED_CLIPBOARD_HOST_MSG_REPORT_FORMATS, g_u32DelayedFormats);1084 vboxSvcClipboardReportMsg(pClientData, VBOX_SHARED_CLIPBOARD_HOST_MSG_REPORT_FORMATS, g_u32DelayedFormats); 856 1085 g_fDelayedAnnouncement = false; 857 1086 g_u32DelayedFormats = 0; … … 883 1112 pClientData->State.asyncRead.paParms = paParms; 884 1113 pClientData->State.fReadPending = true; 885 f AsynchronousProcessing= true;1114 fDefer = true; 886 1115 VBoxSvcClipboardUnlock(); 887 1116 } … … 956 1185 { 957 1186 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 958 rc = vboxSvcClipboardURIHandler(u32ClientID, pvClient, u32Function, cParms, paParms, tsArrival, 959 &fAsynchronousProcessing); 1187 rc = vboxSvcClipboardURIHandler(pClient, callHandle, u32Function, cParms, paParms, tsArrival); 1188 if (RT_SUCCESS(rc)) 1189 { 1190 /* The URI handler does deferring on its own. */ 1191 fDefer = true; 1192 } 960 1193 #else 961 1194 rc = VERR_NOT_IMPLEMENTED; … … 964 1197 } 965 1198 966 LogFlowFunc((" fAsynchronousProcessing=%RTbool\n", fAsynchronousProcessing));967 968 if (!f AsynchronousProcessing)1199 LogFlowFunc(("u32ClientID=%RU32, fDefer=%RTbool\n", pClient->uClientID, fDefer)); 1200 1201 if (!fDefer) 969 1202 g_pHelpers->pfnCallComplete(callHandle, rc); 970 1203 … … 998 1231 999 1232 /** 1233 * Defers a client from returning back to the caller (guest side). 1234 * 1235 * @returns VBox status code. 1236 * @param pClient Client to defer. 1237 * @param hHandle The call handle to defer. 1238 * @param u32Function Function ID to save. 1239 * @param cParms Number of parameters to save. 1240 * @param paParms Parameter arrray to save. 1241 */ 1242 int vboxSvcClipboardClientDefer(PVBOXCLIPBOARDCLIENT pClient, 1243 VBOXHGCMCALLHANDLE hHandle, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 1244 { 1245 LogFlowFunc(("uClient=%RU32\n", pClient->uClientID)); 1246 1247 AssertMsgReturn(pClient->fDeferred == false, ("Client already in deferred mode\n"), 1248 VERR_WRONG_ORDER); 1249 1250 pClient->fDeferred = true; 1251 1252 pClient->Deferred.hHandle = hHandle; 1253 pClient->Deferred.uType = u32Function; 1254 pClient->Deferred.cParms = cParms; 1255 pClient->Deferred.paParms = paParms; 1256 1257 return false; 1258 } 1259 1260 /** 1261 * Completes a call of a client, which in turn will return the result to the caller on 1262 * the guest side. 1263 * 1264 * @returns VBox status code. 1265 * @param pClient Client to complete. 1266 * @param hHandle Call handle to complete. 1267 * @param rc Return code to set for the client. 1268 */ 1269 int vboxSvcClipboardClientComplete(PVBOXCLIPBOARDCLIENT pClient, VBOXHGCMCALLHANDLE hHandle, int rc) 1270 { 1271 RT_NOREF(pClient); 1272 1273 LogFlowFunc(("uClient=%RU32, rc=%Rrc\n", pClient->uClientID, rc)); 1274 1275 g_pHelpers->pfnCallComplete(hHandle, rc); 1276 1277 return VINF_SUCCESS; 1278 } 1279 1280 /** 1281 * Completes a deferred client. 1282 * 1283 * @returns VBox status code. 1284 * @param pClient Client to complete. 1285 * @param rcComplete Return code to set for the client. 1286 */ 1287 int vboxSvcClipboardClientDeferredComplete(PVBOXCLIPBOARDCLIENT pClient, int rcComplete) 1288 { 1289 LogFlowFunc(("uClient=%RU32, fDeferred=%RTbool\n", pClient->uClientID, pClient->fDeferred)); 1290 1291 int rc = VINF_SUCCESS; 1292 1293 if (pClient->fDeferred) /* Not deferred? Bail out early. */ 1294 { 1295 LogFlowFunc(("Completing call\n")); 1296 1297 rc = vboxSvcClipboardClientComplete(pClient, pClient->Deferred.hHandle, rcComplete); 1298 1299 pClient->fDeferred = false; 1300 RT_ZERO(pClient->Deferred); 1301 } 1302 1303 return rc; 1304 } 1305 1306 /** 1307 * Sets a deferred client's next message info -- when returning to the client, it then 1308 * can retrieve the actual message sent by the host. 1309 * 1310 * @returns VBox status code. 1311 * @param pClient Client to set the next message information for. 1312 * @param uMsg Message ID to set. 1313 * @param cParms Number of parameters of message required. 1314 */ 1315 int vboxSvcClipboardClientDeferredSetMsgInfo(PVBOXCLIPBOARDCLIENT pClient, uint32_t uMsg, uint32_t cParms) 1316 { 1317 int rc; 1318 1319 LogFlowFunc(("uClient=%RU32\n", pClient->uClientID)); 1320 1321 if (pClient->fDeferred) 1322 { 1323 if (pClient->Deferred.cParms >= 2) 1324 { 1325 AssertPtrReturn(pClient->Deferred.paParms, VERR_BUFFER_OVERFLOW); 1326 1327 HGCMSvcSetU32(&pClient->Deferred.paParms[0], uMsg); 1328 HGCMSvcSetU32(&pClient->Deferred.paParms[1], cParms); 1329 1330 rc = VINF_SUCCESS; 1331 } 1332 else 1333 rc = VERR_INVALID_PARAMETER; 1334 } 1335 else 1336 rc = VERR_INVALID_STATE; 1337 1338 LogFlowFuncLeaveRC(rc); 1339 return rc; 1340 } 1341 1342 /** 1000 1343 * Initializes a Shared Clipboard service's client state. 1001 1344 * … … 1025 1368 LogFlowFuncEnter(); 1026 1369 1027 RT_NOREF(pState);1370 vboxSvcClipboardMsgQueueReset(pState); 1028 1371 1029 1372 return VINF_SUCCESS; … … 1040 1383 1041 1384 /** @todo Clear async / asynRead / ... data? */ 1042 1043 pState->u32ClientID = 0; 1044 pState->fAsync = false; 1045 pState->fHostMsgFormats = false; 1046 pState->fHostMsgQuit = false; 1047 pState->fHostMsgReadData = false; 1048 pState->fReadPending = false; 1385 vboxSvcClipboardMsgQueueReset(pState); 1386 1387 pState->u32ClientID = 0; 1388 pState->fAsync = false; 1389 pState->fReadPending = false; 1390 1391 pState->fHostMsgQuit = false; 1392 pState->fHostMsgReadData = false; 1393 pState->fHostMsgFormats = false; 1394 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 1395 pState->URI.fTransferStart = false; 1396 pState->URI.enmTransferDir = SHAREDCLIPBOARDURITRANSFERDIR_UNKNOWN; 1397 #endif 1398 1049 1399 pState->u32AvailableFormats = 0; 1050 1400 pState->u32RequestedFormat = 0; … … 1061 1411 int rc = VINF_SUCCESS; 1062 1412 1063 LogFunc(("svcHostCall: fn = %d, cParms = %d, pparms = %d\n", 1064 u32Function, cParms, paParms)); 1413 LogFlowFunc(("u32Function=%RU32, cParms=%RU32, paParms=%p\n", u32Function, cParms, paParms)); 1065 1414 1066 1415 switch (u32Function) … … 1111 1460 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 1112 1461 rc = vboxSvcClipboardURIHostHandler(u32Function, cParms, paParms); 1462 #else 1463 rc = VERR_NOT_IMPLEMENTED; 1113 1464 #endif 1114 1465 } break; 1115 1466 } 1116 1467 1117 LogFlowFunc (("svcHostCall: rc = %Rrc\n", rc));1468 LogFlowFuncLeaveRC(rc); 1118 1469 return rc; 1119 1470 } … … 1218 1569 int rc = VINF_SUCCESS; 1219 1570 1220 if (g_pClientData != NULL) 1571 PVBOXCLIPBOARDCLIENTDATA pClientData = NULL; /** @todo FIX !!! */ 1572 1573 if (pClientData != NULL) 1221 1574 { 1222 1575 switch (u32Function) -
trunk/src/VBox/HostServices/SharedClipboard/testcase/tstClipboardServiceHost.cpp
r79120 r79497 118 118 HGCMSvcSetU32(&parms[1], 0); 119 119 call.rc = VERR_TRY_AGAIN; 120 table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG ,120 table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD, 121 121 2, parms, 0); 122 122 RTTESTI_CHECK_RC(call.rc, VERR_TRY_AGAIN); /* This should get updated only when the guest call completes. */ … … 127 127 RTTESTI_CHECK_RC_OK(call.rc); 128 128 call.rc = VERR_TRY_AGAIN; 129 table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG ,129 table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD, 130 130 2, parms, 0); 131 131 RTTESTI_CHECK_RC(call.rc, VERR_TRY_AGAIN); /* This call should not complete yet. */ … … 138 138 HGCMSvcSetU32(&parms[1], 0); 139 139 call.rc = VERR_TRY_AGAIN; 140 table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG ,140 table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD, 141 141 2, parms, 0); 142 142 RTTESTI_CHECK(parms[0].u.uint32 == VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA); … … 144 144 RTTESTI_CHECK_RC_OK(call.rc); 145 145 call.rc = VERR_TRY_AGAIN; 146 table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG ,146 table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD, 147 147 2, parms, 0); 148 148 RTTESTI_CHECK_RC(call.rc, VERR_TRY_AGAIN); /* This call should not complete yet. */ … … 153 153 HGCMSvcSetU32(&parms[1], 0); 154 154 call.rc = VERR_TRY_AGAIN; 155 table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG ,155 table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD, 156 156 2, parms, 0); 157 157 RTTESTI_CHECK_RC(call.rc, VERR_TRY_AGAIN); /* This should get updated only when the guest call completes. */ … … 162 162 RTTESTI_CHECK_RC_OK(call.rc); 163 163 call.rc = VERR_TRY_AGAIN; 164 table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG ,164 table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD, 165 165 2, parms, 0); 166 166 RTTESTI_CHECK(parms[0].u.uint32 == VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA); … … 168 168 RTTESTI_CHECK_RC_OK(call.rc); 169 169 call.rc = VERR_TRY_AGAIN; 170 table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG ,170 table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD, 171 171 2, parms, 0); 172 172 RTTESTI_CHECK_RC(call.rc, VERR_TRY_AGAIN); /* This call should not complete yet. */ … … 179 179 HGCMSvcSetU32(&parms[1], 0); 180 180 call.rc = VERR_TRY_AGAIN; 181 table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG ,181 table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD, 182 182 2, parms, 0); 183 183 RTTESTI_CHECK(parms[0].u.uint32 == VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA); … … 185 185 RTTESTI_CHECK_RC_OK(call.rc); 186 186 call.rc = VERR_TRY_AGAIN; 187 table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG ,187 table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD, 188 188 2, parms, 0); 189 189 RTTESTI_CHECK(parms[0].u.uint32 == VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA); … … 191 191 RTTESTI_CHECK_RC_OK(call.rc); 192 192 call.rc = VERR_TRY_AGAIN; 193 table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG ,193 table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD, 194 194 2, parms, 0); 195 195 RTTESTI_CHECK_RC(call.rc, VERR_TRY_AGAIN); /* This call should not complete yet. */
Note:
See TracChangeset
for help on using the changeset viewer.