Changeset 58329 in vbox
- Timestamp:
- Oct 20, 2015 10:05:12 AM (9 years ago)
- Location:
- trunk
- Files:
-
- 12 edited
-
include/VBox/HostServices/DragAndDropSvc.h (modified) (6 diffs)
-
include/VBox/HostServices/Service.h (modified) (5 diffs)
-
src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibDragAndDrop.cpp (modified) (19 diffs)
-
src/VBox/Frontends/VirtualBox/src/runtime/UIDnDHandler.cpp (modified) (14 diffs)
-
src/VBox/Frontends/VirtualBox/src/runtime/UIDnDHandler.h (modified) (4 diffs)
-
src/VBox/GuestHost/DragAndDrop/DnDURIList.cpp (modified) (2 diffs)
-
src/VBox/HostServices/DragAndDrop/service.cpp (modified) (22 diffs)
-
src/VBox/Main/include/GuestDnDPrivate.h (modified) (20 diffs)
-
src/VBox/Main/src-client/ConsoleImpl.cpp (modified) (2 diffs)
-
src/VBox/Main/src-client/GuestDnDPrivate.cpp (modified) (5 diffs)
-
src/VBox/Main/src-client/GuestDnDSourceImpl.cpp (modified) (22 diffs)
-
src/VBox/Main/src-client/GuestDnDTargetImpl.cpp (modified) (12 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/HostServices/DragAndDropSvc.h
r58257 r58329 32 32 * Protocol changelog: 33 33 * 34 * Protocol v1 (VBox < 5.0 ):35 * -Initial implementation which only implemented host to guest transfers.36 * -For file transfers all file information such as the file name and file size were34 * Protocol v1 (VBox < 5.0, deprecated): 35 * | Initial implementation which only implemented host to guest transfers. 36 * | For file transfers all file information such as the file name and file size were 37 37 * transferred with every file data chunk being sent. 38 38 * 39 * Protocol v2 (VBox 5.0 ):40 * -Added support for guest to host transfers.41 * -Added protocol version support through VBOXDNDCONNECTMSG. The host takes the installed39 * Protocol v2 (VBox 5.0 - VBox 5.0.8, deprecated): 40 * + Added support for guest to host transfers. 41 * + Added protocol version support through VBOXDNDCONNECTMSG. The host takes the installed 42 42 * Guest Additions version as indicator which protocol to use for communicating with the guest. 43 43 * The guest itself uses VBOXDNDCONNECTMSG to report its supported protocol version to the DnD service. 44 44 * 45 * Protocol v3 (VBox 5.0+): 46 Added context IDs for every HGCM message. Not used yet and must be 0. 47 * - Added VBOXDNDSNDDATAHDR and VBOXDNDCBSNDDATAHDRDATA to support (simple) accounting of objects 45 * Protocol v3 (VBox 5.0.10 and up, current): 46 * + Added VBOXDNDDISCONNECTMSG for being able to track client disconnects on host side (Main). 47 * + Added context IDs for every HGCM message. Not used yet and must be 0. 48 * + Added VBOXDNDSNDDATAHDR and VBOXDNDCBSNDDATAHDRDATA to support (simple) accounting of objects 48 49 * being transferred, along with supplying separate meta data size (which is part of the total size being sent). 49 * -Added new HOST_DND_HG_SND_DATA_HDR + GUEST_DND_GH_SND_DATA_HDR commands which now allow specifying an optional50 * + Added new HOST_DND_HG_SND_DATA_HDR + GUEST_DND_GH_SND_DATA_HDR commands which now allow specifying an optional 50 51 * compression type and defining a checksum for the overall data transfer. 51 * -Enhannced VBOXDNDGHSENDDATAMSG to support (rolling) checksums for the supplied data block.52 * - VBOXDNDHGSENDFILEDATAMSG and VBOXDNDGHSENDFILEDATAMSG are now sharing the same HGCM mesasge.53 * - VBOXDNDHGSENDDATAMSG and VBOXDNDGHSENDDATAMSG can now contain an optional checksum for the current data block.52 * + Enhannced VBOXDNDGHSENDDATAMSG to support (rolling) checksums for the supplied data block. 53 * + VBOXDNDHGSENDDATAMSG and VBOXDNDGHSENDDATAMSG can now contain an optional checksum for the current data block. 54 * | VBOXDNDHGSENDFILEDATAMSG and VBOXDNDGHSENDFILEDATAMSG are now sharing the same HGCM mesasge. 54 55 * - Removed unused HOST_DND_GH_RECV_DIR, HOST_DND_GH_RECV_FILE_DATA and HOST_DND_GH_RECV_FILE_HDR commands. 55 56 */ … … 184 185 enum eGuestFn 185 186 { 186 /* Guest sends a connection request to the HGCM service. 187 /* Guest sends a connection request to the HGCM service, 188 * along with some additional information like supported 189 * protocol version and flags. 187 190 * Note: New since protocol version 2. */ 188 191 GUEST_DND_CONNECT = 10, 192 193 /* Sent when a guest client disconnected from the HGCM service. */ 194 GUEST_DND_DISCONNECT = 11, 189 195 190 196 /** … … 287 293 HGCMFunctionParameter uAllActions; /* OUT uint32_t */ 288 294 HGCMFunctionParameter pvFormats; /* OUT ptr */ 289 HGCMFunctionParameter c Formats;/* OUT uint32_t */295 HGCMFunctionParameter cbFormats; /* OUT uint32_t */ 290 296 } v1; 291 297 struct … … 299 305 HGCMFunctionParameter uAllActions; /* OUT uint32_t */ 300 306 HGCMFunctionParameter pvFormats; /* OUT ptr */ 301 HGCMFunctionParameter c Formats;/* OUT uint32_t */307 HGCMFunctionParameter cbFormats; /* OUT uint32_t */ 302 308 } v3; 303 309 } u; … … 680 686 681 687 /** 682 * HG Acknowledge Operation event. 688 * Acknowledges a host operation along with the allowed 689 * action(s) on the guest. 683 690 * 684 691 * Used by: … … 923 930 uint32_t uFlags; 924 931 } VBOXDNDCBCONNECTMSGDATA, *PVBOXDNDCBCONNECTMSGDATA; 932 933 typedef struct VBOXDNDCBDISCONNECTMSGDATA 934 { 935 /** Callback data header. */ 936 VBOXDNDCBHEADERDATA hdr; 937 } VBOXDNDCBDISCONNECTMSGDATA, *PVBOXDNDCBDISCONNECTMSGDATA; 925 938 926 939 typedef struct VBOXDNDCBHGGETNEXTHOSTMSG -
trunk/include/VBox/HostServices/Service.h
r58106 r58329 300 300 } 301 301 302 pr ivate:302 protected: 303 303 304 304 uint32_t m_uClientId; … … 310 310 PVBOXHGCMSVCPARM m_paParms; 311 311 }; 312 313 /** 314 * Structure for keeping a HGCM service context. 315 */ 316 typedef struct VBOXHGCMSVCTX 317 { 318 /** HGCM helper functions. */ 319 PVBOXHGCMSVCHELPERS pHelpers; 320 /* 321 * Callback function supplied by the host for notification of updates 322 * to properties. 323 */ 324 PFNHGCMSVCEXT pfnHostCallback; 325 /** User data pointer to be supplied to the host callback function. */ 326 void *pvHostData; 327 } VBOXHGCMSVCTX, *PVBOXHGCMSVCTX; 312 328 313 329 template <class T> … … 383 399 protected: 384 400 explicit AbstractService(PVBOXHGCMSVCHELPERS pHelpers) 385 : m_pHelpers(pHelpers)386 , m_pfnHostCallback(NULL)387 , m_pvHostData(NULL)388 {}401 { 402 RT_ZERO(m_SvcCtx); 403 m_SvcCtx.pHelpers = pHelpers; 404 } 389 405 virtual int init(VBOXHGCMSVCFNTABLE *ptable) { return VINF_SUCCESS; } 390 406 virtual int uninit() { return VINF_SUCCESS; } … … 396 412 /** Type definition for use in callback functions. */ 397 413 typedef AbstractService SELF; 398 /** HGCM helper functions. */ 399 PVBOXHGCMSVCHELPERS m_pHelpers; 400 /* 401 * Callback function supplied by the host for notification of updates 402 * to properties. 403 */ 404 PFNHGCMSVCEXT m_pfnHostCallback; 405 /** User data pointer to be supplied to the host callback function. */ 406 void *m_pvHostData; 414 /** The HGCM service context this service is bound to. */ 415 VBOXHGCMSVCTX m_SvcCtx; 407 416 408 417 /** … … 500 509 LogFlowFunc(("pvService=%p, pfnExtension=%p, pvExtention=%p\n", pvService, pfnExtension, pvExtension)); 501 510 SELF *pSelf = reinterpret_cast<SELF *>(pvService); 502 pSelf->m_ pfnHostCallback = pfnExtension;503 pSelf->m_ pvHostData= pvExtension;511 pSelf->m_SvcCtx.pfnHostCallback = pfnExtension; 512 pSelf->m_SvcCtx.pvHostData = pvExtension; 504 513 return VINF_SUCCESS; 505 514 } -
trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibDragAndDrop.cpp
r58257 r58329 131 131 Msg.u.v1.uAllActions.SetUInt32(0); 132 132 Msg.u.v1.pvFormats.SetPtr(pszFormats, cbFormats); 133 Msg.u.v1.c Formats.SetUInt32(0);133 Msg.u.v1.cbFormats.SetUInt32(0); 134 134 } 135 135 else … … 144 144 Msg.u.v3.uAllActions.SetUInt32(0); 145 145 Msg.u.v3.pvFormats.SetPtr(pszFormats, cbFormats); 146 Msg.u.v3.c Formats.SetUInt32(0);146 Msg.u.v3.cbFormats.SetUInt32(0); 147 147 } 148 148 … … 160 160 rc = Msg.u.v1.uDefAction.GetUInt32(puDefAction); AssertRC(rc); 161 161 rc = Msg.u.v1.uAllActions.GetUInt32(puAllActions); AssertRC(rc); 162 rc = Msg.u.v1.c Formats.GetUInt32(pcbFormatsRecv);AssertRC(rc);162 rc = Msg.u.v1.cbFormats.GetUInt32(pcbFormatsRecv); AssertRC(rc); 163 163 } 164 164 else … … 170 170 rc = Msg.u.v3.uDefAction.GetUInt32(puDefAction); AssertRC(rc); 171 171 rc = Msg.u.v3.uAllActions.GetUInt32(puAllActions); AssertRC(rc); 172 rc = Msg.u.v3.c Formats.GetUInt32(pcbFormatsRecv);AssertRC(rc);172 rc = Msg.u.v3.cbFormats.GetUInt32(pcbFormatsRecv); AssertRC(rc); 173 173 } 174 174 … … 447 447 } 448 448 449 static int vbglR3DnDHGRecvURIData(PVBGLR3GUESTDNDCMDCTX pCtx, DnDDroppedFiles *pDroppedFiles)449 static int vbglR3DnDHGRecvURIData(PVBGLR3GUESTDNDCMDCTX pCtx, PVBOXDNDSNDDATAHDR pDataHdr, DnDDroppedFiles *pDroppedFiles) 450 450 { 451 451 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 452 AssertPtrReturn(pDataHdr, VERR_INVALID_POINTER); 452 453 AssertPtrReturn(pDroppedFiles, VERR_INVALID_POINTER); 454 455 /* Only count the raw data minus the already received meta data. */ 456 Assert(pDataHdr->cbTotal >= pDataHdr->cbMeta); 457 uint64_t cbToRecvBytes = pDataHdr->cbTotal - pDataHdr->cbMeta; 458 uint64_t cToRecvObjs = pDataHdr->cObjects; 459 460 LogFlowFunc(("cbToRecvBytes=%RU64, cToRecvObjs=%RU64, (cbTotal=%RU64, cbMeta=%RU32)\n", 461 cbToRecvBytes, cToRecvObjs, pDataHdr->cbTotal, pDataHdr->cbMeta)); 462 463 /* 464 * Only do accounting for protocol v3 and up. 465 * The older protocols did not have any data accounting available, so 466 * we simply tried to receive as much data as available and bail out. 467 */ 468 const bool fDoAccounting = pCtx->uProtocol >= 3; 469 470 /* Anything to do at all? */ 471 if (fDoAccounting) 472 { 473 if ( !cbToRecvBytes 474 && !cToRecvObjs) 475 { 476 return VINF_SUCCESS; 477 } 478 } 453 479 454 480 /* … … 484 510 char szPathName[RTPATH_MAX] = { 0 }; 485 511 uint32_t cbPathName = 0; 486 uint32_t fFlags = 0; 487 uint32_t fMode = 0; 488 489 while (RT_SUCCESS(rc)) 490 { 512 uint32_t fFlags = 0; 513 uint32_t fMode = 0; 514 515 /* 516 * Only wait for new incoming commands for protocol v3 and up. 517 * The older protocols did not have any data accounting available, so 518 * we simply tried to receive as much data as available and bail out. 519 */ 520 const bool fWait = pCtx->uProtocol >= 3; 521 522 do 523 { 524 LogFlowFunc(("Wating for new message ...\n")); 525 491 526 uint32_t uNextMsg; 492 527 uint32_t cNextParms; 493 rc = vbglR3DnDGetNextMsgType(pCtx, &uNextMsg, &cNextParms, f alse /* fWait */);528 rc = vbglR3DnDGetNextMsgType(pCtx, &uNextMsg, &cNextParms, fWait); 494 529 if (RT_SUCCESS(rc)) 495 530 { … … 519 554 if (RT_SUCCESS(rc)) 520 555 rc = pDroppedFiles->AddDir(pszPathAbs); 556 557 if ( RT_SUCCESS(rc) 558 && fDoAccounting) 559 { 560 Assert(cToRecvObjs); 561 cToRecvObjs--; 562 } 521 563 522 564 RTStrFree(pszPathAbs); … … 623 665 /* Data transfer complete? Close the file. */ 624 666 fClose = objFile.IsComplete(); 667 if ( fClose 668 && fDoAccounting) 669 { 670 Assert(cToRecvObjs); 671 cToRecvObjs--; 672 } 625 673 626 674 /* Only since protocol v2 we know the file size upfront. */ … … 631 679 632 680 cbFileWritten += cbChunkWritten; 681 682 if (pCtx->uProtocol >= 3) 683 { 684 Assert(cbToRecvBytes >= cbChunkRead); 685 cbToRecvBytes -= cbChunkRead; 686 } 633 687 } 634 688 … … 660 714 break; 661 715 662 } /* while */ 716 if (fDoAccounting) 717 { 718 LogFlowFunc(("cbToRecvBytes=%RU64, cToRecvObjs=%RU64\n", cbToRecvBytes, cToRecvObjs)); 719 if ( !cbToRecvBytes 720 && !cToRecvObjs) 721 { 722 break; 723 } 724 } 725 726 } while (RT_SUCCESS(rc)); 663 727 664 728 LogFlowFunc(("Loop ended with %Rrc\n", rc)); … … 723 787 uint32_t cbDataRecv; 724 788 725 if (pCtx->uProtocol < 3) /* For VBox < 5.0.8. */789 if (pCtx->uProtocol < 3) 726 790 { 727 791 Msg.hdr.cParms = 5; … … 901 965 uint32_t cbDataRecv; 902 966 903 if (pCtx->uProtocol < 3) /* For VBox < 5.0.8. */ 967 LogFlowFuncEnter(); 968 969 if (pCtx->uProtocol < 3) 904 970 { 905 971 uint64_t cbDataTmp = pCtx->cbMaxChunkSize; … … 979 1045 RTMemFree(pvDataTmp); 980 1046 } 981 else /* Protocol v3 and up. Since VBox 5.0.8.*/1047 else /* Protocol v3 and up. */ 982 1048 { 983 1049 rc = vbglR3DnDHGRecvDataHdr(pCtx, pDataHdr); 984 1050 if (RT_SUCCESS(rc)) 985 1051 { 986 LogFlowFunc(("cb Meta=%RU32\n", pDataHdr->cbMeta));1052 LogFlowFunc(("cbTotal=%RU64, cbMeta=%RU32\n", pDataHdr->cbTotal, pDataHdr->cbMeta)); 987 1053 if (pDataHdr->cbMeta) 988 1054 { … … 1086 1152 rc = lstURI.RootFromURIData(pvData, cbData, 0 /* fFlags */); 1087 1153 if (RT_SUCCESS(rc)) 1088 rc = vbglR3DnDHGRecvURIData(pCtx, &d roppedFiles);1154 rc = vbglR3DnDHGRecvURIData(pCtx, &dataHdr, &droppedFiles); 1089 1155 1090 1156 if (RT_SUCCESS(rc)) /** @todo Remove this block as soon as we hand in DnDURIList. */ … … 1506 1572 Msg.hdr.u32Function = GUEST_DND_HG_ACK_OP; 1507 1573 1574 LogFlowFunc(("uProto=%RU32\n", pCtx->uProtocol)); 1575 1508 1576 if (pCtx->uProtocol < 3) 1509 1577 { … … 1660 1728 1661 1729 /* For protocol v3 and up we need to send the data header first. */ 1662 if (pCtx->uProtocol > 2)1730 if (pCtx->uProtocol >= 3) 1663 1731 { 1664 1732 AssertPtrReturn(pDataHdr, VERR_INVALID_POINTER); … … 1675 1743 Msg.uScreenId.SetUInt32(0); /** @todo Not used for guest->host (yet). */ 1676 1744 Msg.cbTotal.SetUInt64(pDataHdr->cbTotal); 1677 Msg.cbMeta.SetUInt 64(pDataHdr->cbMeta);1745 Msg.cbMeta.SetUInt32(pDataHdr->cbMeta); 1678 1746 Msg.pvMetaFmt.SetPtr(pDataHdr->pvMetaFmt, pDataHdr->cbMetaFmt); 1679 1747 Msg.cbMetaFmt.SetUInt32(pDataHdr->cbMetaFmt); … … 1700 1768 Msg.hdr.u32Function = GUEST_DND_GH_SND_DATA; 1701 1769 1702 if (pCtx->uProtocol > 2)1770 if (pCtx->uProtocol >= 3) 1703 1771 { 1704 1772 Msg.hdr.cParms = 5; … … 1721 1789 uint32_t cbSent = 0; 1722 1790 1723 HGCMFunctionParameter *pParm = (pCtx->uProtocol > 2)1791 HGCMFunctionParameter *pParm = (pCtx->uProtocol >= 3) 1724 1792 ? &Msg.u.v3.pvData 1725 1793 : &Msg.u.v1.pvData; -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDHandler.cpp
r58212 r58329 75 75 : m_pSession(pSession) 76 76 , m_pParent(pParent) 77 , m_enm Mode(DNDMODE_UNKNOWN)77 , m_enmOpMode(DNDMODE_UNKNOWN) 78 78 , m_fIsPending(false) 79 79 , m_fDataRetrieved(false) … … 99 99 const QMimeData *pMimeData) 100 100 { 101 LogFlowFunc(("enm Mode=%RU32, screenID=%RU32, x=%d, y=%d, action=%ld\n",102 m_enm Mode, screenID, x, y, toVBoxDnDAction(proposedAction)));103 104 if ( m_enm Mode != DNDMODE_UNKNOWN105 && m_enm Mode != DNDMODE_HOSTTOGUEST)101 LogFlowFunc(("enmOpMode=%RU32, screenID=%RU32, x=%d, y=%d, action=%ld\n", 102 m_enmOpMode, screenID, x, y, toVBoxDnDAction(proposedAction))); 103 104 if ( m_enmOpMode != DNDMODE_UNKNOWN 105 && m_enmOpMode != DNDMODE_HOSTTOGUEST) 106 106 return Qt::IgnoreAction; 107 107 … … 114 114 pMimeData->formats().toVector()); 115 115 if (m_dndTarget.isOk()) 116 setMode(DNDMODE_HOSTTOGUEST); 117 118 /* Set the DnD action returned by the guest. */ 119 return toQtDnDAction(result); 116 { 117 setOpMode(DNDMODE_HOSTTOGUEST); 118 return toQtDnDAction(result); 119 } 120 121 msgCenter().cannotDropDataToGuest(m_dndTarget, m_pParent); 122 return Qt::IgnoreAction; 120 123 } 121 124 … … 124 127 const QMimeData *pMimeData) 125 128 { 126 LogFlowFunc(("enm Mode=%RU32, screenID=%RU32, x=%d, y=%d, action=%ld\n",127 m_enm Mode, screenID, x, y, toVBoxDnDAction(proposedAction)));128 129 if (m_enm Mode != DNDMODE_HOSTTOGUEST)129 LogFlowFunc(("enmOpMode=%RU32, screenID=%RU32, x=%d, y=%d, action=%ld\n", 130 m_enmOpMode, screenID, x, y, toVBoxDnDAction(proposedAction))); 131 132 if (m_enmOpMode != DNDMODE_HOSTTOGUEST) 130 133 return Qt::IgnoreAction; 131 134 … … 138 141 toVBoxDnDActions(possibleActions), 139 142 pMimeData->formats().toVector()); 140 /* Set the DnD action returned by the guest. */ 141 return toQtDnDAction(result); 143 if (m_dndTarget.isOk()) 144 return toQtDnDAction(result); 145 146 msgCenter().cannotDropDataToGuest(m_dndTarget, m_pParent); 147 return Qt::IgnoreAction; 142 148 } 143 149 … … 146 152 const QMimeData *pMimeData) 147 153 { 148 LogFlowFunc(("enm Mode=%RU32, screenID=%RU32, x=%d, y=%d, action=%ld\n",149 m_enm Mode, screenID, x, y, toVBoxDnDAction(proposedAction)));150 151 if (m_enm Mode != DNDMODE_HOSTTOGUEST)154 LogFlowFunc(("enmOpMode=%RU32, screenID=%RU32, x=%d, y=%d, action=%ld\n", 155 m_enmOpMode, screenID, x, y, toVBoxDnDAction(proposedAction))); 156 157 if (m_enmOpMode != DNDMODE_HOSTTOGUEST) 152 158 return Qt::IgnoreAction; 153 159 … … 258 264 * mode as well here. 259 265 */ 260 set Mode(DNDMODE_UNKNOWN);266 setOpMode(DNDMODE_UNKNOWN); 261 267 262 268 return toQtDnDAction(enmResult); … … 265 271 void UIDnDHandler::dragLeave(ulong screenID) 266 272 { 267 LogFlowFunc(("enm Mode=%RU32, screenID=%RU32\n", m_enmMode, screenID));268 269 if (m_enm Mode == DNDMODE_HOSTTOGUEST)273 LogFlowFunc(("enmOpMode=%RU32, screenID=%RU32\n", m_enmOpMode, screenID)); 274 275 if (m_enmOpMode == DNDMODE_HOSTTOGUEST) 270 276 { 271 277 m_dndTarget.Leave(screenID); 272 set Mode(DNDMODE_UNKNOWN);278 setOpMode(DNDMODE_UNKNOWN); 273 279 } 274 280 } … … 448 454 #ifdef VBOX_WITH_DRAG_AND_DROP_GH 449 455 450 LogFlowFunc(("enm Mode=%RU32, fIsPending=%RTbool, screenID=%RU32\n", m_enmMode, m_fIsPending, screenID));456 LogFlowFunc(("enmOpMode=%RU32, fIsPending=%RTbool, screenID=%RU32\n", m_enmOpMode, m_fIsPending, screenID)); 451 457 452 458 { 453 459 QMutexLocker AutoReadLock(&m_ReadLock); 454 460 455 if ( m_enm Mode != DNDMODE_UNKNOWN456 && m_enm Mode != DNDMODE_GUESTTOHOST) /* Wrong mode set? */461 if ( m_enmOpMode != DNDMODE_UNKNOWN 462 && m_enmOpMode != DNDMODE_GUESTTOHOST) /* Wrong mode set? */ 457 463 return VINF_SUCCESS; 458 464 … … 548 554 } 549 555 550 set Mode(DNDMODE_GUESTTOHOST);556 setOpMode(DNDMODE_GUESTTOHOST); 551 557 552 558 rc = dragStartInternal(m_dataSource.lstFormats, … … 594 600 m_fIsPending = false; 595 601 596 set Mode(DNDMODE_UNKNOWN);602 setOpMode(DNDMODE_UNKNOWN); 597 603 } 598 604 … … 684 690 /* After we successfully retrieved data from the source we query it from Main. */ 685 691 vecData = m_dndSource.ReceiveData(); /** @todo QVector.size() is "int" only!? */ 686 if (vecData.isEmpty()) 687 rc = VERR_NO_DATA; 692 if (m_dndSource.isOk()) 693 { 694 if (vecData.isEmpty()) 695 rc = VERR_NO_DATA; 696 } 697 else 698 { 699 msgCenter().cannotDropDataToHost(m_dndSource, m_pParent); 700 rc = VERR_GENERAL_FAILURE; /** @todo Fudge; do a GetResultCode() to rc translation. */ 701 } 688 702 } 689 703 else … … 699 713 } 700 714 701 set Mode(DNDMODE_UNKNOWN);715 setOpMode(DNDMODE_UNKNOWN); 702 716 703 717 LogFlowFuncLeaveRC(rc); … … 705 719 } 706 720 707 void UIDnDHandler::set Mode(DNDMODE enmMode)721 void UIDnDHandler::setOpMode(DNDOPMODE enmMode) 708 722 { 709 723 QMutexLocker AutoWriteLock(&m_WriteLock); 710 m_enm Mode = enmMode;711 LogF lowFunc(("Mode is now: %RU32\n", m_enmMode));724 m_enmOpMode = enmMode; 725 LogFunc(("Operation mode is now: %RU32\n", m_enmOpMode)); 712 726 } 713 727 -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDHandler.h
r57288 r58329 49 49 * drag and drop mode. 50 50 */ 51 typedef enum DND MODE51 typedef enum DNDOPMODE 52 52 { 53 53 /** Unknown mode. */ … … 60 60 /** The usual 32-bit type blow up. */ 61 61 DNDMODE_32BIT_HACK = 0x7fffffff 62 } DND MODE;62 } DNDOPMODE; 63 63 64 64 /** … … 125 125 int dragStartInternal(const QStringList &lstFormats, Qt::DropAction defAction, Qt::DropActions actions); 126 126 int retrieveDataInternal(Qt::DropAction dropAction, const QString &strMIMEType, QVector<uint8_t> &vecData); 127 void set Mode(DNDMODE enmMode);127 void setOpMode(DNDOPMODE enmMode); 128 128 129 129 protected: … … 133 133 /** Pointer to parent widget. */ 134 134 QWidget *m_pParent; 135 136 135 /** Drag and drop source instance. */ 137 136 CDnDSource m_dndSource; 138 137 /** Drag and drop target instance. */ 139 138 CDnDTarget m_dndTarget; 140 /** Current transfer direction. */ 141 DNDMODE m_enmMode; 139 /** Current operation mode, indicating the transfer direction. 140 * Note: This is independent of the current drag and drop 141 * mode being set for this VM! */ 142 DNDOPMODE m_enmOpMode; 142 143 /** Current data from the source (if any). 143 144 * At the momenet we only support one source at a time. */ -
trunk/src/VBox/GuestHost/DragAndDrop/DnDURIList.cpp
r58212 r58329 25 25 #include <iprt/fs.h> 26 26 #include <iprt/path.h> 27 #include <iprt/string.h> 27 28 #include <iprt/symlink.h> 28 29 #include <iprt/uri.h> … … 448 449 AssertReturn(cbData, VERR_INVALID_PARAMETER); 449 450 451 if (!RTStrIsValidEncoding(static_cast<const char *>(pvData))) 452 return VERR_INVALID_PARAMETER; 453 450 454 RTCList<RTCString> lstURI = 451 RTCString(static_cast<const char *>(pvData), cbData - 1).split("\r\n");455 RTCString(static_cast<const char *>(pvData), cbData - 1).split("\r\n"); 452 456 if (lstURI.isEmpty()) 453 457 return VINF_SUCCESS; -
trunk/src/VBox/HostServices/DragAndDrop/service.cpp
r58257 r58329 30 30 #define LOG_GROUP LOG_GROUP_GUEST_DND 31 31 32 #include <algorithm> 33 #include <list> 32 34 #include <map> 33 35 … … 44 46 *********************************************************************************************************************************/ 45 47 46 /** Map holding pointers to HGCM clients. Key is the (unique) HGCM client ID. */ 47 typedef std::map<uint32_t, HGCM::Client*> DnDClientMap; 48 class DragAndDropClient : public HGCM::Client 49 { 50 public: 51 52 DragAndDropClient(uint32_t uClientId, VBOXHGCMCALLHANDLE hHandle = NULL, 53 uint32_t uMsg = 0, uint32_t cParms = 0, VBOXHGCMSVCPARM aParms[] = NULL) 54 : HGCM::Client(uClientId, hHandle, uMsg, cParms, aParms) 55 , m_fDeferred(false) 56 { 57 RT_ZERO(m_SvcCtx); 58 } 59 60 virtual ~DragAndDropClient(void) 61 { 62 disconnect(); 63 } 64 65 public: 66 67 void complete(VBOXHGCMCALLHANDLE hHandle, int rcOp); 68 void completeDeferred(int rcOp); 69 void disconnect(void); 70 bool isDeferred(void) const { return m_fDeferred; } 71 void setDeferred(VBOXHGCMCALLHANDLE hHandle, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 72 void setSvcContext(const HGCM::VBOXHGCMSVCTX &SvcCtx) { m_SvcCtx = SvcCtx; } 73 74 protected: 75 76 /** The HGCM service context this client is bound to. */ 77 HGCM::VBOXHGCMSVCTX m_SvcCtx; 78 /** Flag indicating whether this client currently is deferred mode, 79 * meaning that it did not return to the caller yet. */ 80 bool m_fDeferred; 81 }; 82 83 /** Map holding pointers to drag and drop clients. Key is the (unique) HGCM client ID. */ 84 typedef std::map<uint32_t, DragAndDropClient*> DnDClientMap; 85 86 /** Simple queue (list) which holds deferred (waiting) clients. */ 87 typedef std::list<uint32_t> DnDClientQueue; 48 88 49 89 /** … … 68 108 69 109 int modeSet(uint32_t u32Mode); 70 inline uint32_t modeGet( ){ return m_u32Mode; };110 inline uint32_t modeGet(void) const { return m_u32Mode; }; 71 111 72 112 protected: … … 76 116 protected: 77 117 78 DnDManager *m_pManager; 79 /** Map of all connected clients. */ 80 DnDClientMap m_clientMap; 118 /** Pointer to our DnD manager instance. */ 119 DnDManager *m_pManager; 120 /** Map of all connected clients. 121 * The primary key is the (unique) client ID, the secondary value 122 * an allocated pointer to the DragAndDropClient class, managed 123 * by this service class. */ 124 DnDClientMap m_clientMap; 81 125 /** List of all clients which are queued up (deferred return) and ready 82 * to process new commands. */ 83 RTCList<HGCM::Client*> m_clientQueue; 84 uint32_t m_u32Mode; 126 * to process new commands. The key is the (unique) client ID. */ 127 DnDClientQueue m_clientQueue; 128 /** Current drag and drop mode. */ 129 uint32_t m_u32Mode; 85 130 }; 86 131 132 133 /********************************************************************************************************************************* 134 * Client implementation * 135 *********************************************************************************************************************************/ 136 137 /** 138 * Completes the call by returning the control back to the guest 139 * side code. 140 */ 141 void DragAndDropClient::complete(VBOXHGCMCALLHANDLE hHandle, int rcOp) 142 { 143 LogFlowThisFunc(("uClientID=%RU32\n", m_uClientId)); 144 145 if ( m_SvcCtx.pHelpers 146 && m_SvcCtx.pHelpers->pfnCallComplete) 147 { 148 m_SvcCtx.pHelpers->pfnCallComplete(hHandle, rcOp); 149 } 150 } 151 152 /** 153 * Completes a deferred call by returning the control back to the guest 154 * side code. 155 */ 156 void DragAndDropClient::completeDeferred(int rcOp) 157 { 158 AssertMsg(m_fDeferred, ("Client %RU32 is not in deferred mode\n", m_uClientId)); 159 Assert(m_hHandle != NULL); 160 161 LogFlowThisFunc(("uClientID=%RU32\n", m_uClientId)); 162 163 complete(m_hHandle, rcOp); 164 m_fDeferred = false; 165 } 166 167 /** 168 * Called when the HGCM client disconnected on the guest side. 169 * This function takes care of the client's data cleanup and also lets the host 170 * know that the client has been disconnected. 171 * 172 */ 173 void DragAndDropClient::disconnect(void) 174 { 175 LogFlowThisFunc(("uClient=%RU32\n", m_uClientId)); 176 177 if (isDeferred()) 178 completeDeferred(VERR_INTERRUPTED); 179 180 /* 181 * Let the host know. 182 */ 183 VBOXDNDCBDISCONNECTMSGDATA data; 184 RT_ZERO(data); 185 /** @todo Magic needed? */ 186 187 if (m_SvcCtx.pfnHostCallback) 188 { 189 int rc2 = m_SvcCtx.pfnHostCallback(m_SvcCtx.pvHostData, GUEST_DND_DISCONNECT, &data, sizeof(data)); 190 if (RT_FAILURE(rc2)) 191 LogFlowFunc(("Warning: Unable to notify host about client %RU32 disconnect, rc=%Rrc\n", m_uClientId, rc2)); 192 /* Not fatal. */ 193 } 194 } 195 196 /** 197 * Set the client's status to deferred, meaning that it does not return to the caller 198 * on the guest side yet. 199 */ 200 void DragAndDropClient::setDeferred(VBOXHGCMCALLHANDLE hHandle, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 201 { 202 LogFlowThisFunc(("uClient=%RU32\n", m_uClientId)); 203 204 AssertMsg(m_fDeferred == false, ("Client already in deferred mode\n")); 205 m_fDeferred = true; 206 207 m_hHandle = hHandle; 208 m_uMsg = u32Function; 209 m_cParms = cParms; 210 m_paParms = paParms; 211 } 87 212 88 213 /********************************************************************************************************************************* … … 118 243 int DragAndDropService::uninit(void) 119 244 { 245 LogFlowFuncEnter(); 246 120 247 if (m_pManager) 121 248 { … … 124 251 } 125 252 253 DnDClientMap::iterator itClient = m_clientMap.begin(); 254 while (itClient != m_clientMap.end()) 255 { 256 delete itClient->second; 257 m_clientMap.erase(itClient); 258 itClient = m_clientMap.begin(); 259 } 260 261 LogFlowFuncLeave(); 126 262 return VINF_SUCCESS; 127 263 } … … 147 283 try 148 284 { 149 m_clientMap[u32ClientID] = new HGCM::Client(u32ClientID); 285 DragAndDropClient *pClient = new DragAndDropClient(u32ClientID); 286 pClient->setSvcContext(m_SvcCtx); 287 m_clientMap[u32ClientID] = pClient; 150 288 } 151 289 catch(std::bad_alloc &) … … 179 317 * Remove from waiters queue. 180 318 */ 181 for (size_t i = 0; i < m_clientQueue.size(); i++) 182 { 183 HGCM::Client *pClient = m_clientQueue.at(i); 184 if (pClient->clientId() == u32ClientID) 185 { 186 if (m_pHelpers) 187 m_pHelpers->pfnCallComplete(pClient->handle(), VERR_INTERRUPTED); 188 189 m_clientQueue.removeAt(i); 190 delete pClient; 191 192 break; 193 } 194 } 319 m_clientQueue.remove(u32ClientID); 195 320 196 321 /* … … 208 333 int DragAndDropService::modeSet(uint32_t u32Mode) 209 334 { 210 /** @todo Validate mode. */ 335 #ifndef VBOX_WITH_DRAG_AND_DROP_GH 336 if ( u32Mode == VBOX_DRAG_AND_DROP_MODE_GUEST_TO_HOST 337 || u32Mode == VBOX_DRAG_AND_DROP_MODE_BIDIRECTIONAL) 338 { 339 m_u32Mode = VBOX_DRAG_AND_DROP_MODE_OFF; 340 return VERR_NOT_SUPPORTED; 341 } 342 #endif 343 211 344 switch (u32Mode) 212 345 { … … 308 441 #endif 309 442 310 #define DO_HOST_CALLBACK(); \ 311 if ( RT_SUCCESS(rc) \ 312 && m_pfnHostCallback) \ 313 { \ 314 rc = m_pfnHostCallback(m_pvHostData, u32Function, &data, sizeof(data)); \ 443 #define DO_HOST_CALLBACK(); \ 444 if ( RT_SUCCESS(rc) \ 445 && m_SvcCtx.pfnHostCallback) \ 446 { \ 447 rc = m_SvcCtx.pfnHostCallback(m_SvcCtx.pvHostData, u32Function, &data, sizeof(data)); \ 448 } 449 450 /* 451 * Lookup client. 452 */ 453 DragAndDropClient *pClient = NULL; 454 455 DnDClientMap::iterator itClient = m_clientMap.find(u32ClientID); 456 if (itClient != m_clientMap.end()) 457 { 458 pClient = itClient->second; 459 AssertPtr(pClient); 460 } 461 else 462 { 463 LogFunc(("Client %RU32 was not found\n", u32ClientID)); 464 rc = VERR_NOT_FOUND; 315 465 } 316 466 317 467 if (rc == VINF_SUCCESS) /* Note: rc might be VINF_HGCM_ASYNC_EXECUTE! */ 318 468 { 319 DnDClientMap::iterator itClient = m_clientMap.find(u32ClientID);320 Assert(itClient != m_clientMap.end());321 322 HGCM::Client *pClient = itClient->second;323 AssertPtr(pClient);324 325 469 LogFlowFunc(("Client %RU32: Protocol v%RU32\n", pClient->clientId(), pClient->protocol())); 326 470 … … 344 488 if (RT_FAILURE(rc)) /* No queued messages available? */ 345 489 { 346 if (m_ pfnHostCallback) /* Try asking the host. */490 if (m_SvcCtx.pfnHostCallback) /* Try asking the host. */ 347 491 { 348 492 VBOXDNDCBHGGETNEXTHOSTMSG data; 349 493 RT_ZERO(data); 350 494 data.hdr.uMagic = CB_MAGIC_DND_HG_GET_NEXT_HOST_MSG; 351 rc = m_ pfnHostCallback(m_pvHostData, u32Function, &data, sizeof(data));495 rc = m_SvcCtx.pfnHostCallback(m_SvcCtx.pvHostData, u32Function, &data, sizeof(data)); 352 496 if (RT_SUCCESS(rc)) 353 497 { … … 366 510 if (RT_FAILURE(rc)) 367 511 { 368 if (paParms[2].u.uint32) /* Blocking flag set? */ 512 uint32_t fFlags = 0; 513 int rc2 = paParms[2].getUInt32(&fFlags); 514 if ( RT_SUCCESS(rc2) 515 && fFlags) /* Blocking flag set? */ 369 516 { 370 517 /* Defer client returning. */ 371 518 rc = VINF_HGCM_ASYNC_EXECUTE; 372 519 } 520 else 521 rc = VERR_INVALID_PARAMETER; 373 522 374 523 LogFlowFunc(("Message queue is empty, returning %Rrc to guest\n", rc)); … … 390 539 if (cParms >= 3) 391 540 rc = paParms[0].getUInt32(&data.hdr.uContextID); 541 else /* Older protocols don't have a context ID. */ 542 rc = VINF_SUCCESS; 392 543 if (RT_SUCCESS(rc)) 393 544 rc = paParms[idxProto].getUInt32(&data.uProtocol); … … 660 811 rc = paParms[0].getUInt32(&data.hdr.uContextID); 661 812 if (RT_SUCCESS(rc)) 662 rc = paParms[ 0].getPointer((void**)&data.pszPath, &data.cbPath);663 if (RT_SUCCESS(rc)) 664 rc = paParms[ 1].getUInt32(&data.cbPath);665 if (RT_SUCCESS(rc)) 666 rc = paParms[ 2].getUInt32(&data.fMode);813 rc = paParms[1].getPointer((void**)&data.pszPath, &data.cbPath); 814 if (RT_SUCCESS(rc)) 815 rc = paParms[2].getUInt32(&data.cbPath); 816 if (RT_SUCCESS(rc)) 817 rc = paParms[3].getUInt32(&data.fMode); 667 818 } 668 819 break; … … 842 993 if (rc == VERR_NO_DATA) /* Manager has no new messsages? Try asking the host. */ 843 994 { 844 if (m_ pfnHostCallback)995 if (m_SvcCtx.pfnHostCallback) 845 996 { 846 997 VBOXDNDCBHGGETNEXTHOSTMSGDATA data; … … 851 1002 data.paParms = paParms; 852 1003 853 rc = m_pfnHostCallback(m_pvHostData, u32Function, &data, sizeof(data)); 1004 rc = m_SvcCtx.pfnHostCallback(m_SvcCtx.pvHostData, u32Function, 1005 &data, sizeof(data)); 854 1006 if (RT_SUCCESS(rc)) 855 1007 { … … 875 1027 try 876 1028 { 877 LogFlowFunc(("Deferring guest call completion of client ID=%RU32\n", u32ClientID));878 m_clientQueue.append(new HGCM::Client(u32ClientID, callHandle,879 u32Function, cParms, paParms));1029 AssertPtr(pClient); 1030 pClient->setDeferred(callHandle, u32Function, cParms, paParms); 1031 m_clientQueue.push_back(u32ClientID); 880 1032 } 881 1033 catch (std::bad_alloc) … … 885 1037 } 886 1038 } 887 else if (m_pHelpers) 888 { 889 /* Complete call on guest side. */ 890 m_pHelpers->pfnCallComplete(callHandle, rc); 891 } 1039 else if (pClient) 1040 pClient->complete(callHandle, rc); 892 1041 else 893 1042 rc = VERR_NOT_IMPLEMENTED; … … 921 1070 if (m_clientQueue.size()) /* Any clients in our queue ready for processing the next command? */ 922 1071 { 923 HGCM::Client *pClient = m_clientQueue.first(); 1072 uint32_t uClientNext = m_clientQueue.front(); 1073 DnDClientMap::iterator itClientNext = m_clientMap.find(uClientNext); 1074 Assert(itClientNext != m_clientMap.end()); 1075 1076 DragAndDropClient *pClient = itClientNext->second; 924 1077 AssertPtr(pClient); 925 1078 … … 939 1092 if (RT_SUCCESS(rc)) 940 1093 { 941 pClient->addMessageInfo(uMsg1, cParms1); 942 if ( m_pHelpers 943 && m_pHelpers->pfnCallComplete) 944 { 945 m_pHelpers->pfnCallComplete(pClient->handle(), rc); 946 } 947 948 m_clientQueue.removeFirst(); 949 950 delete pClient; 951 pClient = NULL; 952 } 953 else 954 AssertMsgFailed(("m_pManager::nextMessageInfo failed with rc=%Rrc\n", rc)); 1094 rc = pClient->addMessageInfo(uMsg1, cParms1); 1095 1096 /* Note: Report the current rc back to the guest. */ 1097 pClient->completeDeferred(rc); 1098 1099 m_clientQueue.pop_front(); 1100 } 955 1101 } 956 1102 else … … 992 1138 AssertPtr(pSelf); 993 1139 994 if (pSelf->m_ pfnHostCallback)1140 if (pSelf->m_SvcCtx.pfnHostCallback) 995 1141 { 996 1142 LogFlowFunc(("GUEST_DND_HG_EVT_PROGRESS: uStatus=%RU32, uPercentage=%RU32, rc=%Rrc\n", … … 1003 1149 data.rc = rc; /** @todo uin32_t vs. int. */ 1004 1150 1005 return pSelf->m_ pfnHostCallback(pSelf->m_pvHostData,1006 GUEST_DND_HG_EVT_PROGRESS,1007 &data, sizeof(data));1151 return pSelf->m_SvcCtx.pfnHostCallback(pSelf->m_SvcCtx.pvHostData, 1152 GUEST_DND_HG_EVT_PROGRESS, 1153 &data, sizeof(data)); 1008 1154 } 1009 1155 -
trunk/src/VBox/Main/include/GuestDnDPrivate.h
r58232 r58329 51 51 typedef std::vector<com::Utf8Str> GuestDnDMIMEList; 52 52 53 /* 54 ** @todo Put most of the implementations below in GuestDnDPrivate.cpp! 55 */ 56 53 57 class GuestDnDCallbackEvent 54 58 { … … 100 104 size_t add(const void *pvDataAdd, size_t cbDataAdd) 101 105 { 106 LogFlowThisFunc(("pvDataAdd=%p, cbDataAdd=%zu\n", pvDataAdd, cbDataAdd)); 107 102 108 if (!cbDataAdd) 103 109 return 0; … … 217 223 218 224 GuestDnDData(void) 219 : cbProcessed(0) 220 , cbAddData(0) 225 : cbEstTotal(0) 226 , cbEstMeta(0) 227 , cbProcessed(0) 221 228 { 222 229 RT_ZERO(dataHdr); … … 241 248 { 242 249 const uint64_t cbTotal = getTotal(); 250 LogFlowFunc(("cbProcessed=%RU64, cbTotal=%RU64\n", cbProcessed, cbTotal)); 243 251 Assert(cbProcessed <= cbTotal); 244 252 return (cbProcessed == cbTotal); … … 257 265 uint8_t getPercentComplete(void) const 258 266 { 259 int64_t cbTotal = RT_MAX(getTotal(), 1);267 int64_t cbTotal = RT_MAX(getTotal(), 1); 260 268 return (uint8_t)(cbProcessed * 100 / cbTotal); 261 269 } … … 270 278 } 271 279 272 uint64_t getTotal(void) const { return dataMeta.getSize() + cbAddData; }280 uint64_t getTotal(void) const { return cbEstTotal; } 273 281 274 282 void reset(void) … … 280 288 281 289 dataMeta.reset(); 290 291 cbEstTotal = 0; 292 cbEstMeta = 0; 282 293 cbProcessed = 0; 283 cbAddData = 0;284 294 } 285 295 … … 306 316 } 307 317 308 void setAdditionalSize(uint64_t cbAdd)309 {310 LogFlowFunc(("cbAdd=%RU64\n", cbAdd));311 312 cbAddData = cbAdd;313 314 invalidate();315 }316 317 318 void setEstimatedSize(uint64_t cbTotal, uint32_t cbMeta) 318 319 { 319 320 Assert(cbMeta <= cbTotal); 320 321 321 LogFlowFunc(("cbTotal=%RU64, cbMeta=%RU64\n", cbTotal, cbMeta)); 322 323 dataMeta.reset(); 324 325 dataHdr.cbMeta = cbMeta; 326 setAdditionalSize(cbTotal - cbMeta); 322 LogFlowFunc(("cbTotal=%RU64, cbMeta=%RU32\n", cbTotal, cbMeta)); 323 324 cbEstTotal = cbTotal; 325 cbEstMeta = cbMeta; 327 326 } 328 327 … … 351 350 352 351 dataHdr.cbMetaFmt = 0; 353 }354 355 void invalidate(void)356 {357 /* Update data header. */358 dataHdr.cbMeta = dataMeta.getSize();359 dataHdr.cbTotal = dataHdr.cbMeta + cbAddData;360 361 LogFlowFunc(("cbTotal=%RU64, cbMeta=%RU32\n", dataHdr.cbTotal, dataHdr.cbMeta));362 352 } 363 353 … … 370 360 * according to the format being sent. */ 371 361 GuestDnDMetaData dataMeta; 362 /** Estimated total data size when receiving data. */ 363 uint64_t cbEstTotal; 364 /** Estimated meta data size when receiving data. */ 365 uint32_t cbEstMeta; 372 366 /** Overall size (in bytes) of processed data. */ 373 367 uint64_t cbProcessed; 374 /** Additional data to process which does not count375 * as meta data. Just in here for accounting reasons. */376 uint64_t cbAddData;377 368 }; 369 370 /** Initial state. */ 371 #define DND_OBJCTX_STATE_NONE 0 372 /** The header was received/sent. */ 373 #define DND_OBJCTX_STATE_HAS_HDR RT_BIT(0) 378 374 379 375 /** … … 387 383 : pObjURI(NULL) 388 384 , fIntermediate(false) 389 , f HeaderSent(false) { }385 , fState(DND_OBJCTX_STATE_NONE) { } 390 386 391 387 virtual ~GuestDnDURIObjCtx(void) … … 396 392 public: 397 393 398 DnDURIObject *createIntermediate(void) 399 { 394 int createIntermediate(DnDURIObject::Type enmType = DnDURIObject::Unknown) 395 { 396 LogFlowThisFuncEnter(); 397 400 398 reset(); 401 399 400 int rc; 401 402 402 try 403 403 { 404 pObjURI = new DnDURIObject( );404 pObjURI = new DnDURIObject(enmType); 405 405 fIntermediate = true; 406 407 rc = VINF_SUCCESS; 406 408 } 407 409 catch (std::bad_alloc &) 408 410 { 409 } 410 411 return pObjURI; 411 rc = VERR_NO_MEMORY; 412 } 413 414 return rc; 412 415 } 413 416 414 417 void destroy(void) 415 418 { 419 LogFlowThisFuncEnter(); 420 416 421 if ( pObjURI 417 422 && fIntermediate) 418 423 { 419 424 delete pObjURI; 420 fIntermediate = false; 421 } 422 423 pObjURI = NULL; 424 } 425 } 426 427 pObjURI = NULL; 428 fIntermediate = false; 429 } 430 431 DnDURIObject *getObj(void) { return pObjURI; } 425 432 426 433 bool isIntermediate(void) { return fIntermediate; } … … 428 435 bool isValid(void) const { return (pObjURI != NULL); } 429 436 437 uint32_t getState(void) const { return fState; } 438 430 439 void reset(void) 431 440 { 441 LogFlowThisFuncEnter(); 442 432 443 destroy(); 433 444 434 445 fIntermediate = false; 435 fHeaderSent = false; 436 } 446 fState = 0; 447 } 448 449 void setObj(DnDURIObject *pObj) 450 { 451 LogFlowThisFunc(("%p\n", pObj)); 452 453 destroy(); 454 455 pObjURI = pObj; 456 } 457 458 uint32_t setState(uint32_t fStateNew) 459 { 460 /** @todo Add validation. */ 461 fState = fStateNew; 462 return fState; 463 } 464 465 protected: 437 466 438 467 /** Pointer to current object being handled. */ … … 440 469 /** Flag whether pObjURI needs deletion after use. */ 441 470 bool fIntermediate; 442 /** Flag whether the object's file header has been sent already. */443 bool fHeaderSent;471 /** Internal context state, corresponding to DND_OBJCTX_STATE_XXX. */ 472 uint32_t fState; 444 473 /** @todo Add more statistics / information here. */ 445 474 }; … … 490 519 bool isComplete(void) const 491 520 { 492 LogFlowFunc(("cObjToProcess=%RU64, cObjProcessed=%RU64\n", cObjToProcess, cObjProcessed)); 521 LogFlowFunc(("cObjProcessed=%RU64, cObjToProcess=%RU64\n", cObjProcessed, cObjToProcess)); 522 523 if (!cObjToProcess) /* Always return true if we don't have an object count. */ 524 return true; 525 493 526 Assert(cObjProcessed <= cObjToProcess); 494 527 return (cObjProcessed == cObjToProcess); … … 514 547 { 515 548 /* Point the context object to the current DnDURIObject to process. */ 516 objCtx. pObjURI = pCurObj;549 objCtx.setObj(pCurObj); 517 550 } 518 551 else … … 534 567 { 535 568 case DnDURIObject::Directory: 536 rc = processDirectory(Obj.GetDestPath().c_str(), Obj.GetMode());537 break;538 539 569 case DnDURIObject::File: 540 570 rc = VINF_SUCCESS; … … 570 600 } 571 601 572 void reset(uint64_t cObjs = 0) 573 { 574 cObjToProcess = cObjs; 602 void reset(void) 603 { 604 LogFlowFuncEnter(); 605 606 cObjToProcess = 0; 575 607 cObjProcessed = 0; 576 577 LogFlowFunc(("cObjToProcess=%RU64\n", cObjToProcess));578 608 579 609 droppedFiles.Close(); … … 583 613 } 584 614 585 public: 586 587 int fromMetaData(const GuestDnDMetaData &Data) 615 void setEstimatedObjects(uint64_t cObjs) 616 { 617 Assert(cObjToProcess == 0); 618 cObjToProcess = cObjs; 619 LogFlowFunc(("cObjToProcess=%RU64\n", cObjs)); 620 } 621 622 public: 623 624 int fromLocalMetaData(const GuestDnDMetaData &Data) 588 625 { 589 626 reset(); 590 627 591 size_t cbList = Data.getSize(); 592 const char *pszList = (const char *)Data.getData(); 593 if ( !pszList 594 || !cbList) 595 { 628 if (!Data.getSize()) 596 629 return VINF_SUCCESS; 597 } 598 599 if (!RTStrIsValidEncoding(pszList)) 600 return VERR_INVALID_PARAMETER; 601 602 RTCList<RTCString> lstURIOrg = RTCString(pszList, cbList).split("\r\n"); 603 if (lstURIOrg.isEmpty()) 604 return VINF_SUCCESS; 605 606 /* Note: All files to be transferred will be kept open during the entire DnD 607 * operation, also to keep the accounting right. */ 608 return lstURI.AppendURIPathsFromList(lstURIOrg, DNDURILIST_FLAGS_KEEP_OPEN); 630 631 char *pszList; 632 int rc = RTStrCurrentCPToUtf8(&pszList, (const char *)Data.getData()); 633 if (RT_FAILURE(rc)) 634 { 635 LogFlowThisFunc(("String conversion failed with rc=%Rrc\n", rc)); 636 return rc; 637 } 638 639 const size_t cbList = Data.getSize(); 640 LogFlowThisFunc(("metaData=%p, cbList=%zu\n", &Data, cbList)); 641 642 if (cbList) 643 { 644 RTCList<RTCString> lstURIOrg = RTCString(pszList, cbList).split("\r\n"); 645 if (!lstURIOrg.isEmpty()) 646 { 647 /* Note: All files to be transferred will be kept open during the entire DnD 648 * operation, also to keep the accounting right. */ 649 rc = lstURI.AppendURIPathsFromList(lstURIOrg, DNDURILIST_FLAGS_KEEP_OPEN); 650 if (RT_SUCCESS(rc)) 651 cObjToProcess = lstURI.TotalCount(); 652 } 653 } 654 655 RTStrFree(pszList); 656 return rc; 657 } 658 659 int fromRemoteMetaData(const GuestDnDMetaData &Data) 660 { 661 LogFlowFuncEnter(); 662 663 int rc = lstURI.RootFromURIData(Data.getData(), Data.getSize(), 0 /* uFlags */); 664 if (RT_SUCCESS(rc)) 665 { 666 const size_t cRootCount = lstURI.RootCount(); 667 LogFlowFunc(("cRootCount=%zu, cObjToProcess=%RU64\n", cRootCount, cObjToProcess)); 668 if (cRootCount > cObjToProcess) 669 rc = VERR_INVALID_PARAMETER; 670 } 671 672 return rc; 609 673 } 610 674 … … 909 973 typedef std::map<uint32_t, GuestDnDCallback> GuestDnDCallbackMap; 910 974 975 /** @todo r=andy This class needs to go, as this now is too inflexible when it comes to all 976 * the callback handling/dispatching. It's part of the initial code and only adds 977 * unnecessary complexity. */ 911 978 class GuestDnDResponse 912 979 { -
trunk/src/VBox/Main/src-client/ConsoleImpl.cpp
r58170 r58329 7385 7385 #endif // 0 7386 7386 7387 7387 7388 7388 /* setup task object and thread to carry out the operation 7389 7389 * asynchronously */ … … 8590 8590 8591 8591 int rc = pVMMDev->hgcmHostCall("VBoxDragAndDropSvc", 8592 DragAndDropSvc::HOST_DND_SET_MODE, 1, &parm); 8593 LogFlowFunc(("rc=%Rrc\n", rc)); 8592 DragAndDropSvc::HOST_DND_SET_MODE, 1 /* cParms */, &parm); 8593 if (RT_FAILURE(rc)) 8594 LogRel(("Error changing drag and drop mode: %Rrc\n", rc)); 8595 8594 8596 return rc; 8595 8597 } -
trunk/src/VBox/Main/src-client/GuestDnDPrivate.cpp
r58257 r58329 312 312 case DragAndDropSvc::DND_PROGRESS_CANCELLED: 313 313 { 314 hr = m_pProgress->i_notifyComplete(S_OK); 314 hr = m_pProgress->Cancel(); 315 AssertComRC(hr); 316 hr = m_pProgress->i_notifyComplete(S_FALSE); 315 317 AssertComRC(hr); 316 318 … … 364 366 case DragAndDropSvc::GUEST_DND_CONNECT: 365 367 { 366 /* Not used in here (yet). */ 368 LogThisFunc(("Client connected\n")); 369 370 /* Nothing to do here (yet). */ 367 371 rc = VINF_SUCCESS; 372 break; 373 } 374 375 case DragAndDropSvc::GUEST_DND_DISCONNECT: 376 { 377 LogThisFunc(("Client disconnected\n")); 378 rc = setProgress(100, DND_PROGRESS_CANCELLED, VINF_SUCCESS); 368 379 break; 369 380 } … … 836 847 && (uRevAdditions = m_pGuest->i_getAdditionsRevision()) > 0) 837 848 { 838 #ifdef _DEBUG839 # if 0849 #ifdef DEBUG 850 # if 1 840 851 /* Hardcode the to-used protocol version; nice for testing side effects. */ 841 852 uProto = 3; 853 rc = VINF_SUCCESS; 842 854 # endif 843 855 #endif … … 851 863 } 852 864 else 853 uProto = 2; /* VBox 5.0.0 - 5.0. 6: Protocol v2. */865 uProto = 2; /* VBox 5.0.0 - 5.0.8: Protocol v2. */ 854 866 } 855 867 … … 940 952 941 953 LogFlowFunc(("cbTotal=%RU64, cbProcessed=%RU64, cbRemaining=%RU64, cbDataAdd=%RU32\n", 942 pData->get Processed(), pData->getProcessed(), pData->getRemaining(), cbDataAdd));954 pData->getTotal(), pData->getProcessed(), pData->getRemaining(), cbDataAdd)); 943 955 944 956 if (!pResp) -
trunk/src/VBox/Main/src-client/GuestDnDSourceImpl.cpp
r58257 r58329 407 407 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 408 408 409 LogFlowThisFunc(("cTransfersPending=%RU32\n", mDataBase.m_cTransfersPending)); 410 409 411 /* Don't allow receiving the actual data until our transfer actually is complete. */ 410 412 if (mDataBase.m_cTransfersPending) … … 412 414 413 415 PRECVDATACTX pCtx = &mData.mRecvCtx; 414 415 if (pCtx->mData.getMeta().getSize() == 0)416 {417 LogFlowFunc(("No data available, returning 0\n"));418 aData.resize(0);419 return S_OK;420 }421 422 416 HRESULT hr = S_OK; 423 size_t cbData;424 417 425 418 try … … 435 428 else 436 429 { 437 cbData = pCtx->mData.getMeta().getSize(); 438 439 /* Copy the data into a safe array of bytes. */ 440 aData.resize(cbData); 441 memcpy(&aData.front(), pCtx->mData.getMeta().getData(), cbData); 430 const size_t cbData = pCtx->mData.getMeta().getSize(); 431 LogFlowFunc(("cbData=%zu\n", cbData)); 432 if (cbData) 433 { 434 /* Copy the data into a safe array of bytes. */ 435 aData.resize(cbData); 436 memcpy(&aData.front(), pCtx->mData.getMeta().getData(), cbData); 437 } 438 else 439 aData.resize(0); 442 440 } 443 441 } … … 447 445 } 448 446 449 LogFlowFunc(("Returning cbData=%zu, hr=%Rhrc\n", cbData, hr));447 LogFlowFunc(("Returning hr=%Rhrc\n", hr)); 450 448 return hr; 451 449 #endif /* VBOX_WITH_DRAG_AND_DROP */ … … 536 534 537 535 Assert(pCtx->mURI.getObjToProcess() == 0); 538 pCtx->mURI.reset(pDataHdr->cObjects); 536 pCtx->mURI.reset(); 537 pCtx->mURI.setEstimatedObjects(pDataHdr->cObjects); 539 538 540 539 /** @todo Handle compression type. */ … … 554 553 try 555 554 { 556 GuestDnDData *pData = &pCtx->mData;557 GuestDnDURIData *pURI = &pCtx->mURI;555 GuestDnDData *pData = &pCtx->mData; 556 GuestDnDURIData *pURI = &pCtx->mURI; 558 557 559 558 uint32_t cbData; 560 559 void *pvData; 561 uint64_t cbTo Process;560 uint64_t cbTotal; 562 561 uint32_t cbMeta; 563 562 564 563 if (mDataBase.m_uProtocolVersion < 3) 565 564 { 566 cbData = pSndData->u.v1.cbData;567 pvData = pSndData->u.v1.pvData;565 cbData = pSndData->u.v1.cbData; 566 pvData = pSndData->u.v1.pvData; 568 567 569 568 /* Sends the total data size to receive for every data chunk. */ 570 cbTo Process= pSndData->u.v1.cbTotalSize;569 cbTotal = pSndData->u.v1.cbTotalSize; 571 570 572 571 /* Meta data size always is cbData, meaning there cannot be an 573 572 * extended data chunk transfer by sending further data. */ 574 cbMeta = cbData;573 cbMeta = cbData; 575 574 } 576 575 else 577 576 { 578 cbData = pSndData->u.v3.cbData;579 pvData = pSndData->u.v3.pvData;577 cbData = pSndData->u.v3.cbData; 578 pvData = pSndData->u.v3.pvData; 580 579 581 580 /* Note: Data sizes get updated in i_onReceiveDataHdr(). */ 582 cbTo Process= pData->getTotal();583 cbMeta = pData->getMeta().getSize();584 } 585 Assert(cbTo Process);581 cbTotal = pData->getTotal(); 582 cbMeta = pData->getMeta().getSize(); 583 } 584 Assert(cbTotal); 586 585 587 586 if ( cbData == 0 588 || cbData > cbTo Process/* Paranoia */)587 || cbData > cbTotal /* Paranoia */) 589 588 { 590 589 LogFlowFunc(("Incoming data size invalid: cbData=%RU32, cbToProcess=%RU64\n", cbData, pData->getTotal())); 591 590 rc = VERR_INVALID_PARAMETER; 592 591 } 593 else if (cbTo Process< cbMeta)594 { 595 AssertMsgFailed(("cbTo Process (%RU64) is smaller than meta size (%zu)\n", cbToProcess, cbMeta));592 else if (cbTotal < cbMeta) 593 { 594 AssertMsgFailed(("cbTotal (%RU64) is smaller than cbMeta (%RU32)\n", cbTotal, cbMeta)); 596 595 rc = VERR_INVALID_PARAMETER; 597 596 } … … 599 598 if (RT_SUCCESS(rc)) 600 599 { 601 pData->getMeta().add(pvData, cbData);602 LogFlowThisFunc(("cbMetaSize=%zu, cbData=%RU32, cbMeta=%RU32, cbTo Process=%RU64\n",603 pData->getMeta().getSize(), cbData, cbMeta, cbTo Process));600 cbMeta = pData->getMeta().add(pvData, cbData); 601 LogFlowThisFunc(("cbMetaSize=%zu, cbData=%RU32, cbMeta=%RU32, cbTotal=%RU64\n", 602 pData->getMeta().getSize(), cbData, cbMeta, cbTotal)); 604 603 } 605 604 606 605 if (RT_SUCCESS(rc)) 607 606 { 608 /* (Meta) Data transfer complete? */ 607 /* 608 * (Meta) Data transfer complete? 609 */ 609 610 Assert(cbMeta <= pData->getMeta().getSize()); 610 611 if (cbMeta == pData->getMeta().getSize()) … … 615 616 { 616 617 /* Try parsing the data as URI list. */ 617 rc = pURI->from MetaData(pData->getMeta());618 rc = pURI->fromRemoteMetaData(pData->getMeta()); 618 619 if (RT_SUCCESS(rc)) 619 620 { 620 621 if (mDataBase.m_uProtocolVersion < 3) 621 pData->setEstimatedSize(cbTo Process, cbMeta);622 pData->setEstimatedSize(cbTotal, cbMeta); 622 623 623 624 /* … … 655 656 || cbPath > RTPATH_MAX) 656 657 { 658 LogFlowFunc(("Path length invalid, bailing out\n")); 657 659 return VERR_INVALID_PARAMETER; 658 660 } 659 661 660 if (!RTStrIsValidEncoding(pszPath)) 662 int rc = RTStrValidateEncodingEx(pszPath, RTSTR_MAX, 0); 663 if (RT_FAILURE(rc)) 664 { 665 LogFlowFunc(("Path validation failed with %Rrc, bailing out\n", rc)); 661 666 return VERR_INVALID_PARAMETER; 667 } 662 668 663 669 if (pCtx->mURI.isComplete()) 670 { 671 LogFlowFunc(("Data transfer already complete, bailing out\n")); 664 672 return VERR_INVALID_PARAMETER; 665 666 GuestDnDURIObjCtx objCtx = pCtx->mURI.getObj(0); /** @todo Fill in context ID. */ 667 DnDURIObject *pObj = objCtx.createIntermediate(); 668 if (!pObj) 669 return VERR_NO_MEMORY; 670 671 int rc; 673 } 674 675 GuestDnDURIObjCtx &objCtx = pCtx->mURI.getObj(0); /** @todo Fill in context ID. */ 676 677 rc = objCtx.createIntermediate(DnDURIObject::Directory); 678 if (RT_FAILURE(rc)) 679 return rc; 680 681 DnDURIObject *pObj = objCtx.getObj(); 682 AssertPtr(pObj); 672 683 673 684 const char *pszDroppedFilesDir = pCtx->mURI.getDroppedFiles().GetDirAbs(); … … 682 693 rc = RTDirCreateFullPath(pszDir, fMode); 683 694 if (RT_SUCCESS(rc)) 695 { 696 pCtx->mURI.processObject(*pObj); 697 objCtx.reset(); 684 698 LogRel2(("DnD: Created guest directory on host: %s\n", pszDir)); 699 } 685 700 else 686 701 LogRel(("DnD: Error creating guest directory '%s' on host, rc=%Rrc\n", pszDir, rc)); 687 688 pCtx->mURI.removeObjCurrent();689 702 690 703 RTStrFree(pszDir); … … 726 739 } 727 740 728 if (pCtx->mURI. isComplete())741 if (pCtx->mURI.getObjToProcess() && pCtx->mURI.isComplete()) 729 742 return VERR_INVALID_PARAMETER; 730 743 … … 733 746 do 734 747 { 735 GuestDnDURIObjCtx objCtx = pCtx->mURI.getObj(0); /** @todo Fill in context ID. */736 DnDURIObject *pObj = objCtx.pObjURI;748 GuestDnDURIObjCtx &objCtx = pCtx->mURI.getObj(0); /** @todo Fill in context ID. */ 749 DnDURIObject *pObj = objCtx.getObj(); 737 750 738 751 /* … … 760 773 * Create new intermediate object to work with. 761 774 */ 762 pObj = objCtx.createIntermediate(); 763 if (!pObj) 764 rc = VERR_NO_MEMORY; 765 775 rc = objCtx.createIntermediate(); 766 776 if (RT_SUCCESS(rc)) 767 777 { 778 pObj = objCtx.getObj(); 779 768 780 const char *pszDroppedFilesDir = pCtx->mURI.getDroppedFiles().GetDirAbs(); 769 781 … … 828 840 int rc = VINF_SUCCESS; 829 841 842 LogFlowFunc(("pvData=%p, cbData=%RU32, cbBlockSize=%RU32\n", pvData, cbData, mData.mcbBlockSize)); 843 830 844 /* 831 845 * Sanity checking. … … 836 850 do 837 851 { 838 GuestDnDURIObjCtx objCtx = pCtx->mURI.getObj(0); /** @todo Fill in context ID. */839 DnDURIObject *pObj = objCtx.pObjURI;852 GuestDnDURIObjCtx &objCtx = pCtx->mURI.getObj(0); /** @todo Fill in context ID. */ 853 DnDURIObject *pObj = objCtx.getObj(); 840 854 841 855 if (!pObj) 842 856 { 843 rc = VERR_INVALID_PARAMETER; 857 LogFlowFunc(("Warning: No current object set\n")); 858 rc = VERR_WRONG_ORDER; 844 859 break; 845 860 } … … 880 895 /** @todo Sanitize path. */ 881 896 LogRel2(("DnD: File transfer to host complete: %s\n", pObj->GetDestPath().c_str())); 897 pCtx->mURI.processObject(*pObj); 882 898 objCtx.reset(); 883 884 rc = VINF_EOF;885 899 } 886 900 } … … 1028 1042 * Register callbacks. 1029 1043 */ 1044 REGISTER_CALLBACK(GUEST_DND_CONNECT); 1045 REGISTER_CALLBACK(GUEST_DND_DISCONNECT); 1030 1046 REGISTER_CALLBACK(GUEST_DND_GH_EVT_ERROR); 1031 1047 REGISTER_CALLBACK(GUEST_DND_GH_SND_DATA); … … 1059 1075 * Unregister callbacks. 1060 1076 */ 1077 UNREGISTER_CALLBACK(GUEST_DND_CONNECT); 1078 UNREGISTER_CALLBACK(GUEST_DND_DISCONNECT); 1061 1079 UNREGISTER_CALLBACK(GUEST_DND_GH_EVT_ERROR); 1062 1080 UNREGISTER_CALLBACK(GUEST_DND_GH_SND_DATA); … … 1114 1132 */ 1115 1133 /* Guest callbacks. */ 1134 REGISTER_CALLBACK(GUEST_DND_CONNECT); 1135 REGISTER_CALLBACK(GUEST_DND_DISCONNECT); 1116 1136 REGISTER_CALLBACK(GUEST_DND_GH_EVT_ERROR); 1117 1137 if (mDataBase.m_uProtocolVersion >= 3) … … 1164 1184 * Unregister callbacks. 1165 1185 */ 1186 UNREGISTER_CALLBACK(GUEST_DND_CONNECT); 1187 UNREGISTER_CALLBACK(GUEST_DND_DISCONNECT); 1166 1188 UNREGISTER_CALLBACK(GUEST_DND_GH_EVT_ERROR); 1167 1189 UNREGISTER_CALLBACK(GUEST_DND_GH_SND_DATA_HDR); … … 1224 1246 switch (uMsg) 1225 1247 { 1248 case GUEST_DND_CONNECT: 1249 /* Nothing to do here (yet). */ 1250 break; 1251 1252 case GUEST_DND_DISCONNECT: 1253 rc = VERR_CANCELLED; 1254 break; 1255 1226 1256 #ifdef VBOX_WITH_DRAG_AND_DROP_GH 1227 1257 case GUEST_DND_GH_SND_DATA_HDR: … … 1297 1327 switch (uMsg) 1298 1328 { 1329 case GUEST_DND_CONNECT: 1330 /* Nothing to do here (yet). */ 1331 break; 1332 1333 case GUEST_DND_DISCONNECT: 1334 rc = VERR_CANCELLED; 1335 break; 1336 1299 1337 #ifdef VBOX_WITH_DRAG_AND_DROP_GH 1300 1338 case GUEST_DND_GH_SND_DATA_HDR: -
trunk/src/VBox/Main/src-client/GuestDnDTargetImpl.cpp
r58257 r58329 866 866 AssertPtrReturn(pMsg, VERR_INVALID_POINTER); 867 867 868 DnDURIObject *pObj = pObjCtx-> pObjURI;868 DnDURIObject *pObj = pObjCtx->getObj(); 869 869 AssertPtr(pObj); 870 870 … … 893 893 AssertPtrReturn(pMsg, VERR_INVALID_POINTER); 894 894 895 DnDURIObject *pObj = pObjCtx-> pObjURI;895 DnDURIObject *pObj = pObjCtx->getObj(); 896 896 AssertPtr(pObj); 897 897 … … 920 920 if (mDataBase.m_uProtocolVersion >= 2) 921 921 { 922 if (!pObjCtx->fHeaderSent) 922 uint32_t fState = pObjCtx->getState(); 923 if (!(fState & DND_OBJCTX_STATE_HAS_HDR)) 923 924 { 924 925 /* … … 941 942 /** @todo Set progress object title to current file being transferred? */ 942 943 943 pObjCtx-> fHeaderSent = true;944 pObjCtx->setState(fState | DND_OBJCTX_STATE_HAS_HDR); 944 945 } 945 946 else … … 972 973 AssertPtrReturn(pMsg, VERR_INVALID_POINTER); 973 974 974 DnDURIObject *pObj = pObjCtx-> pObjURI;975 DnDURIObject *pObj = pObjCtx->getObj(); 975 976 AssertPtr(pObj); 976 977 … … 1058 1059 switch (uMsg) 1059 1060 { 1061 case GUEST_DND_CONNECT: 1062 /* Nothing to do here (yet). */ 1063 break; 1064 1065 case GUEST_DND_DISCONNECT: 1066 rc = VERR_CANCELLED; 1067 break; 1068 1060 1069 case GUEST_DND_GET_NEXT_HOST_MSG: 1061 1070 { … … 1252 1261 rc = pCtx->mpResp->setCallback(x, i_sendURIDataCallback, pCtx); \ 1253 1262 if (RT_FAILURE(rc)) \ 1254 break;1263 return rc; 1255 1264 1256 1265 #define UNREGISTER_CALLBACK(x) \ … … 1267 1276 if (RT_FAILURE(rc)) 1268 1277 return rc; 1278 1279 /* 1280 * Register callbacks. 1281 */ 1282 /* Guest callbacks. */ 1283 REGISTER_CALLBACK(GUEST_DND_CONNECT); 1284 REGISTER_CALLBACK(GUEST_DND_DISCONNECT); 1285 REGISTER_CALLBACK(GUEST_DND_GET_NEXT_HOST_MSG); 1286 REGISTER_CALLBACK(GUEST_DND_GH_EVT_ERROR); 1287 /* Host callbacks. */ 1288 REGISTER_CALLBACK(HOST_DND_HG_SND_DIR); 1289 if (mDataBase.m_uProtocolVersion >= 2) 1290 REGISTER_CALLBACK(HOST_DND_HG_SND_FILE_HDR); 1291 REGISTER_CALLBACK(HOST_DND_HG_SND_FILE_DATA); 1269 1292 1270 1293 do … … 1276 1299 GuestDnDURIData *pURI = &pCtx->mURI; 1277 1300 1278 rc = pURI->from MetaData(pData->getMeta());1301 rc = pURI->fromLocalMetaData(pData->getMeta()); 1279 1302 if (RT_FAILURE(rc)) 1280 1303 break; … … 1291 1314 1292 1315 /* 1293 * Set the additional size we are going to send after the meta data header + meta data.1294 * Th is additional data will contain the actual file data we want to transfer.1316 * Set the estimated data sizes we are going to send. 1317 * The total size also contains the meta data size. 1295 1318 */ 1296 pData->setAdditionalSize(pURI->getURIList().TotalBytes()); 1297 1319 const uint32_t cbMeta = pData->getMeta().getSize(); 1320 pData->setEstimatedSize(pURI->getURIList().TotalBytes() + cbMeta /* cbTotal */, 1321 cbMeta /* cbMeta */); 1322 1323 /* 1324 * Set the meta format. 1325 */ 1298 1326 void *pvFmt = (void *)pCtx->mFmtReq.c_str(); 1299 1327 uint32_t cbFmt = pCtx->mFmtReq.length() + 1; /* Include terminating zero. */ … … 1326 1354 if (RT_SUCCESS(rc)) 1327 1355 { 1328 /*1329 * Register callbacks.1330 */1331 /* Guest callbacks. */1332 REGISTER_CALLBACK(GUEST_DND_GET_NEXT_HOST_MSG);1333 REGISTER_CALLBACK(GUEST_DND_GH_EVT_ERROR);1334 /* Host callbacks. */1335 REGISTER_CALLBACK(HOST_DND_HG_SND_DIR);1336 if (mDataBase.m_uProtocolVersion >= 2)1337 REGISTER_CALLBACK(HOST_DND_HG_SND_FILE_HDR);1338 REGISTER_CALLBACK(HOST_DND_HG_SND_FILE_DATA);1339 1340 1356 rc = waitForEvent(&pCtx->mCBEvent, pCtx->mpResp, msTimeout); 1341 if (RT_FAILURE(rc)) 1342 { 1343 if (rc == VERR_CANCELLED) 1344 rc = pCtx->mpResp->setProgress(100, DND_PROGRESS_CANCELLED, VINF_SUCCESS); 1345 else if (rc != VERR_GSTDND_GUEST_ERROR) /* Guest-side error are already handled in the callback. */ 1346 rc = pCtx->mpResp->setProgress(100, DND_PROGRESS_ERROR, rc, 1347 GuestDnDTarget::i_hostErrorToString(rc)); 1348 } 1349 else 1350 rc = pCtx->mpResp->setProgress(100, DND_PROGRESS_COMPLETE, VINF_SUCCESS); 1351 1352 /* 1353 * Unregister callbacks. 1354 */ 1355 /* Guest callbacks. */ 1356 UNREGISTER_CALLBACK(GUEST_DND_GET_NEXT_HOST_MSG); 1357 UNREGISTER_CALLBACK(GUEST_DND_GH_EVT_ERROR); 1358 /* Host callbacks. */ 1359 UNREGISTER_CALLBACK(HOST_DND_HG_SND_DIR); 1360 if (mDataBase.m_uProtocolVersion >= 2) 1361 UNREGISTER_CALLBACK(HOST_DND_HG_SND_FILE_HDR); 1362 UNREGISTER_CALLBACK(HOST_DND_HG_SND_FILE_DATA); 1357 if (RT_SUCCESS(rc)) 1358 pCtx->mpResp->setProgress(100, DND_PROGRESS_COMPLETE, VINF_SUCCESS); 1363 1359 } 1364 1360 1365 1361 } while (0); 1362 1363 /* 1364 * Unregister callbacks. 1365 */ 1366 /* Guest callbacks. */ 1367 UNREGISTER_CALLBACK(GUEST_DND_CONNECT); 1368 UNREGISTER_CALLBACK(GUEST_DND_DISCONNECT); 1369 UNREGISTER_CALLBACK(GUEST_DND_GET_NEXT_HOST_MSG); 1370 UNREGISTER_CALLBACK(GUEST_DND_GH_EVT_ERROR); 1371 /* Host callbacks. */ 1372 UNREGISTER_CALLBACK(HOST_DND_HG_SND_DIR); 1373 if (mDataBase.m_uProtocolVersion >= 2) 1374 UNREGISTER_CALLBACK(HOST_DND_HG_SND_FILE_HDR); 1375 UNREGISTER_CALLBACK(HOST_DND_HG_SND_FILE_DATA); 1366 1376 1367 1377 #undef REGISTER_CALLBACK 1368 1378 #undef UNREGISTER_CALLBACK 1379 1380 if (RT_FAILURE(rc)) 1381 { 1382 if (rc == VERR_CANCELLED) 1383 pCtx->mpResp->setProgress(100, DND_PROGRESS_CANCELLED, VINF_SUCCESS); 1384 else if (rc != VERR_GSTDND_GUEST_ERROR) /* Guest-side error are already handled in the callback. */ 1385 pCtx->mpResp->setProgress(100, DND_PROGRESS_ERROR, rc, 1386 GuestDnDTarget::i_hostErrorToString(rc)); 1387 } 1369 1388 1370 1389 /* … … 1401 1420 return VERR_WRONG_ORDER; 1402 1421 1403 DnDURIObject *pCurObj = objCtx. pObjURI;1422 DnDURIObject *pCurObj = objCtx.getObj(); 1404 1423 AssertPtr(pCurObj); 1405 1424
Note:
See TracChangeset
for help on using the changeset viewer.

