Changeset 82527 in vbox
- Timestamp:
- Dec 10, 2019 1:46:40 AM (5 years ago)
- svn:sync-xref-src-repo-rev:
- 135389
- Location:
- trunk
- Files:
-
- 15 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/GuestHost/SharedClipboard.h
r82513 r82527 157 157 RTLISTNODE Node; 158 158 /** The event's ID, for self-reference. */ 159 SHCLEVENTID uID;159 SHCLEVENTID idEvent; 160 160 /** Event semaphore for signalling the event. */ 161 RTSEMEVENT hEventSem;161 RTSEMEVENTMULTI hEvtMulSem; 162 162 /** Payload to this event, optional (NULL). */ 163 163 PSHCLEVENTPAYLOAD pPayload; … … 177 177 SHCLEVENTSOURCEID uID; 178 178 /** Next upcoming event ID. */ 179 SHCLEVENTID uEventIDNext;179 SHCLEVENTID idNextEvent; 180 180 /** List of events (PSHCLEVENT). */ 181 181 RTLISTANCHOR lstEvents; … … 202 202 * @{ 203 203 */ 204 SHCLEVENTID ShClEventIdGenerateAndRegister(PSHCLEVENTSOURCE pSource); 204 205 SHCLEVENTID ShClEventIDGenerate(PSHCLEVENTSOURCE pSource); 205 206 SHCLEVENTID ShClEventGetLast(PSHCLEVENTSOURCE pSource); -
trunk/include/VBox/HostServices/VBoxClipboardSvc.h
r82526 r82527 114 114 /** Returned only when the HGCM client session is closed (by different thread). 115 115 * 116 * This can require no futher host interaction has session has been closed. 116 * This can require no futher host interaction since the session has been 117 * closed. 118 * 119 * @since 1.3.2 117 120 */ 118 121 #define VBOX_SHCL_HOST_MSG_QUIT 1 119 122 /** Request data for a specific format from the guest. 120 123 * 121 * T his takes one parameter (in addition to the message number),a 32-bit124 * Two parameters, first the 32-bit message ID followed by a a 32-bit 122 125 * format bit (VBOX_SHCL_FMT_XXX). The guest will respond by issuing a 123 * VBOX_SHCL_GUEST_F_DATA_WRITE. 126 * VBOX_SHCL_GUEST_FN_DATA_WRITE. 127 * 128 * @note The host may sometimes incorrectly set more than one format bit, in 129 * which case it's up to the guest to pick which to write back. 130 * @since 1.3.2 124 131 */ 125 132 #define VBOX_SHCL_HOST_MSG_READ_DATA 2 126 /** Reports available clipboard format from host to the guest. 127 * Formerly known as VBOX_SHCL_HOST_MSG_REPORT_FORMATS. */ 133 /** Reports available clipboard format on the host to the guest. 134 * 135 * Two parameters, first the 32-bit message ID followed by a 32-bit format mask 136 * containing zero or more VBOX_SHCL_FMT_XXX flags. The guest is not require to 137 * respond to the host when receiving this message. 138 * 139 * @since 1.3.2 140 */ 128 141 #define VBOX_SHCL_HOST_MSG_FORMATS_REPORT 3 129 142 /** Message PEEK or GET operation was canceled, try again. 143 * 144 * This is returned by VBOX_SHCL_GUEST_FN_MSG_PEEK_WAIT and 145 * VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT in response to the guest calling 146 * VBOX_SHCL_GUEST_FN_MSG_CANCEL. The 2nd parameter is set to zero (be it 147 * thought of as a parameter count or a format mask). 148 * 130 149 * @since 6.1.0 131 150 */ 132 151 #define VBOX_SHCL_HOST_MSG_CANCELED 4 152 153 /** Request data for a specific format from the guest with context ID. 154 * 155 * This is send instead of the VBOX_SHCL_HOST_MSG_READ_DATA message to guest 156 * that advertises VBOX_SHCL_GF_0_CONTEXT_ID. The first parameter is a 64-bit 157 * context ID which is to be used when issuing VBOX_SHCL_GUEST_F_DATA_WRITE, and 158 * the second parameter is a 32-bit format bit (VBOX_SHCL_FMT_XXX). The guest 159 * will respond by issuing a VBOX_SHCL_GUEST_F_DATA_WRITE. 160 * 161 * @note The host may sometimes incorrectly set more than one format bit, in 162 * which case it's up to the guest to pick which to write back. 163 * @since 6.3.2 164 */ 165 #define VBOX_SHCL_HOST_MSG_READ_DATA_CID 5 133 166 134 167 /** Sends a transfer status to the guest side. … … 710 743 #define VBOX_SHCL_CPARMS_REPORT_FORMATS_61B 3 /**< The 6.1 dev cycle variant, see VBOX_SHCL_GUEST_FN_REPORT_FORMATS. */ 711 744 /** @} */ 712 /**713 * Reports available formats.714 */715 typedef struct _VBoxShClFormatsMsg716 {717 VBGLIOCHGCMCALL hdr;718 719 union720 {721 struct722 {723 /** uint32_t, out: VBOX_SHCL_FMT_*. */724 HGCMFunctionParameter uFormats;725 } v0;726 727 struct728 {729 /** uint64_t, out: Context ID. */730 HGCMFunctionParameter uContext;731 /** uint32_t, out: VBOX_SHCL_FMT_*. */732 HGCMFunctionParameter uFormats;733 /** uint32_t, out: Format flags. */734 HGCMFunctionParameter fFlags;735 } v1;736 } u;737 } VBoxShClFormatsMsg;738 739 /**740 * Requests to read clipboard data.741 */742 typedef struct _VBoxShClReadDataReqMsg743 {744 VBGLIOCHGCMCALL hdr;745 746 /** uint64_t, out: Context ID. */747 HGCMFunctionParameter uContext;748 /** uint32_t, out: Request flags; currently unused and must be set to 0. */749 HGCMFunctionParameter fFlags;750 /** uint32_t, out: Requested format to read data in. */751 HGCMFunctionParameter uFormat;752 /** uint32_t, out: Maximum size (in bytes) to read. */753 HGCMFunctionParameter cbSize;754 } VBoxShClReadDataReqMsg;755 756 #define VBOX_SHCL_CPARMS_READ_DATA_REQ 4757 745 758 746 /** @name VBOX_SHCL_GUEST_FN_DATA_READ -
trunk/include/VBox/VBoxGuestLib.h
r82525 r82527 624 624 /** 625 625 * Enumeration specifying a Shared Clipboard event type. 626 * @todo r=bird: Surely, this isn't necessary?! 626 627 */ 627 628 typedef enum _VBGLR3CLIPBOARDEVENTTYPE … … 657 658 SHCLFORMATDATA ReportedFormats; 658 659 /** Reports that data needs to be read from the guest. */ 659 SHCL DATAREQReadData;660 SHCLFORMAT fReadData; 660 661 # ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 661 662 /** Reports a transfer status to the guest. */ -
trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxClipboard.cpp
r82525 r82527 93 93 94 94 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 95 95 96 /** 96 97 * Cleanup helper function for transfer callbacks. … … 218 219 vboxClipboardTransferCallbackCleanup(pData); 219 220 } 221 220 222 #endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */ 221 223 … … 559 561 Assert(pEvent->enmType == VBGLR3CLIPBOARDEVENTTYPE_READ_DATA); 560 562 561 const SHCLFORMAT fFormat = (uint32_t)pEvent->u. ReadData.uFmt;563 const SHCLFORMAT fFormat = (uint32_t)pEvent->u.fReadData; 562 564 563 565 HANDLE hClip = NULL; … … 991 993 int rc; 992 994 993 uint32_t uMsg;994 uint32_t uFormats;995 996 995 /* The thread waits for incoming messages from the host. */ 997 996 for (;;) 998 997 { 999 PVBGLR3CLIPBOARDEVENT pEvent = NULL;1000 1001 998 LogFlowFunc(("Waiting for host message (fUseLegacyProtocol=%RTbool, fHostFeatures=%#RX64) ...\n", 1002 999 pCtx->CmdCtx.fUseLegacyProtocol, pCtx->CmdCtx.fHostFeatures)); 1003 1000 1004 if (pCtx->CmdCtx.fUseLegacyProtocol) 1005 { 1006 rc = VbglR3ClipboardGetHostMsgOld(pCtx->CmdCtx.idClient, &uMsg, &uFormats); 1007 if (RT_FAILURE(rc)) 1008 { 1009 if (rc == VERR_INTERRUPTED) 1010 break; 1011 1012 LogFunc(("Error getting host message, rc=%Rrc\n", rc)); 1013 } 1014 else 1015 { 1016 pEvent = (PVBGLR3CLIPBOARDEVENT)RTMemAllocZ(sizeof(VBGLR3CLIPBOARDEVENT)); 1017 AssertPtrBreakStmt(pEvent, rc = VERR_NO_MEMORY); 1018 1019 switch (uMsg) 1020 { 1021 case VBOX_SHCL_HOST_MSG_FORMATS_REPORT: 1022 { 1023 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_REPORT_FORMATS; 1024 pEvent->u.ReportedFormats.Formats = uFormats; 1025 break; 1026 } 1027 1028 case VBOX_SHCL_HOST_MSG_READ_DATA: 1029 { 1030 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_READ_DATA; 1031 pEvent->u.ReadData.uFmt = uFormats; 1032 break; 1033 } 1034 1035 case VBOX_SHCL_HOST_MSG_QUIT: 1036 { 1037 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_QUIT; 1038 break; 1039 } 1040 1041 default: 1042 rc = VERR_NOT_SUPPORTED; 1043 break; 1044 } 1045 1046 if (RT_SUCCESS(rc)) 1047 { 1048 /* Copy over our command context to the event. */ 1049 pEvent->cmdCtx = pCtx->CmdCtx; 1050 } 1051 } 1052 } 1053 else /* Host service has peeking for messages support. */ 1054 { 1055 pEvent = (PVBGLR3CLIPBOARDEVENT)RTMemAllocZ(sizeof(VBGLR3CLIPBOARDEVENT)); 1056 AssertPtrBreakStmt(pEvent, rc = VERR_NO_MEMORY); 1057 1058 uint32_t uMsg = 0; 1059 uint32_t cParms = 0; 1060 rc = VbglR3ClipboardMsgPeekWait(&pCtx->CmdCtx, &uMsg, &cParms, NULL /* pidRestoreCheck */); 1061 if (RT_SUCCESS(rc)) 1062 { 1063 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 1064 rc = VbglR3ClipboardEventGetNextEx(uMsg, cParms, &pCtx->CmdCtx, &pCtx->TransferCtx, pEvent); 1001 PVBGLR3CLIPBOARDEVENT pEvent = (PVBGLR3CLIPBOARDEVENT)RTMemAllocZ(sizeof(VBGLR3CLIPBOARDEVENT)); 1002 AssertPtrBreakStmt(pEvent, rc = VERR_NO_MEMORY); 1003 1004 uint32_t idMsg = 0; 1005 uint32_t cParms = 0; 1006 rc = VbglR3ClipboardMsgPeekWait(&pCtx->CmdCtx, &idMsg, &cParms, NULL /* pidRestoreCheck */); 1007 if (RT_SUCCESS(rc)) 1008 { 1009 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 1010 rc = VbglR3ClipboardEventGetNextEx(idMsg, cParms, &pCtx->CmdCtx, &pCtx->TransferCtx, pEvent); 1065 1011 #else 1066 rc = VbglR3ClipboardEventGetNext(uMsg, cParms, &pCtx->CmdCtx, pEvent); 1067 #endif 1068 } 1012 rc = VbglR3ClipboardEventGetNext(idMsg, cParms, &pCtx->CmdCtx, pEvent); 1013 #endif 1069 1014 } 1070 1015 -
trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibClipboard.cpp
r82526 r82527 249 249 * @param pFormats Where to store the received formats from the host. 250 250 */ 251 VBGLR3DECL(int) VbglR3ClipboardFormatsReportRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLFORMATDATA pFormats)251 static int vbglR3ClipboardFormatsReportRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLFORMATDATA pFormats) 252 252 { 253 253 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 254 254 AssertPtrReturn(pFormats, VERR_INVALID_POINTER); 255 255 256 VBoxShClFormatsMsg Msg; 257 RT_ZERO(Msg); 258 259 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient, VBOX_SHCL_GUEST_FN_MSG_GET, 3); 260 261 Msg.u.v1.uContext.SetUInt64(VBOX_SHCL_HOST_MSG_FORMATS_REPORT); 262 Msg.u.v1.uFormats.SetUInt32(0); 263 Msg.u.v1.fFlags.SetUInt32(0); 264 265 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg)); 266 if (RT_SUCCESS(rc)) 267 { 268 rc = Msg.u.v1.uContext.GetUInt64(&pCtx->idContext); 269 if (RT_SUCCESS(rc)) 270 rc = Msg.u.v1.uFormats.GetUInt32(&pFormats->Formats); 271 if (RT_SUCCESS(rc)) 272 rc = Msg.u.v1.fFlags.GetUInt32(&pFormats->fFlags); 256 pFormats->fFlags = 0; 257 pFormats->Formats = 0; 258 259 struct 260 { 261 VBGLIOCHGCMCALL Hdr; 262 HGCMFunctionParameter id64Context; 263 HGCMFunctionParameter f32Formats; 264 } Msg; 265 266 VBGL_HGCM_HDR_INIT(&Msg.Hdr, pCtx->idClient, VBOX_SHCL_GUEST_FN_MSG_GET, 3); 267 Msg.id64Context.SetUInt64(VBOX_SHCL_HOST_MSG_FORMATS_REPORT); 268 Msg.f32Formats.SetUInt32(0); 269 270 int rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg)); 271 if (RT_SUCCESS(rc)) 272 { 273 rc = Msg.id64Context.GetUInt64(&pCtx->idContext); 274 AssertRC(rc); 275 int rc2 = Msg.f32Formats.GetUInt32(&pFormats->Formats); 276 AssertRCStmt(rc2, rc = rc2); 273 277 } 274 278 … … 283 287 * @returns VBox status code. 284 288 * @param pCtx Shared Clipboard command context to use for the connection. 285 * @param p DataReq Where to store the read data request from the host.286 */ 287 VBGLR3DECL(int) VbglR3ClipboardReadDataRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLDATAREQ pDataReq)289 * @param pfFormat Where to return the requested format. 290 */ 291 static int vbglR3ClipboardReadDataRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLFORMAT pfFormat) 288 292 { 289 293 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 290 AssertPtrReturn(p DataReq, VERR_INVALID_POINTER);291 292 VBoxShClReadDataReqMsg Msg;293 294 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,295 VBOX_SHCL_GUEST_FN_MSG_GET, VBOX_SHCL_CPARMS_READ_DATA_REQ);296 297 Msg.uContext.SetUInt64(VBOX_SHCL_HOST_MSG_READ_DATA);298 Msg.fFlags.SetUInt32(0); 299 Msg.uFormat.SetUInt32(0);300 Msg. cbSize.SetUInt32(0);301 302 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg)); 303 i f (RT_SUCCESS(rc))304 {305 rc = Msg.uContext.GetUInt64(&pCtx->idContext);306 if (RT_SUCCESS(rc))307 rc = Msg.uFormat.GetUInt32(&pDataReq->uFmt);308 i f (RT_SUCCESS(rc))309 rc = Msg.cbSize.GetUInt32(&pDataReq->cbSize);294 AssertPtrReturn(pfFormat, VERR_INVALID_POINTER); 295 296 struct 297 { 298 VBGLIOCHGCMCALL Hdr; 299 HGCMFunctionParameter id64Context; 300 HGCMFunctionParameter f32Format; 301 } Msg; 302 303 VBGL_HGCM_HDR_INIT(&Msg.Hdr, pCtx->idClient, VBOX_SHCL_GUEST_FN_MSG_GET, 2); 304 Msg.id64Context.SetUInt64(VBOX_SHCL_HOST_MSG_READ_DATA_CID); 305 Msg.f32Format.SetUInt32(0); 306 307 int rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg)); 308 if (RT_SUCCESS(rc)) 309 { 310 rc = Msg.id64Context.GetUInt64(&pCtx->idContext); 311 AssertRC(rc); 312 int rc2 = Msg.f32Format.GetUInt32(pfFormat); 313 AssertRCStmt(rc2, rc = rc2); 310 314 } 311 315 … … 332 336 VBoxShClGetHostMsgOld Msg; 333 337 334 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, 335 VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT, VBOX_SHCL_CPARMS_GET_HOST_MSG_OLD); 336 338 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT, VBOX_SHCL_CPARMS_GET_HOST_MSG_OLD); 337 339 VbglHGCMParmUInt32Set(&Msg.msg, 0); 338 340 VbglHGCMParmUInt32Set(&Msg.formats, 0); … … 466 468 * Peeks at the next host message, waiting for one to turn up. 467 469 * 470 * This glosses over the difference between new (6.1) and old (1.3.2) host 471 * service versions, however it does so by abusing @a pcParameters, so don't use 472 * it directly when in legacy mode, always pass it on to 473 * VbglR3ClipboardEventGetNext() or VbglR3ClipboardEventGetNextEx(). 474 * 468 475 * @returns VBox status code. 469 476 * @retval VERR_INTERRUPTED if interrupted. Does the necessary cleanup, so … … 485 492 AssertPtrReturn(pcParameters, VERR_INVALID_POINTER); 486 493 487 int rc;488 489 494 struct 490 495 { … … 493 498 HGCMFunctionParameter cParameters; 494 499 } Msg; 495 VBGL_HGCM_HDR_INIT(&Msg.Hdr, pCtx->idClient, VBOX_SHCL_GUEST_FN_MSG_PEEK_WAIT, 2); 496 VbglHGCMParmUInt64Set(&Msg.idMsg, pidRestoreCheck ? *pidRestoreCheck : 0); 497 VbglHGCMParmUInt32Set(&Msg.cParameters, 0); 498 rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg)); 499 LogFlowFunc(("VbglR3HGCMCall -> %Rrc\n", rc)); 500 if (RT_SUCCESS(rc)) 501 { 502 AssertMsgReturn( Msg.idMsg.type == VMMDevHGCMParmType_64bit 503 && Msg.cParameters.type == VMMDevHGCMParmType_32bit, 504 ("msg.type=%d num_parms.type=%d\n", Msg.idMsg.type, Msg.cParameters.type), 505 VERR_INTERNAL_ERROR_3); 506 507 *pidMsg = (uint32_t)Msg.idMsg.u.value64; 508 *pcParameters = Msg.cParameters.u.value32; 509 return rc; 500 int rc; 501 if (!pCtx->fUseLegacyProtocol) 502 { 503 VBGL_HGCM_HDR_INIT(&Msg.Hdr, pCtx->idClient, VBOX_SHCL_GUEST_FN_MSG_PEEK_WAIT, 2); 504 VbglHGCMParmUInt64Set(&Msg.idMsg, pidRestoreCheck ? *pidRestoreCheck : 0); 505 VbglHGCMParmUInt32Set(&Msg.cParameters, 0); 506 rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg)); 507 LogFlowFunc(("VbglR3HGCMCall -> %Rrc\n", rc)); 508 if (RT_SUCCESS(rc)) 509 { 510 AssertMsgReturn( Msg.idMsg.type == VMMDevHGCMParmType_64bit 511 && Msg.cParameters.type == VMMDevHGCMParmType_32bit, 512 ("msg.type=%d num_parms.type=%d\n", Msg.idMsg.type, Msg.cParameters.type), 513 VERR_INTERNAL_ERROR_3); 514 515 *pidMsg = (uint32_t)Msg.idMsg.u.value64; 516 *pcParameters = Msg.cParameters.u.value32; 517 return rc; 518 } 519 520 /* 521 * If restored, update pidRestoreCheck. 522 */ 523 if (rc == VERR_VM_RESTORED && pidRestoreCheck) 524 *pidRestoreCheck = Msg.idMsg.u.value64; 525 } 526 else 527 { 528 /* 529 * We do some crude stuff here by putting the 2nd parameter (foramts) in the parameter count, 530 * however it's supposed to be passed directly to VbglR3ClipboardEventGetNext or 531 * VbglR3ClipboardEventGetNextEx, so that's fine... 532 */ 533 rc = VbglR3ClipboardGetHostMsgOld(pCtx->idClient, pidMsg, pcParameters); 534 if (RT_SUCCESS(rc)) 535 return rc; 510 536 } 511 537 … … 519 545 AssertRC(rc2); 520 546 } 521 522 /*523 * If restored, update pidRestoreCheck.524 */525 if (rc == VERR_VM_RESTORED && pidRestoreCheck)526 *pidRestoreCheck = Msg.idMsg.u.value64;527 547 528 548 *pidMsg = UINT32_MAX - 1; … … 1922 1942 1923 1943 int rc; 1924 1925 bool fErrorSent = false; /* Whether an error has been reported back to the host already. */ 1926 1927 switch (idMsg) 1928 { 1929 case VBOX_SHCL_HOST_MSG_TRANSFER_STATUS: 1944 if (!pCmdCtx->fUseLegacyProtocol) 1945 { 1946 bool fErrorSent = false; /* Whether an error has been reported back to the host already. */ 1947 1948 switch (idMsg) 1930 1949 { 1931 SHCLTRANSFERDIR enmDir; 1932 SHCLTRANSFERREPORT transferReport; 1933 rc = VbglR3ClipboarTransferStatusRecv(pCmdCtx, &enmDir, &transferReport); 1934 if (RT_SUCCESS(rc)) 1950 case VBOX_SHCL_HOST_MSG_TRANSFER_STATUS: 1935 1951 { 1936 const SHCLTRANSFERID uTransferID = VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->uContextID); 1937 1938 LogFlowFunc(("[Transfer %RU16] enmDir=%RU32, status=%s\n", 1939 uTransferID, enmDir, ShClTransferStatusToStr(transferReport.uStatus))); 1940 1941 switch (transferReport.uStatus) 1942 { 1943 case SHCLTRANSFERSTATUS_INITIALIZED: 1944 RT_FALL_THROUGH(); 1945 case SHCLTRANSFERSTATUS_STARTED: 1946 { 1947 SHCLSOURCE enmSource = SHCLSOURCE_INVALID; 1948 1949 /* The host announces the transfer direction from its point of view, so inverse the direction here. */ 1950 if (enmDir == SHCLTRANSFERDIR_TO_REMOTE) 1951 { 1952 enmDir = SHCLTRANSFERDIR_FROM_REMOTE; 1953 enmSource = SHCLSOURCE_REMOTE; 1954 } 1955 else if (enmDir == SHCLTRANSFERDIR_FROM_REMOTE) 1956 { 1957 enmDir = SHCLTRANSFERDIR_TO_REMOTE; 1958 enmSource = SHCLSOURCE_LOCAL; 1959 } 1960 else 1961 AssertFailedBreakStmt(rc = VERR_INVALID_PARAMETER); 1962 1963 rc = vbglR3ClipboardTransferStart(pCmdCtx, pTransferCtx, uTransferID, 1964 enmDir, enmSource, NULL /* ppTransfer */); 1965 break; 1966 } 1967 1968 case SHCLTRANSFERSTATUS_STOPPED: 1969 RT_FALL_THROUGH(); 1970 case SHCLTRANSFERSTATUS_CANCELED: 1971 RT_FALL_THROUGH(); 1972 case SHCLTRANSFERSTATUS_KILLED: 1973 RT_FALL_THROUGH(); 1974 case SHCLTRANSFERSTATUS_ERROR: 1975 { 1976 rc = vbglR3ClipboardTransferStop(pCmdCtx, pTransferCtx, 1977 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->uContextID)); 1978 break; 1979 } 1980 1981 default: 1982 rc = VERR_NOT_SUPPORTED; 1983 break; 1984 } 1985 1952 SHCLTRANSFERDIR enmDir; 1953 SHCLTRANSFERREPORT transferReport; 1954 rc = VbglR3ClipboarTransferStatusRecv(pCmdCtx, &enmDir, &transferReport); 1986 1955 if (RT_SUCCESS(rc)) 1987 1956 { 1988 pEvent->u.TransferStatus.enmDir = enmDir; 1989 pEvent->u.TransferStatus.Report = transferReport; 1990 pEvent->u.TransferStatus.uID = VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->uContextID); 1991 1992 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_TRANSFER_STATUS; 1993 1994 LogRel2(("Shared Clipboard: Received status %s (rc=%Rrc) for transfer ID=%RU16\n", 1995 ShClTransferStatusToStr(pEvent->u.TransferStatus.Report.uStatus), pEvent->u.TransferStatus.Report.rc, 1996 pEvent->u.TransferStatus.uID)); 1957 const SHCLTRANSFERID uTransferID = VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->uContextID); 1958 1959 LogFlowFunc(("[Transfer %RU16] enmDir=%RU32, status=%s\n", 1960 uTransferID, enmDir, ShClTransferStatusToStr(transferReport.uStatus))); 1961 1962 switch (transferReport.uStatus) 1963 { 1964 case SHCLTRANSFERSTATUS_INITIALIZED: 1965 RT_FALL_THROUGH(); 1966 case SHCLTRANSFERSTATUS_STARTED: 1967 { 1968 SHCLSOURCE enmSource = SHCLSOURCE_INVALID; 1969 1970 /* The host announces the transfer direction from its point of view, so inverse the direction here. */ 1971 if (enmDir == SHCLTRANSFERDIR_TO_REMOTE) 1972 { 1973 enmDir = SHCLTRANSFERDIR_FROM_REMOTE; 1974 enmSource = SHCLSOURCE_REMOTE; 1975 } 1976 else if (enmDir == SHCLTRANSFERDIR_FROM_REMOTE) 1977 { 1978 enmDir = SHCLTRANSFERDIR_TO_REMOTE; 1979 enmSource = SHCLSOURCE_LOCAL; 1980 } 1981 else 1982 AssertFailedBreakStmt(rc = VERR_INVALID_PARAMETER); 1983 1984 rc = vbglR3ClipboardTransferStart(pCmdCtx, pTransferCtx, uTransferID, 1985 enmDir, enmSource, NULL /* ppTransfer */); 1986 break; 1987 } 1988 1989 case SHCLTRANSFERSTATUS_STOPPED: 1990 RT_FALL_THROUGH(); 1991 case SHCLTRANSFERSTATUS_CANCELED: 1992 RT_FALL_THROUGH(); 1993 case SHCLTRANSFERSTATUS_KILLED: 1994 RT_FALL_THROUGH(); 1995 case SHCLTRANSFERSTATUS_ERROR: 1996 { 1997 rc = vbglR3ClipboardTransferStop(pCmdCtx, pTransferCtx, 1998 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->uContextID)); 1999 break; 2000 } 2001 2002 default: 2003 rc = VERR_NOT_SUPPORTED; 2004 break; 2005 } 2006 2007 if (RT_SUCCESS(rc)) 2008 { 2009 pEvent->u.TransferStatus.enmDir = enmDir; 2010 pEvent->u.TransferStatus.Report = transferReport; 2011 pEvent->u.TransferStatus.uID = VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->uContextID); 2012 2013 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_TRANSFER_STATUS; 2014 2015 LogRel2(("Shared Clipboard: Received status %s (rc=%Rrc) for transfer ID=%RU16\n", 2016 ShClTransferStatusToStr(pEvent->u.TransferStatus.Report.uStatus), pEvent->u.TransferStatus.Report.rc, 2017 pEvent->u.TransferStatus.uID)); 2018 } 1997 2019 } 2020 break; 1998 2021 } 1999 break; 2000 } 2001 2002 case VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_HDR_READ: 2003 { 2004 uint32_t fRoots; 2005 rc = VbglR3ClipboardRootListHdrReadReq(pCmdCtx, &fRoots); 2006 2007 /** @todo Validate / handle fRoots. */ 2008 2009 if (RT_SUCCESS(rc)) 2022 2023 case VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_HDR_READ: 2010 2024 { 2011 PSHCLTRANSFER pTransfer = ShClTransferCtxGetTransfer(pTransferCtx, 2012 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->uContextID)); 2013 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND); 2014 2015 SHCLROOTLISTHDR rootListHdr; 2016 RT_ZERO(rootListHdr); 2017 2018 rootListHdr.cRoots = ShClTransferRootsCount(pTransfer); 2019 2020 LogFlowFunc(("cRoots=%RU32\n", rootListHdr.cRoots)); 2021 2022 rc = VbglR3ClipboardRootListHdrReadReply(pCmdCtx, &rootListHdr); 2025 uint32_t fRoots; 2026 rc = VbglR3ClipboardRootListHdrReadReq(pCmdCtx, &fRoots); 2027 2028 /** @todo Validate / handle fRoots. */ 2029 2030 if (RT_SUCCESS(rc)) 2031 { 2032 PSHCLTRANSFER pTransfer = ShClTransferCtxGetTransfer(pTransferCtx, 2033 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->uContextID)); 2034 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND); 2035 2036 SHCLROOTLISTHDR rootListHdr; 2037 RT_ZERO(rootListHdr); 2038 2039 rootListHdr.cRoots = ShClTransferRootsCount(pTransfer); 2040 2041 LogFlowFunc(("cRoots=%RU32\n", rootListHdr.cRoots)); 2042 2043 rc = VbglR3ClipboardRootListHdrReadReply(pCmdCtx, &rootListHdr); 2044 } 2045 break; 2023 2046 } 2024 break; 2025 } 2026 2027 case VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_ENTRY_READ: 2028 { 2029 uint32_t uIndex; 2030 uint32_t fInfo; 2031 rc = VbglR3ClipboardRootListEntryReadReq(pCmdCtx, &uIndex, &fInfo); 2032 if (RT_SUCCESS(rc)) 2047 2048 case VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_ENTRY_READ: 2033 2049 { 2034 PSHCLTRANSFER pTransfer = ShClTransferCtxGetTransfer(pTransferCtx, 2035 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->uContextID)); 2036 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND); 2037 2038 SHCLROOTLISTENTRY rootListEntry; 2039 rc = ShClTransferRootsEntry(pTransfer, uIndex, &rootListEntry); 2040 if (RT_SUCCESS(rc)) 2041 rc = VbglR3ClipboardRootListEntryReadReply(pCmdCtx, uIndex, &rootListEntry); 2042 } 2043 break; 2044 } 2045 2046 case VBOX_SHCL_HOST_MSG_TRANSFER_LIST_OPEN: 2047 { 2048 SHCLLISTOPENPARMS openParmsList; 2049 rc = ShClTransferListOpenParmsInit(&openParmsList); 2050 if (RT_SUCCESS(rc)) 2051 { 2052 rc = VbglR3ClipboardListOpenRecv(pCmdCtx, &openParmsList); 2050 uint32_t uIndex; 2051 uint32_t fInfo; 2052 rc = VbglR3ClipboardRootListEntryReadReq(pCmdCtx, &uIndex, &fInfo); 2053 2053 if (RT_SUCCESS(rc)) 2054 2054 { … … 2057 2057 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND); 2058 2058 2059 LogFlowFunc(("pszPath=%s\n", openParmsList.pszPath)); 2060 2061 SHCLLISTHANDLE hList = SHCLLISTHANDLE_INVALID; 2062 rc = ShClTransferListOpen(pTransfer, &openParmsList, &hList); 2063 2064 /* Reply in any case. */ 2065 int rc2 = VbglR3ClipboardListOpenReply(pCmdCtx, rc, hList); 2066 AssertRC(rc2); 2059 SHCLROOTLISTENTRY rootListEntry; 2060 rc = ShClTransferRootsEntry(pTransfer, uIndex, &rootListEntry); 2061 if (RT_SUCCESS(rc)) 2062 rc = VbglR3ClipboardRootListEntryReadReply(pCmdCtx, uIndex, &rootListEntry); 2067 2063 } 2068 2069 ShClTransferListOpenParmsDestroy(&openParmsList); 2064 break; 2070 2065 } 2071 2066 2072 break; 2073 } 2074 2075 case VBOX_SHCL_HOST_MSG_TRANSFER_LIST_CLOSE: 2076 { 2077 SHCLLISTHANDLE hList; 2078 rc = VbglR3ClipboardListCloseRecv(pCmdCtx, &hList); 2079 if (RT_SUCCESS(rc)) 2067 case VBOX_SHCL_HOST_MSG_TRANSFER_LIST_OPEN: 2080 2068 { 2081 PSHCLTRANSFER pTransfer = ShClTransferCtxGetTransfer(pTransferCtx, 2082 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->uContextID)); 2083 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND); 2084 2085 rc = ShClTransferListClose(pTransfer, hList); 2086 2087 /* Reply in any case. */ 2088 int rc2 = VbglR3ClipboardListCloseReply(pCmdCtx, rc, hList); 2089 AssertRC(rc2); 2090 } 2091 2092 break; 2093 } 2094 2095 case VBOX_SHCL_HOST_MSG_TRANSFER_LIST_HDR_READ: 2096 { 2097 /** @todo Handle filter + list features. */ 2098 2099 SHCLLISTHANDLE hList = SHCLLISTHANDLE_INVALID; 2100 uint32_t fFlags = 0; 2101 rc = VbglR3ClipboardListHdrReadRecvReq(pCmdCtx, &hList, &fFlags); 2102 if (RT_SUCCESS(rc)) 2103 { 2104 PSHCLTRANSFER pTransfer = ShClTransferCtxGetTransfer(pTransferCtx, 2105 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->uContextID)); 2106 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND); 2107 2108 SHCLLISTHDR hdrList; 2109 rc = ShClTransferListGetHeader(pTransfer, hList, &hdrList); 2069 SHCLLISTOPENPARMS openParmsList; 2070 rc = ShClTransferListOpenParmsInit(&openParmsList); 2110 2071 if (RT_SUCCESS(rc)) 2111 2072 { 2112 rc = VbglR3ClipboardListHdrWrite(pCmdCtx, hList, &hdrList); 2113 2114 ShClTransferListHdrDestroy(&hdrList); 2073 rc = VbglR3ClipboardListOpenRecv(pCmdCtx, &openParmsList); 2074 if (RT_SUCCESS(rc)) 2075 { 2076 PSHCLTRANSFER pTransfer = ShClTransferCtxGetTransfer(pTransferCtx, 2077 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->uContextID)); 2078 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND); 2079 2080 LogFlowFunc(("pszPath=%s\n", openParmsList.pszPath)); 2081 2082 SHCLLISTHANDLE hList = SHCLLISTHANDLE_INVALID; 2083 rc = ShClTransferListOpen(pTransfer, &openParmsList, &hList); 2084 2085 /* Reply in any case. */ 2086 int rc2 = VbglR3ClipboardListOpenReply(pCmdCtx, rc, hList); 2087 AssertRC(rc2); 2088 } 2089 2090 ShClTransferListOpenParmsDestroy(&openParmsList); 2115 2091 } 2092 2093 break; 2116 2094 } 2117 2095 2118 break; 2119 } 2120 2121 case VBOX_SHCL_HOST_MSG_TRANSFER_LIST_ENTRY_READ: 2122 { 2123 LogFlowFunc(("VBOX_SHCL_HOST_MSG_TRANSFER_LIST_ENTRY_READ\n")); 2124 2125 SHCLLISTENTRY entryList; 2126 rc = ShClTransferListEntryInit(&entryList); 2127 if (RT_SUCCESS(rc)) 2096 case VBOX_SHCL_HOST_MSG_TRANSFER_LIST_CLOSE: 2128 2097 { 2129 2098 SHCLLISTHANDLE hList; 2130 uint32_t fInfo; 2131 rc = VbglR3ClipboardListEntryReadRecvReq(pCmdCtx, &hList, &fInfo); 2099 rc = VbglR3ClipboardListCloseRecv(pCmdCtx, &hList); 2132 2100 if (RT_SUCCESS(rc)) 2133 2101 { … … 2136 2104 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND); 2137 2105 2138 rc = ShClTransferListRead(pTransfer, hList, &entryList); 2139 if (RT_SUCCESS(rc)) 2140 { 2141 PSHCLFSOBJINFO pObjInfo = (PSHCLFSOBJINFO)entryList.pvInfo; 2142 Assert(entryList.cbInfo == sizeof(SHCLFSOBJINFO)); 2143 2144 RT_NOREF(pObjInfo); 2145 2146 LogFlowFunc(("\t%s (%RU64 bytes)\n", entryList.pszName, pObjInfo->cbObject)); 2147 2148 rc = VbglR3ClipboardListEntryWrite(pCmdCtx, hList, &entryList); 2149 } 2106 rc = ShClTransferListClose(pTransfer, hList); 2107 2108 /* Reply in any case. */ 2109 int rc2 = VbglR3ClipboardListCloseReply(pCmdCtx, rc, hList); 2110 AssertRC(rc2); 2150 2111 } 2151 2112 2152 ShClTransferListEntryDestroy(&entryList);2113 break; 2153 2114 } 2154 2115 2155 break; 2156 } 2157 2158 case VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_OPEN: 2159 { 2160 SHCLOBJOPENCREATEPARMS openParms; 2161 rc = ShClTransferObjOpenParmsInit(&openParms); 2162 if (RT_SUCCESS(rc)) 2116 case VBOX_SHCL_HOST_MSG_TRANSFER_LIST_HDR_READ: 2163 2117 { 2164 rc = VbglR3ClipboardObjOpenRecv(pCmdCtx, &openParms); 2118 /** @todo Handle filter + list features. */ 2119 2120 SHCLLISTHANDLE hList = SHCLLISTHANDLE_INVALID; 2121 uint32_t fFlags = 0; 2122 rc = VbglR3ClipboardListHdrReadRecvReq(pCmdCtx, &hList, &fFlags); 2165 2123 if (RT_SUCCESS(rc)) 2166 2124 { … … 2169 2127 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND); 2170 2128 2171 SHCLOBJHANDLE hObj; 2172 rc = ShClTransferObjOpen(pTransfer, &openParms, &hObj); 2129 SHCLLISTHDR hdrList; 2130 rc = ShClTransferListGetHeader(pTransfer, hList, &hdrList); 2131 if (RT_SUCCESS(rc)) 2132 { 2133 rc = VbglR3ClipboardListHdrWrite(pCmdCtx, hList, &hdrList); 2134 2135 ShClTransferListHdrDestroy(&hdrList); 2136 } 2137 } 2138 2139 break; 2140 } 2141 2142 case VBOX_SHCL_HOST_MSG_TRANSFER_LIST_ENTRY_READ: 2143 { 2144 LogFlowFunc(("VBOX_SHCL_HOST_MSG_TRANSFER_LIST_ENTRY_READ\n")); 2145 2146 SHCLLISTENTRY entryList; 2147 rc = ShClTransferListEntryInit(&entryList); 2148 if (RT_SUCCESS(rc)) 2149 { 2150 SHCLLISTHANDLE hList; 2151 uint32_t fInfo; 2152 rc = VbglR3ClipboardListEntryReadRecvReq(pCmdCtx, &hList, &fInfo); 2153 if (RT_SUCCESS(rc)) 2154 { 2155 PSHCLTRANSFER pTransfer = ShClTransferCtxGetTransfer(pTransferCtx, 2156 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->uContextID)); 2157 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND); 2158 2159 rc = ShClTransferListRead(pTransfer, hList, &entryList); 2160 if (RT_SUCCESS(rc)) 2161 { 2162 PSHCLFSOBJINFO pObjInfo = (PSHCLFSOBJINFO)entryList.pvInfo; 2163 Assert(entryList.cbInfo == sizeof(SHCLFSOBJINFO)); 2164 2165 RT_NOREF(pObjInfo); 2166 2167 LogFlowFunc(("\t%s (%RU64 bytes)\n", entryList.pszName, pObjInfo->cbObject)); 2168 2169 rc = VbglR3ClipboardListEntryWrite(pCmdCtx, hList, &entryList); 2170 } 2171 } 2172 2173 ShClTransferListEntryDestroy(&entryList); 2174 } 2175 2176 break; 2177 } 2178 2179 case VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_OPEN: 2180 { 2181 SHCLOBJOPENCREATEPARMS openParms; 2182 rc = ShClTransferObjOpenParmsInit(&openParms); 2183 if (RT_SUCCESS(rc)) 2184 { 2185 rc = VbglR3ClipboardObjOpenRecv(pCmdCtx, &openParms); 2186 if (RT_SUCCESS(rc)) 2187 { 2188 PSHCLTRANSFER pTransfer = ShClTransferCtxGetTransfer(pTransferCtx, 2189 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->uContextID)); 2190 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND); 2191 2192 SHCLOBJHANDLE hObj; 2193 rc = ShClTransferObjOpen(pTransfer, &openParms, &hObj); 2194 2195 /* Reply in any case. */ 2196 int rc2 = VbglR3ClipboardObjOpenReply(pCmdCtx, rc, hObj); 2197 AssertRC(rc2); 2198 } 2199 2200 ShClTransferObjOpenParmsDestroy(&openParms); 2201 } 2202 2203 break; 2204 } 2205 2206 case VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_CLOSE: 2207 { 2208 SHCLOBJHANDLE hObj; 2209 rc = VbglR3ClipboardObjCloseRecv(pCmdCtx, &hObj); 2210 if (RT_SUCCESS(rc)) 2211 { 2212 PSHCLTRANSFER pTransfer = ShClTransferCtxGetTransfer(pTransferCtx, 2213 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->uContextID)); 2214 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND); 2215 2216 rc = ShClTransferObjClose(pTransfer, hObj); 2173 2217 2174 2218 /* Reply in any case. */ 2175 int rc2 = VbglR3ClipboardObj OpenReply(pCmdCtx, rc, hObj);2219 int rc2 = VbglR3ClipboardObjCloseReply(pCmdCtx, rc, hObj); 2176 2220 AssertRC(rc2); 2177 2221 } 2178 2222 2179 ShClTransferObjOpenParmsDestroy(&openParms);2223 break; 2180 2224 } 2181 2225 2182 break; 2226 case VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_READ: 2227 { 2228 SHCLOBJHANDLE hObj; 2229 uint32_t cbBuf; 2230 uint32_t fFlags; 2231 rc = VbglR3ClipboardObjReadRecv(pCmdCtx, &hObj, &cbBuf, &fFlags); 2232 if (RT_SUCCESS(rc)) 2233 { 2234 PSHCLTRANSFER pTransfer = ShClTransferCtxGetTransfer(pTransferCtx, 2235 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->uContextID)); 2236 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND); 2237 2238 AssertBreakStmt(pCmdCtx->cbChunkSize, rc = VERR_INVALID_PARAMETER); 2239 2240 const uint32_t cbToRead = RT_MIN(cbBuf, pCmdCtx->cbChunkSize); 2241 2242 LogFlowFunc(("hObj=%RU64, cbBuf=%RU32, fFlags=0x%x -> cbChunkSize=%RU32, cbToRead=%RU32\n", 2243 hObj, cbBuf, fFlags, pCmdCtx->cbChunkSize, cbToRead)); 2244 2245 void *pvBuf = RTMemAlloc(cbToRead); 2246 if (pvBuf) 2247 { 2248 uint32_t cbRead; 2249 rc = ShClTransferObjRead(pTransfer, hObj, pvBuf, cbToRead, &cbRead, fFlags); 2250 if (RT_SUCCESS(rc)) 2251 rc = VbglR3ClipboardObjWriteSend(pCmdCtx, hObj, pvBuf, cbRead, NULL /* pcbWritten */); 2252 2253 RTMemFree(pvBuf); 2254 } 2255 else 2256 rc = VERR_NO_MEMORY; 2257 } 2258 2259 break; 2260 } 2261 2262 default: 2263 { 2264 rc = VbglR3ClipboardEventGetNext(idMsg, cParms, pCmdCtx, pEvent); 2265 if (RT_FAILURE(rc)) 2266 fErrorSent = true; 2267 break; 2268 } 2183 2269 } 2184 2270 2185 case VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_CLOSE: 2271 if ( !fErrorSent 2272 && RT_FAILURE(rc)) 2186 2273 { 2187 SHCLOBJHANDLE hObj; 2188 rc = VbglR3ClipboardObjCloseRecv(pCmdCtx, &hObj); 2189 if (RT_SUCCESS(rc)) 2190 { 2191 PSHCLTRANSFER pTransfer = ShClTransferCtxGetTransfer(pTransferCtx, 2192 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->uContextID)); 2193 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND); 2194 2195 rc = ShClTransferObjClose(pTransfer, hObj); 2196 2197 /* Reply in any case. */ 2198 int rc2 = VbglR3ClipboardObjCloseReply(pCmdCtx, rc, hObj); 2199 AssertRC(rc2); 2200 } 2201 2202 break; 2274 /* Report error back to the host. */ 2275 int rc2 = VbglR3ClipboardWriteError(pCmdCtx->uClientID, rc); 2276 AssertRC(rc2); 2203 2277 } 2204 2205 case VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_READ: 2278 } 2279 else 2280 { 2281 /* 2282 * This builds on what we did in VbglR3ClipboardMsgPeekWait, so 2283 * !HACK ALERT! cParms is the format flag or flags. 2284 */ 2285 rc = VINF_SUCCESS; 2286 switch (idMsg) 2206 2287 { 2207 SHCLOBJHANDLE hObj; 2208 uint32_t cbBuf; 2209 uint32_t fFlags; 2210 rc = VbglR3ClipboardObjReadRecv(pCmdCtx, &hObj, &cbBuf, &fFlags); 2211 if (RT_SUCCESS(rc)) 2212 { 2213 PSHCLTRANSFER pTransfer = ShClTransferCtxGetTransfer(pTransferCtx, 2214 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->uContextID)); 2215 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND); 2216 2217 AssertBreakStmt(pCmdCtx->cbChunkSize, rc = VERR_INVALID_PARAMETER); 2218 2219 const uint32_t cbToRead = RT_MIN(cbBuf, pCmdCtx->cbChunkSize); 2220 2221 LogFlowFunc(("hObj=%RU64, cbBuf=%RU32, fFlags=0x%x -> cbChunkSize=%RU32, cbToRead=%RU32\n", 2222 hObj, cbBuf, fFlags, pCmdCtx->cbChunkSize, cbToRead)); 2223 2224 void *pvBuf = RTMemAlloc(cbToRead); 2225 if (pvBuf) 2226 { 2227 uint32_t cbRead; 2228 rc = ShClTransferObjRead(pTransfer, hObj, pvBuf, cbToRead, &cbRead, fFlags); 2229 if (RT_SUCCESS(rc)) 2230 rc = VbglR3ClipboardObjWriteSend(pCmdCtx, hObj, pvBuf, cbRead, NULL /* pcbWritten */); 2231 2232 RTMemFree(pvBuf); 2233 } 2234 else 2235 rc = VERR_NO_MEMORY; 2236 } 2237 2238 break; 2288 case VBOX_SHCL_HOST_MSG_FORMATS_REPORT: 2289 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_REPORT_FORMATS; 2290 pEvent->u.ReportedFormats.Formats = cParms; 2291 break; 2292 2293 case VBOX_SHCL_HOST_MSG_READ_DATA: 2294 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_READ_DATA; 2295 pEvent->u.fReadData = cParms; 2296 break; 2297 2298 case VBOX_SHCL_HOST_MSG_QUIT: 2299 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_QUIT; 2300 break; 2301 2302 default: 2303 AssertMsgFailed(("%u (%#x)\n", idMsg, idMsg)); 2304 rc = VERR_NOT_SUPPORTED; 2305 break; 2239 2306 } 2240 2241 default:2242 {2243 rc = VbglR3ClipboardEventGetNext(idMsg, cParms, pCmdCtx, pEvent);2244 if (RT_FAILURE(rc))2245 fErrorSent = true;2246 break;2247 }2248 }2249 2250 if ( !fErrorSent2251 && RT_FAILURE(rc))2252 {2253 /* Report error back to the host. */2254 int rc2 = VbglR3ClipboardWriteError(pCmdCtx->uClientID, rc);2255 AssertRC(rc2);2256 2307 } 2257 2308 … … 2262 2313 #endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */ 2263 2314 2264 VBGLR3DECL(int) VbglR3ClipboardEventGetNext(uint32_t idMsg, uint32_t cParms, 2265 PVBGLR3SHCLCMDCTX pCtx, PVBGLR3CLIPBOARDEVENT pEvent) 2315 VBGLR3DECL(int) VbglR3ClipboardEventGetNext(uint32_t idMsg, uint32_t cParms, PVBGLR3SHCLCMDCTX pCtx, PVBGLR3CLIPBOARDEVENT pEvent) 2266 2316 { 2267 2317 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); … … 2271 2321 2272 2322 int rc; 2273 2274 #ifdef LOG_ENABLED 2275 LogFunc(("Handling idMsg=%RU32 (%s)\n", idMsg, ShClHostMsgToStr(idMsg))); 2276 #endif 2277 switch (idMsg) 2278 { 2279 case VBOX_SHCL_HOST_MSG_FORMATS_REPORT: 2323 if (!pCtx->fUseLegacyProtocol) 2324 { 2325 LogFunc(("Handling idMsg=%RU32 (%s)\n", idMsg, ShClHostMsgToStr(idMsg))); 2326 switch (idMsg) 2280 2327 { 2281 rc = VbglR3ClipboardFormatsReportRecv(pCtx, &pEvent->u.ReportedFormats); 2282 if (RT_SUCCESS(rc)) 2328 case VBOX_SHCL_HOST_MSG_FORMATS_REPORT: 2329 { 2330 rc = vbglR3ClipboardFormatsReportRecv(pCtx, &pEvent->u.ReportedFormats); 2331 if (RT_SUCCESS(rc)) 2332 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_REPORT_FORMATS; 2333 break; 2334 } 2335 2336 case VBOX_SHCL_HOST_MSG_READ_DATA: 2337 { 2338 rc = vbglR3ClipboardReadDataRecv(pCtx, &pEvent->u.fReadData); 2339 if (RT_SUCCESS(rc)) 2340 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_READ_DATA; 2341 break; 2342 } 2343 2344 case VBOX_SHCL_HOST_MSG_QUIT: 2345 { 2346 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_QUIT; 2347 rc = VINF_SUCCESS; 2348 break; 2349 } 2350 2351 default: 2352 { 2353 rc = VERR_NOT_SUPPORTED; 2354 break; 2355 } 2356 } 2357 2358 if (RT_SUCCESS(rc)) 2359 { 2360 /* Copy over our command context to the event. */ 2361 pEvent->cmdCtx = *pCtx; 2362 } 2363 else 2364 { 2365 /* Report error back to the host. */ 2366 int rc2 = VbglR3ClipboardWriteError(pCtx->idClient, rc); 2367 AssertRC(rc2); 2368 } 2369 } 2370 else 2371 { 2372 /* 2373 * This builds on what we did in VbglR3ClipboardMsgPeekWait, so 2374 * !HACK ALERT! cParms is the format flag or flags. 2375 */ 2376 rc = VINF_SUCCESS; 2377 switch (idMsg) 2378 { 2379 case VBOX_SHCL_HOST_MSG_FORMATS_REPORT: 2283 2380 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_REPORT_FORMATS; 2284 break; 2381 pEvent->u.ReportedFormats.Formats = cParms; 2382 break; 2383 2384 case VBOX_SHCL_HOST_MSG_READ_DATA: 2385 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_READ_DATA; 2386 pEvent->u.fReadData = cParms; 2387 break; 2388 2389 case VBOX_SHCL_HOST_MSG_QUIT: 2390 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_QUIT; 2391 break; 2392 2393 default: 2394 AssertMsgFailed(("%u (%#x)\n", idMsg, idMsg)); 2395 rc = VERR_NOT_SUPPORTED; 2396 break; 2285 2397 } 2286 2287 case VBOX_SHCL_HOST_MSG_READ_DATA:2288 {2289 rc = VbglR3ClipboardReadDataRecv(pCtx, &pEvent->u.ReadData);2290 if (RT_SUCCESS(rc))2291 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_READ_DATA;2292 break;2293 }2294 2295 case VBOX_SHCL_HOST_MSG_QUIT:2296 {2297 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_QUIT;2298 rc = VINF_SUCCESS;2299 break;2300 }2301 2302 default:2303 {2304 rc = VERR_NOT_SUPPORTED;2305 break;2306 }2307 }2308 2309 if (RT_SUCCESS(rc))2310 {2311 /* Copy over our command context to the event. */2312 pEvent->cmdCtx = *pCtx;2313 }2314 else2315 {2316 /* Report error back to the host. */2317 int rc2 = VbglR3ClipboardWriteError(pCtx->idClient, rc);2318 AssertRC(rc2);2319 2398 } 2320 2399 -
trunk/src/VBox/Additions/x11/VBoxClient/clipboard.cpp
r82525 r82527 276 276 for (;;) 277 277 { 278 PVBGLR3CLIPBOARDEVENT pEvent = NULL; 278 PVBGLR3CLIPBOARDEVENT pEvent = (PVBGLR3CLIPBOARDEVENT)RTMemAllocZ(sizeof(VBGLR3CLIPBOARDEVENT)); 279 AssertPtrBreakStmt(pEvent, rc = VERR_NO_MEMORY); 279 280 280 281 LogFlowFunc(("Waiting for host message (fUseLegacyProtocol=%RTbool, fHostFeatures=%#RX64) ...\n", 281 282 pCtx->CmdCtx.fUseLegacyProtocol, pCtx->CmdCtx.fHostFeatures)); 282 283 283 if (pCtx->CmdCtx.fUseLegacyProtocol) 284 { 285 uint32_t uMsg; 286 uint32_t uFormats; 287 288 rc = VbglR3ClipboardGetHostMsgOld(pCtx->CmdCtx.idClient, &uMsg, &uFormats); 289 if (RT_FAILURE(rc)) 290 { 291 if (rc == VERR_INTERRUPTED) /** @todo r=bird: What on earth is the meaning of this?!?!?!?!?!?!? */ 292 break; 293 294 LogFunc(("Error getting host message, rc=%Rrc\n", rc)); 295 } 296 else 297 { 298 pEvent = (PVBGLR3CLIPBOARDEVENT)RTMemAllocZ(sizeof(VBGLR3CLIPBOARDEVENT)); 299 AssertPtrBreakStmt(pEvent, rc = VERR_NO_MEMORY); 300 301 switch (uMsg) 302 { 303 case VBOX_SHCL_HOST_MSG_FORMATS_REPORT: 304 { 305 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_REPORT_FORMATS; 306 pEvent->u.ReportedFormats.Formats = uFormats; 307 break; 308 } 309 310 case VBOX_SHCL_HOST_MSG_READ_DATA: 311 { 312 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_READ_DATA; 313 pEvent->u.ReadData.uFmt = uFormats; 314 break; 315 } 316 317 case VBOX_SHCL_HOST_MSG_QUIT: 318 { 319 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_QUIT; 320 break; 321 } 322 323 default: 324 rc = VERR_NOT_SUPPORTED; 325 break; 326 } 327 328 if (RT_SUCCESS(rc)) 329 { 330 /* Copy over our command context to the event. */ 331 pEvent->cmdCtx = pCtx->CmdCtx; 332 } 333 } 334 } 335 else /* Host service has peeking for messages support. */ 336 { 337 pEvent = (PVBGLR3CLIPBOARDEVENT)RTMemAllocZ(sizeof(VBGLR3CLIPBOARDEVENT)); 338 AssertPtrBreakStmt(pEvent, rc = VERR_NO_MEMORY); 339 340 uint32_t uMsg = 0; 341 uint32_t cParms = 0; 342 rc = VbglR3ClipboardMsgPeekWait(&pCtx->CmdCtx, &uMsg, &cParms, NULL /* pidRestoreCheck */); 343 if (RT_SUCCESS(rc)) 344 { 284 uint32_t idMsg = 0; 285 uint32_t cParms = 0; 286 rc = VbglR3ClipboardMsgPeekWait(&pCtx->CmdCtx, &idMsg, &cParms, NULL /* pidRestoreCheck */); 287 if (RT_SUCCESS(rc)) 288 { 345 289 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 346 rc = VbglR3ClipboardEventGetNextEx(uMsg, cParms, &pCtx->CmdCtx, &pCtx->TransferCtx, pEvent);290 rc = VbglR3ClipboardEventGetNextEx(idMsg, cParms, &pCtx->CmdCtx, &pCtx->TransferCtx, pEvent); 347 291 #else 348 rc = VbglR3ClipboardEventGetNext(uMsg, cParms, &pCtx->CmdCtx, pEvent); 349 #endif 350 } 292 rc = VbglR3ClipboardEventGetNext(idMsg, cParms, &pCtx->CmdCtx, pEvent); 293 #endif 351 294 } 352 295 … … 385 328 if (pReq) 386 329 { 387 pReq->Format = pEvent->u. ReadData.uFmt;330 pReq->Format = pEvent->u.fReadData; 388 331 ShClX11ReadDataFromX11(&g_Ctx.X11, pReq->Format, pReq); 389 332 } -
trunk/src/VBox/GuestHost/SharedClipboard/clipboard-common.cpp
r82526 r82527 89 89 } 90 90 91 #if 0 /* currently not used */ 91 92 /** 92 93 * Creates (initializes) an event. … … 94 95 * @returns VBox status code. 95 96 * @param pEvent Event to initialize. 96 * @param uIDEvent ID to use.97 */ 98 int ShClEventCreate(PSHCLEVENT pEvent, SHCLEVENTID uID)97 * @param idEvent Event ID to use. 98 */ 99 static int shClEventInit(PSHCLEVENT pEvent, SHCLEVENTID idEvent) 99 100 { 100 101 AssertPtrReturn(pEvent, VERR_INVALID_POINTER); 101 102 102 LogFlowFunc(("Event %RU32\n", uID));103 104 int rc = RTSemEvent Create(&pEvent->hEventSem);103 LogFlowFunc(("Event %RU32\n", idEvent)); 104 105 int rc = RTSemEventMultiCreate(&pEvent->hEvtMulSem); 105 106 if (RT_SUCCESS(rc)) 106 107 { 107 pEvent-> uID = uID;108 pEvent->idEvent = idEvent; 108 109 pEvent->pPayload = NULL; 109 110 } … … 111 112 return rc; 112 113 } 113 114 /** 115 * Destroys an event. 114 #endif 115 116 /** 117 * Destroys an event, but doesn't free the memory. 116 118 * 117 119 * @param pEvent Event to destroy. 118 120 */ 119 void ShClEventDestroy(PSHCLEVENT pEvent)121 static void shClEventTerm(PSHCLEVENT pEvent) 120 122 { 121 123 if (!pEvent) 122 124 return; 123 125 124 LogFlowFunc(("Event %RU32\n", pEvent-> uID));125 126 if (pEvent->hEv entSem != NIL_RTSEMEVENT)127 { 128 RTSemEvent Destroy(pEvent->hEventSem);129 pEvent->hEv entSem = NIL_RTSEMEVENT;126 LogFlowFunc(("Event %RU32\n", pEvent->idEvent)); 127 128 if (pEvent->hEvtMulSem != NIL_RTSEMEVENT) 129 { 130 RTSemEventMultiDestroy(pEvent->hEvtMulSem); 131 pEvent->hEvtMulSem = NIL_RTSEMEVENT; 130 132 } 131 133 132 134 ShClPayloadFree(pEvent->pPayload); 133 135 134 pEvent-> uID= 0;136 pEvent->idEvent = 0; 135 137 } 136 138 … … 151 153 pSource->uID = uID; 152 154 /* Choose a random event ID starting point. */ 153 pSource-> uEventIDNext = RTRandU32() % VBOX_SHCL_MAX_EVENTS;155 pSource->idNextEvent = RTRandU32Ex(1, VBOX_SHCL_MAX_EVENTS - 1); 154 156 155 157 LogFlowFuncLeaveRC(VINF_SUCCESS); … … 172 174 173 175 pSource->uID = UINT16_MAX; 174 pSource-> uEventIDNext= UINT32_MAX;176 pSource->idNextEvent = UINT32_MAX; 175 177 } 176 178 … … 190 192 RTListNodeRemove(&pEvIt->Node); 191 193 192 ShClEventDestroy(pEvIt);194 shClEventTerm(pEvIt); 193 195 194 196 RTMemFree(pEvIt); 195 197 pEvIt = NULL; 196 198 } 197 }198 199 /**200 * Generates a new event ID for a specific event source.201 *202 * @returns New event ID generated, or 0 on error.203 * @param pSource Event source to generate event for.204 */205 SHCLEVENTID ShClEventIDGenerate(PSHCLEVENTSOURCE pSource)206 {207 AssertPtrReturn(pSource, 0);208 209 LogFlowFunc(("uSource=%RU16: New event: %RU32\n", pSource->uID, pSource->uEventIDNext));210 211 pSource->uEventIDNext++;212 if (pSource->uEventIDNext == VBOX_SHCL_MAX_EVENTS)213 pSource->uEventIDNext = 0;214 215 return pSource->uEventIDNext;216 199 } 217 200 … … 223 206 * @param uID Event ID to get. 224 207 */ 225 inline PSHCLEVENT shclEventGet(PSHCLEVENTSOURCE pSource, SHCLEVENTID uID)226 { 227 PSHCLEVENT pEv It;228 RTListForEach(&pSource->lstEvents, pEv It, SHCLEVENT, Node)229 { 230 if (pEv It->uID == uID)231 return pEv It;208 DECLINLINE(PSHCLEVENT) shclEventGet(PSHCLEVENTSOURCE pSource, SHCLEVENTID idEvent) 209 { 210 PSHCLEVENT pEvent; 211 RTListForEach(&pSource->lstEvents, pEvent, SHCLEVENT, Node) 212 { 213 if (pEvent->idEvent == idEvent) 214 return pEvent; 232 215 } 233 216 234 217 return NULL; 218 } 219 220 /** 221 * Generates a new event ID for a specific event source. 222 * 223 * @returns New event ID generated, or 0 on error. 224 * @param pSource Event source to generate event for. 225 * @deprecated as this does not deal with duplicates. 226 */ 227 SHCLEVENTID ShClEventIDGenerate(PSHCLEVENTSOURCE pSource) 228 { 229 AssertPtrReturn(pSource, 0); 230 231 SHCLEVENTID idEvent = ++pSource->idNextEvent; 232 if (idEvent >= VBOX_SHCL_MAX_EVENTS) 233 pSource->idNextEvent = idEvent = 1; /* zero == error, remember! */ 234 235 LogFlowFunc(("uSource=%RU16: New event: %RU32\n", pSource->uID, idEvent)); 236 return idEvent; 237 } 238 239 /** 240 * Generates a new event ID for a specific event source and registers it. 241 * 242 * @returns New event ID generated, or 0 on error. 243 * @param pSource Event source to generate event for. 244 */ 245 SHCLEVENTID ShClEventIdGenerateAndRegister(PSHCLEVENTSOURCE pSource) 246 { 247 AssertPtrReturn(pSource, 0); 248 249 /* 250 * Allocate an event. 251 */ 252 PSHCLEVENT pEvent = (PSHCLEVENT)RTMemAllocZ(sizeof(SHCLEVENT)); 253 AssertReturn(pEvent, 0); 254 int rc = RTSemEventMultiCreate(&pEvent->hEvtMulSem); 255 AssertRCReturnStmt(rc, RTMemFree(pEvent), 0); 256 257 /* 258 * Allocate an unique event ID. 259 */ 260 for (uint32_t cTries = 0;; cTries++) 261 { 262 SHCLEVENTID idEvent = ++pSource->idNextEvent; 263 if (idEvent < VBOX_SHCL_MAX_EVENTS) 264 { /* likely */ } 265 else 266 pSource->idNextEvent = idEvent = 1; /* zero == error, remember! */ 267 268 if (shclEventGet(pSource, idEvent) == NULL) 269 { 270 271 pEvent->idEvent = idEvent; 272 RTListAppend(&pSource->lstEvents, &pEvent->Node); 273 274 LogFlowFunc(("uSource=%RU16: New event: %#x\n", pSource->uID, idEvent)); 275 return idEvent; 276 } 277 278 AssertBreak(cTries < 4096); 279 } 280 281 RTMemFree(pEvent); 282 return 0; 235 283 } 236 284 … … 246 294 PSHCLEVENT pEvent = RTListGetLast(&pSource->lstEvents, SHCLEVENT, Node); 247 295 if (pEvent) 248 return pEvent-> uID;296 return pEvent->idEvent; 249 297 250 298 return 0; … … 266 314 } 267 315 316 #if 0 /** @todo fix later */ 268 317 /** 269 318 * Registers an event. … … 283 332 if (shclEventGet(pSource, uID) == NULL) 284 333 { 285 PSHCLEVENT pEvent 286 = (PSHCLEVENT)RTMemAllocZ(sizeof(SHCLEVENT)); 334 PSHCLEVENT pEvent = (PSHCLEVENT)RTMemAllocZ(sizeof(SHCLEVENT)); 287 335 if (pEvent) 288 336 { 289 rc = ShClEventCreate(pEvent, uID);337 rc = shClEventInit(pEvent, uID); 290 338 if (RT_SUCCESS(rc)) 291 339 { … … 308 356 return rc; 309 357 } 358 #endif /* later */ 310 359 311 360 /** … … 327 376 if (pEvent) 328 377 { 329 LogFlowFunc(("Event %RU32\n", pEvent-> uID));378 LogFlowFunc(("Event %RU32\n", pEvent->idEvent)); 330 379 331 380 RTListNodeRemove(&pEvent->Node); 332 381 333 ShClEventDestroy(pEvent);382 shClEventTerm(pEvent); 334 383 335 384 RTMemFree(pEvent); … … 368 417 if (pEvent) 369 418 { 370 rc = RTSemEvent Wait(pEvent->hEventSem, uTimeoutMs);419 rc = RTSemEventMultiWait(pEvent->hEvtMulSem, uTimeoutMs); 371 420 if (RT_SUCCESS(rc)) 372 421 { … … 411 460 pEvent->pPayload = pPayload; 412 461 413 rc = RTSemEvent Signal(pEvent->hEventSem);462 rc = RTSemEventMultiSignal(pEvent->hEvtMulSem); 414 463 } 415 464 else -
trunk/src/VBox/GuestHost/SharedClipboard/clipboard-transfers.cpp
r82478 r82527 1190 1190 RTListInit(&pTransfer->Events.lstEvents); 1191 1191 pTransfer->Events.uID = 0; 1192 pTransfer->Events. uEventIDNext= 1;1192 pTransfer->Events.idNextEvent = 1; 1193 1193 1194 1194 if (RT_SUCCESS(rc)) -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-darwin.cpp
r82480 r82527 70 70 if ( RT_SUCCESS(rc) 71 71 && fChanged) 72 { 73 SHCLFORMATDATA formatData; 74 RT_ZERO(formatData); 75 76 formatData.Formats = fFormats; 77 78 rc = ShClSvcFormatsReport(pCtx->pClient, &formatData); 79 } 72 rc = ShClSvcHostReportFormats(pCtx->pClient, fFormats); 80 73 81 74 LogFlowFuncLeaveRC(rc); … … 215 208 #endif 216 209 217 SHCLDATAREQ dataReq; 218 RT_ZERO(dataReq); 219 220 dataReq.uFmt = pFormats->Formats; 221 dataReq.cbSize = _64K; /** @todo Make this more dynamic. */ 222 223 return ShClSvcDataReadRequest(pClient, &dataReq, NULL /* puEvent */); 210 return ShClSvcDataReadRequest(pClient, pFormats->Formats, NULL /* puEvent */); 224 211 } 225 212 -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-internal.h
r82526 r82527 53 53 54 54 /** 55 * Structure for keeping a single HGCM message.55 * A queued message for the guest. 56 56 */ 57 57 typedef struct _SHCLCLIENTMSG 58 58 { 59 /** Stored message type. */ 60 uint32_t uMsg; 61 /** Number of stored HGCM parameters. */ 62 uint32_t cParms; 63 /** Stored HGCM parameters. */ 64 PVBOXHGCMSVCPARM paParms; 65 /** Message context. */ 66 SHCLMSGCTX Ctx; 67 } SHCLCLIENTMSG, *PSHCLCLIENTMSG; 59 /** The queue list entry. */ 60 RTLISTNODE ListEntry; 61 /** Stored message ID (VBOX_SHCL_HOST_MSG_XXX). */ 62 uint32_t idMsg; 63 /** Number of stored parameters. */ 64 uint32_t cParms; 65 /** The context ID for this message. 66 * @todo r=bird: Why do we need this? */ 67 uint64_t idContext; 68 /** HGCM parameters. */ 69 VBOXHGCMSVCPARM aParms[RT_FLEXIBLE_ARRAY]; 70 } SHCLCLIENTMSG; 71 /** Pointer to a queue message for the guest. */ 72 typedef SHCLCLIENTMSG *PSHCLCLIENTMSG; 68 73 69 74 typedef struct SHCLCLIENTTRANSFERSTATE … … 141 146 { 142 147 /** General client state data. */ 143 SHCLCLIENTSTATE State; 144 RTCRITSECT CritSect; 145 /** The client's message queue (FIFO). */ 146 RTCList<SHCLCLIENTMSG *> queueMsg; 148 SHCLCLIENTSTATE State; 149 /** The critical section protecting the queue, event source and whatnot. */ 150 RTCRITSECT CritSect; 151 /** The client's message queue (SHCLCLIENTMSG). */ 152 RTLISTANCHOR MsgQueue; 153 /** Number of allocated messages (updated atomically, not under critsect). */ 154 uint32_t volatile cAllocatedMessages; 147 155 /** The client's own event source. 148 156 * Needed for events which are not bound to a specific transfer. */ 149 SHCLEVENTSOURCE EventSrc;157 SHCLEVENTSOURCE EventSrc; 150 158 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 151 159 /** Transfer contextdata. */ … … 210 218 /** The actual clipboard formats announced while the host service 211 219 * is reading clipboard data from the extension. */ 212 uint32_t uDelayedFormats;220 uint32_t fDelayedFormats; 213 221 } SHCLEXTSTATE, *PSHCLEXTSTATE; 214 222 … … 216 224 217 225 void shClSvcMsgQueueReset(PSHCLCLIENT pClient); 218 PSHCLCLIENTMSG shClSvcMsgAlloc( uint32_t uMsg, uint32_t cParms);219 void shClSvcMsgFree(PSHCLCLIENT MSG pMsg);220 void shClSvcMsg SetPeekReturn(PSHCLCLIENTMSG pMsg, PVBOXHGCMSVCPARM paDstParms, uint32_t cDstParms);221 int shClSvcMsgAdd (PSHCLCLIENT pClient, PSHCLCLIENTMSG pMsg, bool fAppend);226 PSHCLCLIENTMSG shClSvcMsgAlloc(PSHCLCLIENT pClient, uint32_t uMsg, uint32_t cParms); 227 void shClSvcMsgFree(PSHCLCLIENT pClient, PSHCLCLIENTMSG pMsg); 228 void shClSvcMsgAdd(PSHCLCLIENT pClient, PSHCLCLIENTMSG pMsg, bool fAppend); 229 int shClSvcMsgAddAndWakeupClient(PSHCLCLIENT pClient, PSHCLCLIENTMSG pMsg); 222 230 223 231 int shClSvcClientInit(PSHCLCLIENT pClient, uint32_t uClientID); … … 243 251 * @{ 244 252 */ 245 int ShClSvcDataReadRequest(PSHCLCLIENT pClient, PSHCLDATAREQ pDataReq, PSHCLEVENTID puEvent);253 int ShClSvcDataReadRequest(PSHCLCLIENT pClient, SHCLFORMAT fFormat, PSHCLEVENTID puEvent); 246 254 int ShClSvcDataReadSignal(PSHCLCLIENT pClient, PSHCLCLIENTCMDCTX pCmdCtx, PSHCLDATABLOCK pData); 247 int ShClSvc FormatsReport(PSHCLCLIENT pClient, PSHCLFORMATDATA pFormats);255 int ShClSvcHostReportFormats(PSHCLCLIENT pClient, SHCLFORMATS fFormats); 248 256 uint32_t ShClSvcGetMode(void); 249 257 bool ShClSvcGetHeadless(void); -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-transfers.cpp
r82526 r82527 121 121 int rc; 122 122 123 PSHCLCLIENTMSG pMsgHdr = shClSvcMsgAlloc( VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_HDR_READ,123 PSHCLCLIENTMSG pMsgHdr = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_HDR_READ, 124 124 VBOX_SHCL_CPARMS_ROOT_LIST_HDR_READ_REQ); 125 125 if (pMsgHdr) … … 162 162 for (uint32_t i = 0; i < pSrcRootListHdr->cRoots; i++) 163 163 { 164 PSHCLCLIENTMSG pMsgEntry = shClSvcMsgAlloc( VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_ENTRY_READ,164 PSHCLCLIENTMSG pMsgEntry = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_ENTRY_READ, 165 165 VBOX_SHCL_CPARMS_ROOT_LIST_ENTRY_READ_REQ); 166 166 … … 240 240 int rc; 241 241 242 PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc( VBOX_SHCL_HOST_MSG_TRANSFER_LIST_OPEN,242 PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_TRANSFER_LIST_OPEN, 243 243 VBOX_SHCL_CPARMS_LIST_OPEN); 244 244 if (pMsg) … … 300 300 int rc; 301 301 302 PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc( VBOX_SHCL_HOST_MSG_TRANSFER_LIST_CLOSE,302 PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_TRANSFER_LIST_CLOSE, 303 303 VBOX_SHCL_CPARMS_LIST_CLOSE); 304 304 if (pMsg) … … 348 348 int rc; 349 349 350 PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc( VBOX_SHCL_HOST_MSG_TRANSFER_LIST_HDR_READ,350 PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_TRANSFER_LIST_HDR_READ, 351 351 VBOX_SHCL_CPARMS_LIST_HDR_READ_REQ); 352 352 if (pMsg) … … 409 409 int rc; 410 410 411 PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc( VBOX_SHCL_HOST_MSG_TRANSFER_LIST_ENTRY_READ,411 PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_TRANSFER_LIST_ENTRY_READ, 412 412 VBOX_SHCL_CPARMS_LIST_ENTRY_READ); 413 413 if (pMsg) … … 469 469 int rc; 470 470 471 PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc( VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_OPEN,471 PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_OPEN, 472 472 VBOX_SHCL_CPARMS_OBJ_OPEN); 473 473 if (pMsg) … … 531 531 int rc; 532 532 533 PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc( VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_CLOSE,533 PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_CLOSE, 534 534 VBOX_SHCL_CPARMS_OBJ_CLOSE); 535 535 if (pMsg) … … 587 587 int rc; 588 588 589 PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc( VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_READ,589 PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_READ, 590 590 VBOX_SHCL_CPARMS_OBJ_READ_REQ); 591 591 if (pMsg) … … 646 646 int rc; 647 647 648 PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc( VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_WRITE,648 PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_WRITE, 649 649 VBOX_SHCL_CPARMS_OBJ_WRITE); 650 650 if (pMsg) … … 1986 1986 /* puEvent is optional. */ 1987 1987 1988 PSHCLCLIENTMSG pMsgReadData = shClSvcMsgAlloc( VBOX_SHCL_HOST_MSG_TRANSFER_STATUS,1988 PSHCLCLIENTMSG pMsgReadData = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_TRANSFER_STATUS, 1989 1989 VBOX_SHCL_CPARMS_TRANSFER_STATUS); 1990 1990 if (!pMsgReadData) -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-win.cpp
r82526 r82527 167 167 } 168 168 169 static int vboxClipboardSvcWinDataRead(PSHCLCONTEXT pCtx, UINT cfFormat, 170 void **ppvData, uint32_t *pcbData) 171 { 172 SHCLDATAREQ dataReq; 173 RT_ZERO(dataReq); 174 175 dataReq.uFmt = SharedClipboardWinClipboardFormatToVBox(cfFormat); 176 dataReq.cbSize = _64K; /** @todo Make this more dynamic. */ 177 178 LogFlowFunc(("cfFormat=%u -> uFmt=0x%x\n", cfFormat, dataReq.uFmt)); 179 180 if (dataReq.uFmt == VBOX_SHCL_FMT_NONE) 181 { 182 LogRel2(("Shared Clipbaord: Windows format %u not supported, ingoring\n", cfFormat)); 169 static int vboxClipboardSvcWinDataRead(PSHCLCONTEXT pCtx, UINT uFormat, void **ppvData, uint32_t *pcbData) 170 { 171 SHCLFORMAT fFormat = SharedClipboardWinClipboardFormatToVBox(uFormat); 172 LogFlowFunc(("uFormat=%u -> uFmt=0x%x\n", uFormat, fFormat)); 173 174 if (fFormat == VBOX_SHCL_FMT_NONE) 175 { 176 LogRel2(("Shared Clipbaord: Windows format %u not supported, ingoring\n", uFormat)); 183 177 return VERR_NOT_SUPPORTED; 184 178 } 185 179 186 180 SHCLEVENTID uEvent = 0; 187 int rc = ShClSvcDataReadRequest(pCtx->pClient, &dataReq, &uEvent);181 int rc = ShClSvcDataReadRequest(pCtx->pClient, fFormat, &uEvent); 188 182 if (RT_SUCCESS(rc)) 189 183 { … … 310 304 311 305 /* Insert the requested clipboard format data into the clipboard. */ 312 const UINT cfFormat = (UINT)wParam; 313 314 const SHCLFORMAT fFormat = SharedClipboardWinClipboardFormatToVBox(cfFormat); 315 316 LogFunc(("WM_RENDERFORMAT: cfFormat=%u -> fFormat=0x%x\n", cfFormat, fFormat)); 306 const UINT uFormat = (UINT)wParam; 307 const SHCLFORMAT fFormat = SharedClipboardWinClipboardFormatToVBox(uFormat); 308 LogFunc(("WM_RENDERFORMAT: uFormat=%u -> fFormat=0x%x\n", uFormat, fFormat)); 317 309 318 310 if ( fFormat == VBOX_SHCL_FMT_NONE … … 327 319 void *pvData = NULL; 328 320 uint32_t cbData = 0; 329 int rc = vboxClipboardSvcWinDataRead(pCtx, cfFormat, &pvData, &cbData);321 int rc = vboxClipboardSvcWinDataRead(pCtx, uFormat, &pvData, &cbData); 330 322 if ( RT_SUCCESS(rc) 331 323 && pvData 332 324 && cbData) 333 325 { 334 rc = vboxClipboardSvcWinDataSet(pCtx, cfFormat, pvData, cbData);326 rc = vboxClipboardSvcWinDataSet(pCtx, uFormat, pvData, cbData); 335 327 336 328 RTMemFree(pvData); … … 597 589 rc = SharedClipboardWinGetFormats(&pCtx->Win, &Formats); 598 590 if ( RT_SUCCESS(rc) 599 && Formats.Formats != VBOX_SHCL_FMT_NONE) 600 { 601 rc = ShClSvcFormatsReport(pCtx->pClient, &Formats); 602 } 591 && Formats.Formats != VBOX_SHCL_FMT_NONE) /** @todo r=bird: BUGBUG: revisit this. */ 592 rc = ShClSvcHostReportFormats(pCtx->pClient, Formats.Formats); 603 593 } 604 594 else /* If we don't have any client data (yet), bail out. */ -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-x11.cpp
r82526 r82527 113 113 * there is data in the host clipboard it will automatically be sent to 114 114 * the guest when the clipboard starts up. */ 115 SHCLFORMATDATA formatData; 116 RT_ZERO(formatData); 117 118 formatData.Formats = VBOX_SHCL_FMT_NONE; 119 120 return ShClSvcFormatsReport(pClient, &formatData); 115 return ShClSvcHostReportFormats(pClient, VBOX_SHCL_FMT_NONE); 121 116 } 122 117 … … 250 245 * 251 246 * @param pCtx Opaque context pointer for the glue code. 252 * @param Formats The formats available. 253 */ 254 DECLCALLBACK(void) ShClX11ReportFormatsCallback(PSHCLCONTEXT pCtx, uint32_t Formats) 255 { 256 LogFlowFunc(("pCtx=%p, Formats=%02X\n", pCtx, Formats)); 257 258 if (Formats == VBOX_SHCL_FMT_NONE) /* No formats to report? Bail out early. */ 247 * @param fFormats The formats available. 248 */ 249 DECLCALLBACK(void) ShClX11ReportFormatsCallback(PSHCLCONTEXT pCtx, uint32_t fFormats) 250 { 251 LogFlowFunc(("pCtx=%p, fFormats=%#x\n", pCtx, fFormats)); 252 253 /** @todo r=bird: BUGBUG: Revisit this */ 254 if (fFormats == VBOX_SHCL_FMT_NONE) /* No formats to report? Bail out early. */ 259 255 return; 260 256 261 SHCLFORMATDATA formatData; 262 RT_ZERO(formatData); 263 264 formatData.Formats = Formats; 265 266 int rc = ShClSvcFormatsReport(pCtx->pClient, &formatData); 257 int rc = ShClSvcHostReportFormats(pCtx->pClient, fFormats); 267 258 RT_NOREF(rc); 268 259 … … 317 308 * 318 309 * @param pCtx Pointer to the host clipboard structure. 319 * @param Format The format in which the data should be transferred. 310 * @param fFormat The format in which the data should be transferred 311 * (VBOX_SHCL_FMT_XXX). 320 312 * @param ppv On success and if pcb > 0, this will point to a buffer 321 313 * to be freed with RTMemFree containing the data read. … … 323 315 * returned. 324 316 */ 325 DECLCALLBACK(int) ShClX11RequestDataForX11Callback(PSHCLCONTEXT pCtx, SHCLFORMAT Format, void **ppv, uint32_t *pcb)326 { 327 LogFlowFunc(("pCtx=%p, Format=0x%x\n", pCtx, Format));317 DECLCALLBACK(int) ShClX11RequestDataForX11Callback(PSHCLCONTEXT pCtx, SHCLFORMAT fFormat, void **ppv, uint32_t *pcb) 318 { 319 LogFlowFunc(("pCtx=%p, Format=0x%x\n", pCtx, fFormat)); 328 320 329 321 if (pCtx->fShuttingDown) … … 337 329 338 330 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 339 if (Format == VBOX_SHCL_FMT_URI_LIST) 340 { 341 rc = 0; 342 } 331 if (fFormat == VBOX_SHCL_FMT_URI_LIST) 332 rc = VINF_SUCCESS; 343 333 else 344 334 #endif 345 335 { 346 336 /* Request data from the guest. */ 347 SHCLDATAREQ dataReq;348 RT_ZERO(dataReq);349 350 dataReq.uFmt = Format;351 dataReq.cbSize = _64K; /** @todo Make this more dynamic. */352 353 337 SHCLEVENTID uEvent; 354 rc = ShClSvcDataReadRequest(pCtx->pClient, &dataReq, &uEvent);338 rc = ShClSvcDataReadRequest(pCtx->pClient, fFormat, &uEvent); 355 339 if (RT_SUCCESS(rc)) 356 340 { … … 375 359 376 360 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 361 377 362 int ShClSvcImplTransferCreate(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer) 378 363 { … … 429 414 return rc; 430 415 } 431 #endif 416 417 #endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */ -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc.cpp
r82526 r82527 368 368 * 369 369 * @param pClient Pointer to the client data structure to reset message queue for. 370 * @note Caller enters pClient->CritSect. 370 371 */ 371 372 void shClSvcMsgQueueReset(PSHCLCLIENT pClient) 372 373 { 374 Assert(RTCritSectIsOwner(&pClient->CritSect)); 373 375 LogFlowFuncEnter(); 374 376 375 while (! pClient->queueMsg.isEmpty())376 { 377 RTMemFree(pClient->queueMsg.last());378 pClient->queueMsg.removeLast();377 while (!RTListIsEmpty(&pClient->MsgQueue)) 378 { 379 PSHCLCLIENTMSG pMsg = RTListRemoveFirst(&pClient->MsgQueue, SHCLCLIENTMSG, ListEntry); 380 shClSvcMsgFree(pClient, pMsg); 379 381 } 380 382 } … … 384 386 * 385 387 * @returns Allocated clipboard message, or NULL on failure. 386 * @param uMsg Message type of message to allocate. 387 * @param cParms Number of HGCM parameters to allocate. 388 */ 389 PSHCLCLIENTMSG shClSvcMsgAlloc(uint32_t uMsg, uint32_t cParms) 390 { 391 PSHCLCLIENTMSG pMsg = (PSHCLCLIENTMSG)RTMemAlloc(sizeof(SHCLCLIENTMSG)); 388 * @param pClient The client which is target of this message. 389 * @param idMsg The message ID (VBOX_SHCL_HOST_MSG_XXX) to use 390 * @param cParms The number of parameters the message takes. 391 */ 392 PSHCLCLIENTMSG shClSvcMsgAlloc(PSHCLCLIENT pClient, uint32_t idMsg, uint32_t cParms) 393 { 394 RT_NOREF(pClient); 395 PSHCLCLIENTMSG pMsg = (PSHCLCLIENTMSG)RTMemAllocZ(RT_UOFFSETOF_DYN(SHCLCLIENTMSG, aParms[cParms])); 392 396 if (pMsg) 393 397 { 394 pMsg->paParms = (PVBOXHGCMSVCPARM)RTMemAllocZ(sizeof(VBOXHGCMSVCPARM) * cParms); 395 if (pMsg->paParms) 396 { 398 uint32_t cAllocated = ASMAtomicIncU32(&pClient->cAllocatedMessages); 399 if (cAllocated <= 4096) 400 { 401 RTListInit(&pMsg->ListEntry); 397 402 pMsg->cParms = cParms; 398 pMsg->uMsg = uMsg; 399 403 pMsg->idMsg = idMsg; 400 404 return pMsg; 401 405 } 402 } 403 404 RTMemFree(pMsg); 406 AssertMsgFailed(("Too many messages allocated for client %u! (%u)\n", pClient->State.uClientID, cAllocated)); 407 ASMAtomicDecU32(&pClient->cAllocatedMessages); 408 RTMemFree(pMsg); 409 } 405 410 return NULL; 406 411 } … … 409 414 * Frees a formerly allocated clipboard message. 410 415 * 411 * @param pMsg Clipboard message to free. 412 * The pointer will be invalid after calling this function. 413 */ 414 void shClSvcMsgFree(PSHCLCLIENTMSG pMsg) 415 { 416 if (!pMsg) 417 return; 418 419 if (pMsg->paParms) 420 RTMemFree(pMsg->paParms); 421 422 RTMemFree(pMsg); 423 pMsg = NULL; 416 * @param pClient The client which was the target of this message. 417 * @param pMsg Clipboard message to free. 418 */ 419 void shClSvcMsgFree(PSHCLCLIENT pClient, PSHCLCLIENTMSG pMsg) 420 { 421 RT_NOREF(pClient); 422 /** @todo r=bird: Do accounting. */ 423 if (pMsg) 424 { 425 pMsg->idMsg = UINT32_C(0xdeadface); 426 RTMemFree(pMsg); 427 428 uint32_t cAllocated = ASMAtomicDecU32(&pClient->cAllocatedMessages); 429 Assert(cAllocated < UINT32_MAX / 2); 430 } 424 431 } 425 432 … … 433 440 * @remarks ASSUMES the parameters has been cleared by clientMsgPeek. 434 441 */ 435 void shClSvcMsgSetPeekReturn(PSHCLCLIENTMSG pMsg, PVBOXHGCMSVCPARM paDstParms, uint32_t cDstParms)442 static void shClSvcMsgSetPeekReturn(PSHCLCLIENTMSG pMsg, PVBOXHGCMSVCPARM paDstParms, uint32_t cDstParms) 436 443 { 437 444 Assert(cDstParms >= 2); 438 445 if (paDstParms[0].type == VBOX_HGCM_SVC_PARM_32BIT) 439 paDstParms[0].u.uint32 = pMsg-> uMsg;446 paDstParms[0].u.uint32 = pMsg->idMsg; 440 447 else 441 paDstParms[0].u.uint64 = pMsg-> uMsg;448 paDstParms[0].u.uint64 = pMsg->idMsg; 442 449 paDstParms[1].u.uint32 = pMsg->cParms; 443 450 444 451 uint32_t i = RT_MIN(cDstParms, pMsg->cParms + 2); 445 452 while (i-- > 2) 446 switch (pMsg-> paParms[i - 2].type)453 switch (pMsg->aParms[i - 2].type) 447 454 { 448 455 case VBOX_HGCM_SVC_PARM_32BIT: paDstParms[i].u.uint32 = ~(uint32_t)sizeof(uint32_t); break; 449 456 case VBOX_HGCM_SVC_PARM_64BIT: paDstParms[i].u.uint32 = ~(uint32_t)sizeof(uint64_t); break; 450 case VBOX_HGCM_SVC_PARM_PTR: paDstParms[i].u.uint32 = pMsg-> paParms[i - 2].u.pointer.size; break;457 case VBOX_HGCM_SVC_PARM_PTR: paDstParms[i].u.uint32 = pMsg->aParms[i - 2].u.pointer.size; break; 451 458 } 452 459 } … … 455 462 * Sets the VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT return parameters. 456 463 * 457 * This function does the necessary translation between the legacy protocol (<= VBox 6.0) and the new protocols (>= VBox 6.1),458 * as messages are always stored as >= v1 messages in the message queue.459 *460 464 * @returns VBox status code. 461 * @param pMsg Message to set return parameters to.465 * @param pMsg The message which parameters to return to the guest. 462 466 * @param paDstParms The peek parameter vector. 463 * @param cDstParms The number of peek parameters (at least two). 464 * @param pfRemove Returns whether the message can be removed from the queue or not. 465 * This is needed for certain messages which need to stay around for more than one (guest) call. 466 */ 467 int shClSvcMsgSetGetHostMsgOldReturn(PSHCLCLIENTMSG pMsg, PVBOXHGCMSVCPARM paDstParms, uint32_t cDstParms, 468 bool *pfRemove) 469 { 470 AssertPtrReturn(pMsg, VERR_INVALID_POINTER); 471 AssertPtrReturn(paDstParms, VERR_INVALID_POINTER); 472 AssertReturn (cDstParms >= 2, VERR_INVALID_PARAMETER); 473 AssertPtrReturn(pfRemove, VERR_INVALID_POINTER); 474 475 int rc = VINF_SUCCESS; 476 477 bool fRemove = true; 478 479 LogFlowFunc(("uMsg=%RU32 (%s), cParms=%RU32\n", 480 pMsg->uMsg, ShClHostMsgToStr(pMsg->uMsg), pMsg->cParms)); 481 482 switch (pMsg->uMsg) 483 { 484 case VBOX_SHCL_HOST_MSG_QUIT: 485 { 486 HGCMSvcSetU32(&paDstParms[0], VBOX_SHCL_HOST_MSG_QUIT); 487 HGCMSvcSetU32(&paDstParms[1], 0 /* Not used */); 467 * @param cDstParms The number of peek parameters should be exactly two 468 */ 469 static int shClSvcMsgSetOldWaitReturn(PSHCLCLIENTMSG pMsg, PVBOXHGCMSVCPARM paDstParms, uint32_t cDstParms) 470 { 471 /* 472 * Assert sanity. 473 */ 474 AssertPtr(pMsg); 475 AssertPtrReturn(paDstParms, VERR_INVALID_POINTER); 476 AssertReturn(cDstParms >= 2, VERR_INVALID_PARAMETER); 477 478 Assert(pMsg->cParms == 2); 479 Assert(pMsg->aParms[0].u.uint32 == pMsg->idMsg); 480 switch (pMsg->idMsg) 481 { 482 case VBOX_SHCL_HOST_MSG_READ_DATA: 483 case VBOX_SHCL_HOST_MSG_FORMATS_REPORT: 488 484 break; 489 }490 491 case VBOX_SHCL_HOST_MSG_READ_DATA:492 {493 HGCMSvcSetU32(&paDstParms[0], VBOX_SHCL_HOST_MSG_READ_DATA);494 AssertBreakStmt(pMsg->cParms >= 2, rc = VERR_INVALID_PARAMETER); /* Paranoia. */495 uint32_t uSrcFmt = VBOX_SHCL_FMT_NONE;496 uint32_t uDstFmt = VBOX_SHCL_FMT_NONE;497 rc = HGCMSvcGetU32(&pMsg->paParms[2] /* uFormat */, &uSrcFmt);498 if (RT_SUCCESS(rc))499 {500 if (uSrcFmt & VBOX_SHCL_FMT_UNICODETEXT)501 uDstFmt = VBOX_SHCL_FMT_UNICODETEXT;502 else if (uSrcFmt & VBOX_SHCL_FMT_BITMAP)503 uDstFmt = VBOX_SHCL_FMT_BITMAP;504 else if (uSrcFmt & VBOX_SHCL_FMT_HTML)505 uDstFmt = VBOX_SHCL_FMT_HTML;506 else507 AssertStmt(uSrcFmt == VBOX_SHCL_FMT_NONE, uSrcFmt = VBOX_SHCL_FMT_NONE);508 509 LogFlowFunc(("uSrcFmt=0x%x, uDstFmt=0x%x\n", uSrcFmt, uDstFmt));510 511 /* Remove format we're going to return from the queued message. */512 uSrcFmt &= ~uDstFmt;513 HGCMSvcSetU32(&pMsg->paParms[2], uSrcFmt);514 515 /* Only report back one format at a time. */516 HGCMSvcSetU32(&paDstParms[1], uDstFmt);517 518 /* If no more formats are left, the message can be removed finally. */519 fRemove = uSrcFmt == VBOX_SHCL_FMT_NONE;520 521 LogFlowFunc(("uSrcFmt=0x%x, fRemove=%RTbool\n", uSrcFmt, fRemove));522 }523 break;524 }525 526 case VBOX_SHCL_HOST_MSG_FORMATS_REPORT:527 {528 HGCMSvcSetU32(&paDstParms[0], VBOX_SHCL_HOST_MSG_FORMATS_REPORT);529 AssertBreakStmt(pMsg->cParms >= 2, rc = VERR_INVALID_PARAMETER); /* Paranoia. */530 uint32_t uFmts;531 rc = HGCMSvcGetU32(&pMsg->paParms[1] /* uFormats */, &uFmts);532 if (RT_SUCCESS(rc))533 HGCMSvcSetU32(&paDstParms[1], uFmts);534 break;535 }536 537 485 default: 538 AssertFailed(); /* Not supported by legacy protocol. */ 539 rc = VERR_NOT_SUPPORTED; 540 break; 541 } 542 543 *pfRemove = fRemove; 544 545 LogFlowFuncLeaveRC(rc); 546 return rc; 486 AssertFailed(); 487 } 488 489 /* 490 * Set the parameters. 491 */ 492 if (pMsg->cParms > 0) 493 paDstParms[0] = pMsg->aParms[0]; 494 if (pMsg->cParms > 1) 495 paDstParms[1] = pMsg->aParms[1]; 496 return VINF_SUCCESS; 547 497 } 548 498 … … 554 504 * @param pMsg Pointer to message to add. The queue then owns the pointer. 555 505 * @param fAppend Whether to append or prepend the message to the queue. 556 */ 557 int shClSvcMsgAdd(PSHCLCLIENT pClient, PSHCLCLIENTMSG pMsg, bool fAppend) 558 { 559 AssertPtrReturn(pMsg, VERR_INVALID_POINTER); 560 561 LogFlowFunc(("uMsg=%RU32 (%s), cParms=%RU32, fAppend=%RTbool\n", 562 pMsg->uMsg, ShClHostMsgToStr(pMsg->uMsg), pMsg->cParms, fAppend)); 506 * 507 * @note Caller must enter critical section. 508 */ 509 void shClSvcMsgAdd(PSHCLCLIENT pClient, PSHCLCLIENTMSG pMsg, bool fAppend) 510 { 511 Assert(RTCritSectIsOwned(&pClient->CritSect)); 512 AssertPtr(pMsg); 513 514 LogFlowFunc(("idMsg=%s (%RU32) cParms=%RU32 fAppend=%RTbool\n", 515 ShClHostMsgToStr(pMsg->idMsg), pMsg->idMsg, pMsg->cParms, fAppend)); 563 516 564 517 if (fAppend) 565 pClient->queueMsg.append(pMsg);518 RTListAppend(&pClient->MsgQueue, &pMsg->ListEntry); 566 519 else 567 pClient->queueMsg.prepend(pMsg); 568 569 /** @todo Catch / handle OOM? */ 570 571 return VINF_SUCCESS; 520 RTListPrepend(&pClient->MsgQueue, &pMsg->ListEntry); 521 } 522 523 524 /** 525 * Appends a message to the client's queue and wake it up. 526 * 527 * @returns VBox status code, though the message is consumed regardless of what 528 * is returned. 529 * @param pClient The client to queue the message on. 530 * @param pMsg The message to queue. Ownership is always 531 * transfered to the queue. 532 * 533 * @note Caller must enter critical section. 534 */ 535 int shClSvcMsgAddAndWakeupClient(PSHCLCLIENT pClient, PSHCLCLIENTMSG pMsg) 536 { 537 Assert(RTCritSectIsOwned(&pClient->CritSect)); 538 AssertPtr(pMsg); 539 AssertPtr(pClient); 540 LogFlowFunc(("idMsg=%s (%u) cParms=%u\n", ShClHostMsgToStr(pMsg->idMsg), pMsg->idMsg, pMsg->cParms)); 541 542 RTListAppend(&pClient->MsgQueue, &pMsg->ListEntry); 543 return shClSvcClientWakeup(pClient); 572 544 } 573 545 … … 584 556 /* Assign the client ID. */ 585 557 pClient->State.uClientID = uClientID; 558 RTListInit(&pClient->MsgQueue); 559 pClient->cAllocatedMessages = 0; 586 560 587 561 LogFlowFunc(("[Client %RU32]\n", pClient->State.uClientID)); … … 669 643 670 644 LogFlowFunc(("[Client %RU32]\n", pClient->State.uClientID)); 645 RTCritSectEnter(&pClient->CritSect); 671 646 672 647 /* Reset message queue. */ … … 684 659 685 660 shclSvcClientStateReset(&pClient->State); 661 662 RTCritSectLeave(&pClient->CritSect); 686 663 } 687 664 … … 824 801 * Return information about the first message if one is pending in the list. 825 802 */ 826 if (!pClient->queueMsg.isEmpty()) 827 { 828 PSHCLCLIENTMSG pFirstMsg = pClient->queueMsg.first(); 829 if (pFirstMsg) 830 { 831 shClSvcMsgSetPeekReturn(pFirstMsg, paParms, cParms); 832 LogFlowFunc(("[Client %RU32] VBOX_SHCL_GUEST_FN_MSG_PEEK_XXX -> VINF_SUCCESS (idMsg=%u (%s), cParms=%u)\n", 833 pClient->State.uClientID, pFirstMsg->uMsg, ShClHostMsgToStr(pFirstMsg->uMsg), 834 pFirstMsg->cParms)); 835 return VINF_SUCCESS; 836 } 803 PSHCLCLIENTMSG pFirstMsg = RTListGetFirst(&pClient->MsgQueue, SHCLCLIENTMSG, ListEntry); 804 if (pFirstMsg) 805 { 806 shClSvcMsgSetPeekReturn(pFirstMsg, paParms, cParms); 807 LogFlowFunc(("[Client %RU32] VBOX_SHCL_GUEST_FN_MSG_PEEK_XXX -> VINF_SUCCESS (idMsg=%s (%u), cParms=%u)\n", 808 pClient->State.uClientID, ShClHostMsgToStr(pFirstMsg->idMsg), pFirstMsg->idMsg, pFirstMsg->cParms)); 809 return VINF_SUCCESS; 837 810 } 838 811 … … 875 848 static int shClSvcClientMsgOldGet(PSHCLCLIENT pClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 876 849 { 850 /* 851 * Validate input. 852 */ 853 ASSERT_GUEST_RETURN(cParms == VBOX_SHCL_CPARMS_GET_HOST_MSG_OLD, VERR_WRONG_PARAMETER_COUNT); 854 ASSERT_GUEST_RETURN(paParms[0].type == VBOX_HGCM_SVC_PARM_32BIT, VERR_WRONG_PARAMETER_TYPE); /* id32Msg */ 855 ASSERT_GUEST_RETURN(paParms[1].type == VBOX_HGCM_SVC_PARM_32BIT, VERR_WRONG_PARAMETER_TYPE); /* f32Formats */ 856 857 paParms[0].u.uint32 = 0; 858 paParms[1].u.uint32 = 0; 859 860 /* 861 * If there is a message pending we can return immediately. 862 */ 877 863 int rc; 878 879 if (cParms != VBOX_SHCL_CPARMS_GET_HOST_MSG_OLD) 880 { 881 rc = VERR_INVALID_PARAMETER; 882 } 883 else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* msg */ 884 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT) /* formats */ 885 { 886 rc = VERR_INVALID_PARAMETER; 887 } 864 PSHCLCLIENTMSG pFirstMsg = RTListGetFirst(&pClient->MsgQueue, SHCLCLIENTMSG, ListEntry); 865 if (pFirstMsg) 866 { 867 LogFlowFunc(("[Client %RU32] uMsg=%s (%RU32), cParms=%RU32\n", pClient->State.uClientID, 868 ShClHostMsgToStr(pFirstMsg->idMsg), pFirstMsg->idMsg, pFirstMsg->cParms)); 869 870 rc = shClSvcMsgSetOldWaitReturn(pFirstMsg, paParms, cParms); 871 AssertPtr(g_pHelpers); 872 rc = g_pHelpers->pfnCallComplete(hCall, rc); 873 if (rc != VERR_CANCELLED) 874 { 875 RTListNodeRemove(&pFirstMsg->ListEntry); 876 shClSvcMsgFree(pClient, pFirstMsg); 877 878 rc = VINF_HGCM_ASYNC_EXECUTE; /* The caller must not complete it. */ 879 } 880 } 881 /* 882 * Otherwise we must wait. 883 */ 888 884 else 889 885 { 890 if (!pClient->queueMsg.isEmpty()) 891 { 892 PSHCLCLIENTMSG pFirstMsg = pClient->queueMsg.first(); 893 AssertPtr(pFirstMsg); 894 895 LogFlowFunc(("[Client %RU32] uMsg=%RU32 (%s), cParms=%RU32\n", 896 pClient->State.uClientID, pFirstMsg->uMsg, ShClHostMsgToStr(pFirstMsg->uMsg), 897 pFirstMsg->cParms)); 898 899 bool fRemove; 900 rc = shClSvcMsgSetGetHostMsgOldReturn(pFirstMsg, paParms, cParms, &fRemove); 901 if (RT_SUCCESS(rc)) 902 { 903 AssertPtr(g_pHelpers); 904 rc = g_pHelpers->pfnCallComplete(hCall, rc); 905 if ( rc != VERR_CANCELLED 906 && fRemove) 907 { 908 pClient->queueMsg.removeFirst(); 909 shClSvcMsgFree(pFirstMsg); 910 911 rc = VINF_HGCM_ASYNC_EXECUTE; /* The caller must not complete it. */ 912 } 913 } 914 } 915 else 916 { 917 ASSERT_GUEST_MSG_RETURN(pClient->Pending.uType == 0, ("Already pending! (idClient=%RU32)\n", 918 pClient->State.uClientID), VERR_RESOURCE_BUSY); 919 920 pClient->Pending.hHandle = hCall; 921 pClient->Pending.cParms = cParms; 922 pClient->Pending.paParms = paParms; 923 pClient->Pending.uType = VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT; 924 925 rc = VINF_HGCM_ASYNC_EXECUTE; /* The caller must not complete it. */ 926 927 LogFlowFunc(("[Client %RU32] Is now in pending mode...\n", pClient->State.uClientID)); 928 } 886 ASSERT_GUEST_MSG_RETURN(pClient->Pending.uType == 0, ("Already pending! (idClient=%RU32)\n", pClient->State.uClientID), 887 VERR_RESOURCE_BUSY); 888 889 pClient->Pending.hHandle = hCall; 890 pClient->Pending.cParms = cParms; 891 pClient->Pending.paParms = paParms; 892 pClient->Pending.uType = VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT; 893 894 rc = VINF_HGCM_ASYNC_EXECUTE; /* The caller must not complete it. */ 895 896 LogFlowFunc(("[Client %RU32] Is now in pending mode...\n", pClient->State.uClientID)); 929 897 } 930 898 … … 965 933 * Return information about the first message if one is pending in the list. 966 934 */ 967 if (!pClient->queueMsg.isEmpty()) 968 { 969 PSHCLCLIENTMSG pFirstMsg = pClient->queueMsg.first(); 970 if (pFirstMsg) 971 { 972 LogFlowFunc(("First message is: %RU32 (%s), cParms=%RU32\n", 973 pFirstMsg->uMsg, ShClHostMsgToStr(pFirstMsg->uMsg), pFirstMsg->cParms)); 974 975 ASSERT_GUEST_MSG_RETURN(pFirstMsg->uMsg == idMsgExpected || idMsgExpected == UINT32_MAX, 976 ("idMsg=%u (%s) cParms=%u, caller expected %u (%s) and %u\n", 977 pFirstMsg->uMsg, ShClHostMsgToStr(pFirstMsg->uMsg), pFirstMsg->cParms, 978 idMsgExpected, ShClHostMsgToStr(idMsgExpected), cParms), 979 VERR_MISMATCH); 980 ASSERT_GUEST_MSG_RETURN(pFirstMsg->cParms == cParms, 981 ("idMsg=%u (%s) cParms=%u, caller expected %u (%s) and %u\n", 982 pFirstMsg->uMsg, ShClHostMsgToStr(pFirstMsg->uMsg), pFirstMsg->cParms, 983 idMsgExpected, ShClHostMsgToStr(idMsgExpected), cParms), 984 VERR_WRONG_PARAMETER_COUNT); 985 986 /* Check the parameter types. */ 987 for (uint32_t i = 0; i < cParms; i++) 988 ASSERT_GUEST_MSG_RETURN(pFirstMsg->paParms[i].type == paParms[i].type, 989 ("param #%u: type %u, caller expected %u (idMsg=%u %s)\n", i, pFirstMsg->paParms[i].type, 990 paParms[i].type, pFirstMsg->uMsg, ShClHostMsgToStr(pFirstMsg->uMsg)), 991 VERR_WRONG_PARAMETER_TYPE); 935 PSHCLCLIENTMSG pFirstMsg = RTListGetFirst(&pClient->MsgQueue, SHCLCLIENTMSG, ListEntry); 936 if (pFirstMsg) 937 { 938 LogFlowFunc(("First message is: %s (%u), cParms=%RU32\n", ShClHostMsgToStr(pFirstMsg->idMsg), pFirstMsg->idMsg, pFirstMsg->cParms)); 939 940 ASSERT_GUEST_MSG_RETURN(pFirstMsg->idMsg == idMsgExpected || idMsgExpected == UINT32_MAX, 941 ("idMsg=%u (%s) cParms=%u, caller expected %u (%s) and %u\n", 942 pFirstMsg->idMsg, ShClHostMsgToStr(pFirstMsg->idMsg), pFirstMsg->cParms, 943 idMsgExpected, ShClHostMsgToStr(idMsgExpected), cParms), 944 VERR_MISMATCH); 945 ASSERT_GUEST_MSG_RETURN(pFirstMsg->cParms == cParms, 946 ("idMsg=%u (%s) cParms=%u, caller expected %u (%s) and %u\n", 947 pFirstMsg->idMsg, ShClHostMsgToStr(pFirstMsg->idMsg), pFirstMsg->cParms, 948 idMsgExpected, ShClHostMsgToStr(idMsgExpected), cParms), 949 VERR_WRONG_PARAMETER_COUNT); 950 951 /* Check the parameter types. */ 952 for (uint32_t i = 0; i < cParms; i++) 953 ASSERT_GUEST_MSG_RETURN(pFirstMsg->aParms[i].type == paParms[i].type, 954 ("param #%u: type %u, caller expected %u (idMsg=%u %s)\n", i, pFirstMsg->aParms[i].type, 955 paParms[i].type, pFirstMsg->idMsg, ShClHostMsgToStr(pFirstMsg->idMsg)), 956 VERR_WRONG_PARAMETER_TYPE); 957 /* 958 * Copy out the parameters. 959 * 960 * No assertions on buffer overflows, and keep going till the end so we can 961 * communicate all the required buffer sizes. 962 */ 963 int rc = VINF_SUCCESS; 964 for (uint32_t i = 0; i < cParms; i++) 965 switch (pFirstMsg->aParms[i].type) 966 { 967 case VBOX_HGCM_SVC_PARM_32BIT: 968 paParms[i].u.uint32 = pFirstMsg->aParms[i].u.uint32; 969 break; 970 971 case VBOX_HGCM_SVC_PARM_64BIT: 972 paParms[i].u.uint64 = pFirstMsg->aParms[i].u.uint64; 973 break; 974 975 case VBOX_HGCM_SVC_PARM_PTR: 976 { 977 uint32_t const cbSrc = pFirstMsg->aParms[i].u.pointer.size; 978 uint32_t const cbDst = paParms[i].u.pointer.size; 979 paParms[i].u.pointer.size = cbSrc; /** @todo Check if this is safe in other layers... 980 * Update: Safe, yes, but VMMDevHGCM doesn't pass it along. */ 981 if (cbSrc <= cbDst) 982 memcpy(paParms[i].u.pointer.addr, pFirstMsg->aParms[i].u.pointer.addr, cbSrc); 983 else 984 { 985 AssertMsgFailed(("#%u: cbSrc=%RU32 is bigger than cbDst=%RU32\n", i, cbSrc, cbDst)); 986 rc = VERR_BUFFER_OVERFLOW; 987 } 988 break; 989 } 990 991 default: 992 AssertMsgFailed(("#%u: %u\n", i, pFirstMsg->aParms[i].type)); 993 rc = VERR_INTERNAL_ERROR; 994 break; 995 } 996 if (RT_SUCCESS(rc)) 997 { 992 998 /* 993 * Copy out the parameters. 994 * 995 * No assertions on buffer overflows, and keep going till the end so we can 996 * communicate all the required buffer sizes. 999 * Complete the message and remove the pending message unless the 1000 * guest raced us and cancelled this call in the meantime. 997 1001 */ 998 int rc = VINF_SUCCESS; 999 for (uint32_t i = 0; i < cParms; i++) 1000 switch (pFirstMsg->paParms[i].type) 1001 { 1002 case VBOX_HGCM_SVC_PARM_32BIT: 1003 paParms[i].u.uint32 = pFirstMsg->paParms[i].u.uint32; 1004 break; 1005 1006 case VBOX_HGCM_SVC_PARM_64BIT: 1007 paParms[i].u.uint64 = pFirstMsg->paParms[i].u.uint64; 1008 break; 1009 1010 case VBOX_HGCM_SVC_PARM_PTR: 1011 { 1012 uint32_t const cbSrc = pFirstMsg->paParms[i].u.pointer.size; 1013 uint32_t const cbDst = paParms[i].u.pointer.size; 1014 paParms[i].u.pointer.size = cbSrc; /** @todo Check if this is safe in other layers... 1015 * Update: Safe, yes, but VMMDevHGCM doesn't pass it along. */ 1016 if (cbSrc <= cbDst) 1017 memcpy(paParms[i].u.pointer.addr, pFirstMsg->paParms[i].u.pointer.addr, cbSrc); 1018 else 1019 { 1020 AssertMsgFailed(("#%u: cbSrc=%RU32 is bigger than cbDst=%RU32\n", i, cbSrc, cbDst)); 1021 rc = VERR_BUFFER_OVERFLOW; 1022 } 1023 break; 1024 } 1025 1026 default: 1027 AssertMsgFailed(("#%u: %u\n", i, pFirstMsg->paParms[i].type)); 1028 rc = VERR_INTERNAL_ERROR; 1029 break; 1030 } 1031 if (RT_SUCCESS(rc)) 1002 AssertPtr(g_pHelpers); 1003 rc = g_pHelpers->pfnCallComplete(hCall, rc); 1004 1005 LogFlowFunc(("[Client %RU32] pfnCallComplete -> %Rrc\n", pClient->State.uClientID, rc)); 1006 1007 if (rc != VERR_CANCELLED) 1032 1008 { 1033 /* 1034 * Complete the message and remove the pending message unless the 1035 * guest raced us and cancelled this call in the meantime. 1036 */ 1037 AssertPtr(g_pHelpers); 1038 rc = g_pHelpers->pfnCallComplete(hCall, rc); 1039 1040 LogFlowFunc(("[Client %RU32] pfnCallComplete -> %Rrc\n", pClient->State.uClientID, rc)); 1041 1042 if (rc != VERR_CANCELLED) 1043 { 1044 pClient->queueMsg.removeFirst(); 1045 shClSvcMsgFree(pFirstMsg); 1046 } 1047 1048 return VINF_HGCM_ASYNC_EXECUTE; /* The caller must not complete it. */ 1009 RTListNodeRemove(&pFirstMsg->ListEntry); 1010 shClSvcMsgFree(pClient, pFirstMsg); 1049 1011 } 1050 1012 1051 LogFlowFunc(("[Client %RU32] Returning %Rrc\n", pClient->State.uClientID, rc)); 1052 return rc; 1053 } 1013 return VINF_HGCM_ASYNC_EXECUTE; /* The caller must not complete it. */ 1014 } 1015 1016 LogFlowFunc(("[Client %RU32] Returning %Rrc\n", pClient->State.uClientID, rc)); 1017 return rc; 1054 1018 } 1055 1019 … … 1096 1060 { 1097 1061 Assert(pClient->Pending.cParms >= 2); 1098 HGCMSvcSetU32(&pClient->Pending.paParms[0], VBOX_SHCL_HOST_MSG_CANCELED); 1062 if (pClient->Pending.paParms[0].type == VBOX_HGCM_SVC_PARM_64BIT) 1063 HGCMSvcSetU64(&pClient->Pending.paParms[0], VBOX_SHCL_HOST_MSG_CANCELED); 1064 else 1065 HGCMSvcSetU32(&pClient->Pending.paParms[0], VBOX_SHCL_HOST_MSG_CANCELED); 1099 1066 rcComplete = VINF_TRY_AGAIN; 1100 1067 } … … 1133 1100 * 1134 1101 * @param pClient Client to wake up. 1102 * @note Caller must enter pClient->CritSect. 1135 1103 */ 1136 1104 int shClSvcClientWakeup(PSHCLCLIENT pClient) 1137 1105 { 1106 Assert(RTCritSectIsOwner(&pClient->CritSect)); 1138 1107 int rc = VINF_NO_CHANGE; 1139 1108 1140 if (pClient->Pending.uType )1109 if (pClient->Pending.uType != 0) 1141 1110 { 1142 1111 LogFunc(("[Client %RU32] Waking up ...\n", pClient->State.uClientID)); 1143 1112 1144 rc = VINF_SUCCESS; 1145 1146 if (!pClient->queueMsg.isEmpty()) 1147 { 1148 PSHCLCLIENTMSG pFirstMsg = pClient->queueMsg.first(); 1149 if (pFirstMsg) 1150 { 1151 LogFunc(("[Client %RU32] Current host message is %RU32 (%s), cParms=%RU32\n", 1152 pClient->State.uClientID, pFirstMsg->uMsg, ShClHostMsgToStr(pFirstMsg->uMsg), 1153 pFirstMsg->cParms)); 1154 1155 bool fDonePending = false; 1156 1157 if (pClient->Pending.uType == VBOX_SHCL_GUEST_FN_MSG_PEEK_WAIT) 1158 { 1159 shClSvcMsgSetPeekReturn(pFirstMsg, pClient->Pending.paParms, pClient->Pending.cParms); 1160 fDonePending = true; 1161 } 1162 else if (pClient->Pending.uType == VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT) /* Legacy, Guest Additions < 6.1. */ 1163 { 1164 bool fRemove; 1165 rc = shClSvcMsgSetGetHostMsgOldReturn(pFirstMsg, pClient->Pending.paParms, pClient->Pending.cParms, 1166 &fRemove); 1167 if (RT_SUCCESS(rc)) 1168 { 1169 if (fRemove) 1170 { 1171 /* The old (legacy) protocol gets the message right when returning from peeking, so 1172 * remove the actual message from our queue right now. */ 1173 pClient->queueMsg.removeFirst(); 1174 shClSvcMsgFree(pFirstMsg); 1175 } 1176 1177 fDonePending = true; 1178 } 1179 } 1180 1181 if (fDonePending) 1182 { 1183 rc = g_pHelpers->pfnCallComplete(pClient->Pending.hHandle, VINF_SUCCESS); 1184 1185 pClient->Pending.hHandle = NULL; 1186 pClient->Pending.paParms = NULL; 1187 pClient->Pending.cParms = 0; 1188 pClient->Pending.uType = 0; 1189 } 1190 } 1191 else 1192 AssertFailed(); 1193 } 1113 PSHCLCLIENTMSG pFirstMsg = RTListGetFirst(&pClient->MsgQueue, SHCLCLIENTMSG, ListEntry); 1114 AssertReturn(pFirstMsg, VERR_INTERNAL_ERROR); 1115 1116 LogFunc(("[Client %RU32] Current host message is %s (%RU32), cParms=%RU32\n", 1117 pClient->State.uClientID, ShClHostMsgToStr(pFirstMsg->idMsg), pFirstMsg->idMsg, pFirstMsg->cParms)); 1118 1119 if (pClient->Pending.uType == VBOX_SHCL_GUEST_FN_MSG_PEEK_WAIT) 1120 shClSvcMsgSetPeekReturn(pFirstMsg, pClient->Pending.paParms, pClient->Pending.cParms); 1121 else if (pClient->Pending.uType == VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT) /* Legacy, Guest Additions < 6.1. */ 1122 shClSvcMsgSetOldWaitReturn(pFirstMsg, pClient->Pending.paParms, pClient->Pending.cParms); 1194 1123 else 1195 AssertMsgFailed(("Waking up client ID=%RU32 with no host message in queue is a bad idea\n", pClient->State.uClientID)); 1196 1197 return rc; 1124 AssertMsgFailedReturn(("pClient->Pending.uType=%u\n", pClient->Pending.uType), VERR_INTERNAL_ERROR_3); 1125 1126 rc = g_pHelpers->pfnCallComplete(pClient->Pending.hHandle, VINF_SUCCESS); 1127 1128 if ( rc != VERR_CANCELLED 1129 && pClient->Pending.uType == VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT) 1130 { 1131 RTListNodeRemove(&pFirstMsg->ListEntry); 1132 shClSvcMsgFree(pClient, pFirstMsg); 1133 } 1134 1135 pClient->Pending.hHandle = NULL; 1136 pClient->Pending.paParms = NULL; 1137 pClient->Pending.cParms = 0; 1138 pClient->Pending.uType = 0; 1198 1139 } 1199 1140 else 1200 1141 LogFunc(("[Client %RU32] Not in pending state, skipping wakeup\n", pClient->State.uClientID)); 1201 1142 1202 return VINF_NO_CHANGE;1143 return rc; 1203 1144 } 1204 1145 … … 1208 1149 * @returns VBox status code. 1209 1150 * @param pClient Client to request to read data form. 1210 * @param pDataReq Data request to send to the guest.1151 * @param fFormat The format being requested (VBOX_SHCL_FMT_XXX). 1211 1152 * @param puEvent Event ID for waiting for new data. Optional. 1212 1153 */ 1213 int ShClSvcDataReadRequest(PSHCLCLIENT pClient, PSHCLDATAREQ pDataReq, PSHCLEVENTID puEvent) 1214 { 1154 int ShClSvcDataReadRequest(PSHCLCLIENT pClient, SHCLFORMAT fFormat, PSHCLEVENTID pidEvent) 1155 { 1156 LogFlowFuncEnter(); 1157 if (pidEvent) 1158 *pidEvent = 0; 1215 1159 AssertPtrReturn(pClient, VERR_INVALID_POINTER); 1216 AssertPtrReturn(pDataReq, VERR_INVALID_POINTER); 1217 /* puEvent is optional. */ 1218 1219 LogFlowFuncEnter(); 1220 1160 1161 /* 1162 * Allocate a message. 1163 */ 1221 1164 int rc; 1222 1223 PSHCLCLIENTMSG pMsgReadData = shClSvcMsgAlloc(VBOX_SHCL_HOST_MSG_READ_DATA, 1224 VBOX_SHCL_CPARMS_READ_DATA_REQ); 1225 if (pMsgReadData) 1226 { 1227 const SHCLEVENTID uEvent = ShClEventIDGenerate(&pClient->EventSrc); 1228 1229 LogFlowFunc(("uFmt=0x%x\n", pDataReq->uFmt)); 1230 1231 HGCMSvcSetU64(&pMsgReadData->paParms[0], VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID, 1232 pClient->EventSrc.uID, uEvent)); 1233 HGCMSvcSetU32(&pMsgReadData->paParms[1], 0 /* fFlags */); 1234 HGCMSvcSetU32(&pMsgReadData->paParms[2], pDataReq->uFmt); 1235 HGCMSvcSetU32(&pMsgReadData->paParms[3], pClient->State.cbChunkSize); 1236 1237 rc = shClSvcMsgAdd(pClient, pMsgReadData, true /* fAppend */); 1238 if (RT_SUCCESS(rc)) 1239 { 1240 rc = ShClEventRegister(&pClient->EventSrc, uEvent); 1241 if (RT_SUCCESS(rc)) 1242 { 1243 rc = shClSvcClientWakeup(pClient); 1244 if (RT_SUCCESS(rc)) 1245 { 1246 if (puEvent) 1247 *puEvent = uEvent; 1248 } 1249 else 1250 ShClEventUnregister(&pClient->EventSrc, uEvent); 1251 } 1252 } 1165 PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc(pClient, 1166 pClient->State.fGuestFeatures0 & VBOX_SHCL_GF_0_CONTEXT_ID 1167 ? VBOX_SHCL_HOST_MSG_READ_DATA_CID : VBOX_SHCL_HOST_MSG_READ_DATA, 1168 2); 1169 if (pMsg) 1170 { 1171 /* 1172 * Enter the critical section and generate an event. 1173 */ 1174 RTCritSectEnter(&pClient->CritSect); 1175 1176 const SHCLEVENTID idEvent = ShClEventIdGenerateAndRegister(&pClient->EventSrc); 1177 if (idEvent != 0) 1178 { 1179 LogFlowFunc(("fFormat=%#x idEvent=%#x\n", fFormat, idEvent)); 1180 1181 /* 1182 * Format the message 1183 */ 1184 if (pMsg->idMsg == VBOX_SHCL_HOST_MSG_READ_DATA_CID) 1185 HGCMSvcSetU64(&pMsg->aParms[0], VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID, pClient->EventSrc.uID, idEvent)); 1186 else 1187 HGCMSvcSetU32(&pMsg->aParms[0], VBOX_SHCL_HOST_MSG_READ_DATA); 1188 HGCMSvcSetU32(&pMsg->aParms[1], fFormat); 1189 1190 /* 1191 * Queue it and wake up the client if it's waiting on a message. 1192 */ 1193 shClSvcMsgAddAndWakeupClient(pClient, pMsg); 1194 if (pidEvent) 1195 *pidEvent = idEvent; 1196 rc = VINF_SUCCESS; 1197 } 1198 else 1199 rc = VERR_TRY_AGAIN; 1200 1201 RTCritSectLeave(&pClient->CritSect); 1253 1202 } 1254 1203 else … … 1300 1249 * @returns VBox status code. 1301 1250 * @param pClient Client to request to read data form. 1302 * @param pFormats Formats to report. 1303 */ 1304 int ShClSvcFormatsReport(PSHCLCLIENT pClient, PSHCLFORMATDATA pFormats) 1305 { 1251 * @param fFormats The formats to report (VBOX_SHCL_FMT_XXX), zero 1252 * is okay (empty the clipboard). 1253 */ 1254 int ShClSvcHostReportFormats(PSHCLCLIENT pClient, SHCLFORMATS fFormats) 1255 { 1256 LogFlowFuncEnter(); 1306 1257 AssertPtrReturn(pClient, VERR_INVALID_POINTER); 1307 AssertPtrReturn(pFormats, VERR_INVALID_POINTER);1308 1309 LogFlowFuncEnter();1310 1311 uint32_t fFormats = pFormats->Formats;1312 uint32_t fFlags = pFormats->fFlags;1313 1258 1314 1259 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 1315 /* If transfer mode is set to disabled, don't report the URI list format to the guest. */ 1260 /* 1261 * If transfer mode is set to disabled, don't report the URI list format to the guest. 1262 */ 1316 1263 if (!(g_fTransferMode & VBOX_SHCL_TRANSFER_MODE_ENABLED)) 1264 { 1265 LogFlowFunc(("fFormats=%#x -> %#x\n", fFormats, fFormats & ~VBOX_SHCL_FMT_URI_LIST)); 1317 1266 fFormats &= ~VBOX_SHCL_FMT_URI_LIST; 1267 } 1318 1268 #endif 1319 1320 LogFlowFunc(("fFormats=0x%x -> 0x%x\n", pFormats->Formats, fFormats)); 1321 1322 /* Nothing to report? Bail out early. */ 1323 if (fFormats == VBOX_SHCL_FMT_NONE) 1324 return VINF_SUCCESS; 1325 1326 LogRel2(("Shared Clipboard: Reporting formats 0x%x to guest\n", fFormats)); 1327 1269 LogRel2(("Shared Clipboard: Reporting formats %#x to guest\n", fFormats)); 1270 1271 /* 1272 * Allocate a message, populate parameters and post it to the client. 1273 */ 1328 1274 int rc; 1329 1330 PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc(VBOX_SHCL_HOST_MSG_FORMATS_REPORT, 3); 1275 PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_FORMATS_REPORT, 2); 1331 1276 if (pMsg) 1332 1277 { 1333 const SHCLEVENTID uEvent = ShClEventIDGenerate(&pClient->EventSrc);1334 1335 HGCMSvcSetU64(&pMsg->paParms[0], VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID, 1336 pClient->EventSrc.uID, uEvent));1337 HGCMSvcSetU32(&pMsg->paParms[1], fFormats);1338 HGCMSvcSetU32(&pMsg->paParms[2], fFlags);1339 1340 rc = shClSvcMsgAdd(pClient, pMsg, true /* fAppend */);1341 if (RT_SUCCESS(rc))1342 {1278 HGCMSvcSetU32(&pMsg->aParms[0], VBOX_SHCL_HOST_MSG_FORMATS_REPORT); 1279 HGCMSvcSetU32(&pMsg->aParms[1], fFormats); 1280 1281 RTCritSectEnter(&pClient->CritSect); 1282 shClSvcMsgAddAndWakeupClient(pClient, pMsg); 1283 RTCritSectLeave(&pClient->CritSect); 1284 1285 /* 1286 * ... 1287 */ 1343 1288 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 1344 /* If we announce an URI list, create a transfer locally and also tell the guest to create1345 * a transfer on the guest side. */1346 if (fFormats & VBOX_SHCL_FMT_URI_LIST)1347 {1348 rc = shClSvcTransferStart(pClient, SHCLTRANSFERDIR_TO_REMOTE, SHCLSOURCE_LOCAL,1349 NULL /* pTransfer */);1350 if (RT_FAILURE(rc))1351 LogRel(("Shared Clipboard: Initializing host write transfer failed with %Rrc\n", rc));1352 }1353 else1354 {1289 # error fixme 1290 /* If we announce an URI list, create a transfer locally and also tell the guest to create 1291 * a transfer on the guest side. */ 1292 if (fFormats & VBOX_SHCL_FMT_URI_LIST) 1293 { 1294 rc = shClSvcTransferStart(pClient, SHCLTRANSFERDIR_TO_REMOTE, SHCLSOURCE_LOCAL, 1295 NULL /* pTransfer */); 1296 if (RT_FAILURE(rc)) 1297 LogRel(("Shared Clipboard: Initializing host write transfer failed with %Rrc\n", rc)); 1298 } 1299 else 1355 1300 #endif 1356 pClient->State.fFlags |= SHCLCLIENTSTATE_FLAGS_READ_ACTIVE; 1357 1358 rc = shClSvcClientWakeup(pClient); 1359 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 1360 } 1361 #endif 1362 } 1301 { 1302 pClient->State.fFlags |= SHCLCLIENTSTATE_FLAGS_READ_ACTIVE; 1303 rc = VINF_SUCCESS; 1304 } 1305 /** @todo r=bird: shouldn't we also call shClSvcSetSource(pClient, SHCLSOURCE_LOCAL) here?? 1306 * Looks like the caller of this function does it, but only on windows. Very helpful. */ 1363 1307 } 1364 1308 else … … 1575 1519 /* Read clipboard data from the extension. */ 1576 1520 rc = g_ExtState.pfnExtension(g_ExtState.pvExtension, VBOX_CLIPBOARD_EXT_FN_DATA_READ, &parms, sizeof(parms)); 1577 LogRelFlowFunc(("DATA/Ext: fDelayedAnnouncement=%RTbool uDelayedFormats=%#x cbData=%RU32->%RU32 rc=%Rrc\n",1578 g_ExtState.fDelayedAnnouncement, g_ExtState. uDelayedFormats, dataBlock.cbData, parms.cbData, rc));1521 LogRelFlowFunc(("DATA/Ext: fDelayedAnnouncement=%RTbool fDelayedFormats=%#x cbData=%RU32->%RU32 rc=%Rrc\n", 1522 g_ExtState.fDelayedAnnouncement, g_ExtState.fDelayedFormats, dataBlock.cbData, parms.cbData, rc)); 1579 1523 1580 1524 /* Did the extension send the clipboard formats yet? … … 1582 1526 if (g_ExtState.fDelayedAnnouncement) 1583 1527 { 1584 SHCLFORMATDATA FormatData; 1585 FormatData.fFlags = 0; 1586 FormatData.Formats = g_ExtState.uDelayedFormats; 1587 Assert(FormatData.Formats != VBOX_SHCL_FMT_NONE); /* There better is *any* format here now. */ 1588 1589 int rc2 = ShClSvcFormatsReport(pClient, &FormatData); 1528 int rc2 = ShClSvcHostReportFormats(pClient, g_ExtState.fDelayedFormats); 1590 1529 AssertRC(rc2); 1591 1530 1592 1531 g_ExtState.fDelayedAnnouncement = false; 1593 g_ExtState. uDelayedFormats = 0;1532 g_ExtState.fDelayedFormats = 0; 1594 1533 } 1595 1534 … … 2224 2163 static SSMFIELD const s_aShClSSMClientMsgHdr[] = 2225 2164 { 2226 SSMFIELD_ENTRY(SHCLCLIENTMSG, uMsg),2165 SSMFIELD_ENTRY(SHCLCLIENTMSG, idMsg), 2227 2166 SSMFIELD_ENTRY(SHCLCLIENTMSG, cParms), 2228 2167 SSMFIELD_ENTRY_TERM() … … 2230 2169 2231 2170 /** 2232 * SSM descriptor table for the VBOXSHCLMSGCTX structure. 2171 * SSM descriptor table for what used to be the VBOXSHCLMSGCTX structure but is 2172 * now part of SHCLCLIENTMSG. 2233 2173 */ 2234 2174 static SSMFIELD const s_aShClSSMClientMsgCtx[] = 2235 2175 { 2236 SSMFIELD_ENTRY(SHCL MSGCTX, uContextID),2176 SSMFIELD_ENTRY(SHCLCLIENTMSG, idContext), 2237 2177 SSMFIELD_ENTRY_TERM() 2238 2178 }; … … 2269 2209 2270 2210 /* Serialize the client's internal message queue. */ 2271 rc = SSMR3PutU64(pSSM, (uint64_t)pClient->queueMsg.size()); 2211 uint32_t cMsgs = 0; 2212 PSHCLCLIENTMSG pMsg; 2213 RTListForEach(&pClient->MsgQueue, pMsg, SHCLCLIENTMSG, ListEntry) 2214 { 2215 cMsgs += 1; 2216 } 2217 2218 rc = SSMR3PutU64(pSSM, cMsgs); 2272 2219 AssertRCReturn(rc, rc); 2273 2220 2274 for (size_t i = 0; i < pClient->queueMsg.size(); i++) 2275 { 2276 PSHCLCLIENTMSG pMsg = pClient->queueMsg.at(i); 2277 AssertPtr(pMsg); 2278 2279 rc = SSMR3PutStructEx(pSSM, pMsg, sizeof(SHCLCLIENTMSG), 0 /*fFlags*/, &s_aShClSSMClientMsgHdr[0], NULL); 2280 AssertRCReturn(rc, rc); 2281 2282 rc = SSMR3PutStructEx(pSSM, &pMsg->Ctx, sizeof(SHCLMSGCTX), 0 /*fFlags*/, &s_aShClSSMClientMsgCtx[0], NULL); 2283 AssertRCReturn(rc, rc); 2284 2285 for (uint32_t p = 0; p < pMsg->cParms; p++) 2286 { 2287 rc = HGCMSvcSSMR3Put(&pMsg->paParms[p], pSSM); 2288 AssertRCReturn(rc, rc); 2289 } 2221 RTListForEach(&pClient->MsgQueue, pMsg, SHCLCLIENTMSG, ListEntry) 2222 { 2223 SSMR3PutStructEx(pSSM, pMsg, sizeof(SHCLCLIENTMSG), 0 /*fFlags*/, &s_aShClSSMClientMsgHdr[0], NULL); 2224 SSMR3PutStructEx(pSSM, pMsg, sizeof(SHCLCLIENTMSG), 0 /*fFlags*/, &s_aShClSSMClientMsgCtx[0], NULL); 2225 2226 for (uint32_t iParm = 0; iParm < pMsg->cParms; iParm++) 2227 HGCMSvcSSMR3Put(&pMsg->aParms[iParm], pSSM); 2290 2228 } 2291 2229 … … 2375 2313 for (uint64_t i = 0; i < cMsgs; i++) 2376 2314 { 2377 PSHCLCLIENTMSG pMsg = (PSHCLCLIENTMSG)RTMemAlloc(sizeof(SHCLCLIENTMSG)); 2315 union 2316 { 2317 SHCLCLIENTMSG Msg; 2318 uint8_t abPadding[RT_UOFFSETOF(SHCLCLIENTMSG, aParms) + sizeof(VBOXHGCMSVCPARM) * 2]; 2319 } u; 2320 2321 SSMR3GetStructEx(pSSM, &u.Msg, RT_UOFFSETOF(SHCLCLIENTMSG, aParms), 0 /*fFlags*/, &s_aShClSSMClientMsgHdr[0], NULL); 2322 rc = SSMR3GetStructEx(pSSM, &u.Msg, RT_UOFFSETOF(SHCLCLIENTMSG, aParms), 0 /*fFlags*/, &s_aShClSSMClientMsgCtx[0], NULL); 2323 AssertRCReturn(rc, rc); 2324 2325 AssertLogRelMsgReturn(u.Msg.cParms <= VMMDEV_MAX_HGCM_PARMS, 2326 ("Too many HGCM message parameters: %u (%#x)\n", u.Msg.cParms, u.Msg.cParms), 2327 VERR_SSM_DATA_UNIT_FORMAT_CHANGED); 2328 2329 PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc(pClient, u.Msg.idMsg, u.Msg.cParms); 2378 2330 AssertReturn(pMsg, VERR_NO_MEMORY); 2379 2380 SSMR3GetStructEx(pSSM, pMsg, sizeof(SHCLCLIENTMSG), 0 /*fFlags*/, &s_aShClSSMClientMsgHdr[0], NULL); 2381 rc = SSMR3GetStructEx(pSSM, &pMsg->Ctx, sizeof(SHCLMSGCTX), 0 /*fFlags*/, &s_aShClSSMClientMsgCtx[0], NULL); 2382 AssertRCReturnStmt(rc, RTMemFree(pMsg), rc); 2383 2384 AssertLogRelMsgReturnStmt(pMsg->cParms <= VMMDEV_MAX_HGCM_PARMS, 2385 ("Too many HGCM message parameters: %u (%#x)\n", pMsg->cParms, pMsg->cParms), 2386 RTMemFree(pMsg), 2387 VERR_SSM_DATA_UNIT_FORMAT_CHANGED); 2388 2389 pMsg->paParms = (PVBOXHGCMSVCPARM)RTMemAllocZ(sizeof(VBOXHGCMSVCPARM) * pMsg->cParms); 2390 AssertReturnStmt(pMsg->paParms, RTMemFree(pMsg), VERR_NO_MEMORY); 2331 pMsg->idContext = u.Msg.idContext; 2391 2332 2392 2333 for (uint32_t p = 0; p < pMsg->cParms; p++) 2393 2334 { 2394 rc = HGCMSvcSSMR3Get(&pMsg-> paParms[p], pSSM);2395 AssertRCReturn (rc, rc); /* we'll leak stuff here, oh well... */2335 rc = HGCMSvcSSMR3Get(&pMsg->aParms[p], pSSM); 2336 AssertRCReturnStmt(rc, shClSvcMsgFree(pClient, pMsg), rc); 2396 2337 } 2397 2338 2398 rc = shClSvcMsgAdd(pClient, pMsg, true /* fAppend */); 2399 AssertRCReturn(rc, rc); 2339 shClSvcMsgAdd(pClient, pMsg, true /* fAppend */); 2400 2340 } 2401 2341 } … … 2436 2376 { 2437 2377 LogFlowFunc(("VBOX_CLIPBOARD_EXT_FN_FORMAT_ANNOUNCE: g_ExtState.fReadingData=%RTbool\n", g_ExtState.fReadingData)); 2438 if (g_ExtState.fReadingData) 2378 if (!g_ExtState.fReadingData) 2379 rc = ShClSvcHostReportFormats(pClient, u32Format); 2380 else 2439 2381 { 2440 2382 g_ExtState.fDelayedAnnouncement = true; 2441 g_ExtState.uDelayedFormats = u32Format; 2383 g_ExtState.fDelayedFormats = u32Format; 2384 rc = VINF_SUCCESS; 2442 2385 } 2443 else if (u32Format != VBOX_SHCL_FMT_NONE)2444 {2445 SHCLFORMATDATA formatData;2446 RT_ZERO(formatData);2447 2448 formatData.Formats = u32Format;2449 2450 rc = ShClSvcFormatsReport(pClient, &formatData);2451 }2452 2453 2386 break; 2454 2387 } … … 2456 2389 /* The service extension wants read data from the guest. */ 2457 2390 case VBOX_CLIPBOARD_EXT_FN_DATA_READ: 2458 { 2459 SHCLDATAREQ dataReq; 2460 RT_ZERO(dataReq); 2461 2462 dataReq.uFmt = u32Format; 2463 dataReq.cbSize = _64K; /** @todo Make this more dynamic. */ 2464 2465 rc = ShClSvcDataReadRequest(pClient, &dataReq, NULL /* puEvent */); 2391 rc = ShClSvcDataReadRequest(pClient, u32Format, NULL /* puEvent */); 2466 2392 break; 2467 }2468 2393 2469 2394 default: -
trunk/src/VBox/HostServices/SharedClipboard/testcase/tstClipboardServiceHost.cpp
r82526 r82527 128 128 129 129 /* Adds a host data read request message to the client's message queue. */ 130 static void testMsgAddReadData(PSHCLCLIENT pClient, uint32_t uFormat) 131 { 132 SHCLDATAREQ dataReq; 133 RT_ZERO(dataReq); 134 135 dataReq.uFmt = uFormat; 136 137 int rc = ShClSvcDataReadRequest(pClient, &dataReq, NULL /* puEvent */); 130 static void testMsgAddReadData(PSHCLCLIENT pClient, uint32_t fFormat) 131 { 132 int rc = ShClSvcDataReadRequest(pClient, fFormat, NULL /* puEvent */); 138 133 RTTESTI_CHECK_RC_OK(rc); 139 134 }
Note:
See TracChangeset
for help on using the changeset viewer.