Changeset 82527 in vbox for trunk/src/VBox/HostServices/SharedClipboard
- Timestamp:
- Dec 10, 2019 1:46:40 AM (5 years ago)
- svn:sync-xref-src-repo-rev:
- 135389
- Location:
- trunk/src/VBox/HostServices/SharedClipboard
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
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.