Changeset 92735 in vbox for trunk/src/VBox
- Timestamp:
- Dec 3, 2021 4:03:24 PM (3 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxClipboard.cpp
r91746 r92735 5 5 6 6 /* 7 * Copyright (C) 2006-202 0Oracle Corporation7 * Copyright (C) 2006-2021 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 160 160 /* The IDataObject *must* be created on the same thread as our (proxy) window, so post a message to it 161 161 * to do the stuff for us. */ 162 const SHCLEVENTID idEvent = ShClEventIdGenerateAndRegister(&pTransfer->Events); 163 if (idEvent != NIL_SHCLEVENTID) 162 PSHCLEVENT pEvent; 163 rc = ShClEventSourceGenerateAndRegisterEvent(&pTransfer->Events, &pEvent); 164 if (RT_SUCCESS(rc)) 164 165 { 165 166 /* Don't want to rely on SendMessage (synchronous) here, so just post and wait the event getting signalled. */ 166 ::PostMessage(pCtx->Win.hWnd, SHCL_WIN_WM_TRANSFER_START, (WPARAM)pTransfer, (LPARAM) idEvent);167 ::PostMessage(pCtx->Win.hWnd, SHCL_WIN_WM_TRANSFER_START, (WPARAM)pTransfer, (LPARAM)pEvent->idEvent); 167 168 168 169 PSHCLEVENTPAYLOAD pPayload; 169 rc = ShClEventWait( &pTransfer->Events, idEvent, 30 * 1000 /* Timeout in ms */, &pPayload);170 rc = ShClEventWait(pEvent, 30 * 1000 /* Timeout in ms */, &pPayload); 170 171 if (RT_SUCCESS(rc)) 171 172 { … … 176 177 } 177 178 178 ShClEvent Unregister(&pTransfer->Events, idEvent);179 ShClEventRelease(pEvent); 179 180 } 180 181 else -
trunk/src/VBox/GuestHost/SharedClipboard/clipboard-common.cpp
r91630 r92735 7 7 * Includes contributions from François Revol 8 8 * 9 * Copyright (C) 2006-202 0Oracle Corporation9 * Copyright (C) 2006-2021 Oracle Corporation 10 10 * 11 11 * This file is part of VirtualBox Open Source Edition (OSE), as … … 38 38 * Prototypes * 39 39 *********************************************************************************************************************************/ 40 static void shClEventSourceResetInternal(PSHCLEVENTSOURCE pSource); 41 42 static void shClEventDestroy(PSHCLEVENT pEvent); 40 43 DECLINLINE(PSHCLEVENT) shclEventGet(PSHCLEVENTSOURCE pSource, SHCLEVENTID idEvent); 41 44 … … 103 106 104 107 /** 105 * Destroys an event, but doesn't free the memory.106 *107 * @param pEvent Event to destroy.108 */109 static void shClEventTerm(PSHCLEVENT pEvent)110 {111 if (!pEvent)112 return;113 114 AssertMsgReturnVoid(pEvent->cRefs == 0, ("Event %RU32 still has %RU32 references\n",115 pEvent->idEvent, pEvent->cRefs));116 117 LogFlowFunc(("Event %RU32\n", pEvent->idEvent));118 119 if (pEvent->hEvtMulSem != NIL_RTSEMEVENT)120 {121 RTSemEventMultiDestroy(pEvent->hEvtMulSem);122 pEvent->hEvtMulSem = NIL_RTSEMEVENT;123 }124 125 ShClPayloadFree(pEvent->pPayload);126 127 pEvent->idEvent = 0;128 }129 130 /**131 108 * Creates a new event source. 132 109 * … … 140 117 AssertPtrReturn(pSource, VERR_INVALID_POINTER); 141 118 119 int rc = RTCritSectInit(&pSource->CritSect); 120 AssertRCReturn(rc, rc); 121 142 122 RTListInit(&pSource->lstEvents); 143 123 … … 152 132 * Destroys an event source. 153 133 * 134 * @returns VBox status code. 154 135 * @param pSource Event source to destroy. 155 136 */ 156 voidShClEventSourceDestroy(PSHCLEVENTSOURCE pSource)137 int ShClEventSourceDestroy(PSHCLEVENTSOURCE pSource) 157 138 { 158 139 if (!pSource) 159 return ;140 return VINF_SUCCESS; 160 141 161 142 LogFlowFunc(("ID=%RU32\n", pSource->uID)); 162 143 163 ShClEventSourceReset(pSource); 164 165 pSource->uID = UINT16_MAX; 166 pSource->idNextEvent = UINT32_MAX; 167 } 168 169 /** 170 * Resets an event source. 144 int rc = RTCritSectEnter(&pSource->CritSect); 145 if (RT_SUCCESS(rc)) 146 { 147 shClEventSourceResetInternal(pSource); 148 149 rc = RTCritSectLeave(&pSource->CritSect); 150 AssertRC(rc); 151 152 RTCritSectDelete(&pSource->CritSect); 153 154 pSource->uID = UINT16_MAX; 155 pSource->idNextEvent = UINT32_MAX; 156 } 157 158 return rc; 159 } 160 161 /** 162 * Resets an event source, internal version. 171 163 * 172 164 * @param pSource Event source to reset. 173 165 */ 174 void ShClEventSourceReset(PSHCLEVENTSOURCE pSource)166 static void shClEventSourceResetInternal(PSHCLEVENTSOURCE pSource) 175 167 { 176 168 LogFlowFunc(("ID=%RU32\n", pSource->uID)); … … 182 174 RTListNodeRemove(&pEvIt->Node); 183 175 184 shClEvent Term(pEvIt);176 shClEventDestroy(pEvIt); 185 177 186 178 RTMemFree(pEvIt); … … 190 182 191 183 /** 184 * Resets an event source. 185 * 186 * @param pSource Event source to reset. 187 */ 188 void ShClEventSourceReset(PSHCLEVENTSOURCE pSource) 189 { 190 int rc2 = RTCritSectEnter(&pSource->CritSect); 191 if (RT_SUCCESS(rc2)) 192 { 193 shClEventSourceResetInternal(pSource); 194 195 rc2 = RTCritSectLeave(&pSource->CritSect); 196 AssertRC(rc2); 197 } 198 } 199 200 /** 192 201 * Generates a new event ID for a specific event source and registers it. 193 202 * 194 * @returns New event ID generated, or NIL_SHCLEVENTID on error.203 * @returns VBox status code. 195 204 * @param pSource Event source to generate event for. 196 */ 197 SHCLEVENTID ShClEventIdGenerateAndRegister(PSHCLEVENTSOURCE pSource) 198 { 199 AssertPtrReturn(pSource, NIL_SHCLEVENTID); 200 201 /* 202 * Allocate an event. 203 */ 205 * @param ppEvent Where to return the new event generated on success. 206 */ 207 int ShClEventSourceGenerateAndRegisterEvent(PSHCLEVENTSOURCE pSource, PSHCLEVENT *ppEvent) 208 { 209 AssertPtrReturn(pSource, VERR_INVALID_POINTER); 210 AssertPtrReturn(ppEvent, VERR_INVALID_POINTER); 211 204 212 PSHCLEVENT pEvent = (PSHCLEVENT)RTMemAllocZ(sizeof(SHCLEVENT)); 205 AssertReturn(pEvent, NIL_SHCLEVENTID);213 AssertReturn(pEvent, VERR_NO_MEMORY); 206 214 int rc = RTSemEventMultiCreate(&pEvent->hEvtMulSem); 207 AssertRCReturnStmt(rc, RTMemFree(pEvent), NIL_SHCLEVENTID); 208 209 /* 210 * Allocate an unique event ID. 211 */ 212 for (uint32_t cTries = 0;; cTries++) 213 { 214 SHCLEVENTID idEvent = ++pSource->idNextEvent; 215 if (idEvent < VBOX_SHCL_MAX_EVENTS) 216 { /* likely */ } 217 else 218 pSource->idNextEvent = idEvent = 1; /* zero == error, remember! */ 219 220 if (shclEventGet(pSource, idEvent) == NULL) 221 { 222 pEvent->idEvent = idEvent; 223 RTListAppend(&pSource->lstEvents, &pEvent->Node); 224 225 LogFlowFunc(("uSource=%RU16: New event: %#x\n", pSource->uID, idEvent)); 226 return idEvent; 227 } 228 229 AssertBreak(cTries < 4096); 215 if (RT_SUCCESS(rc)) 216 { 217 rc = RTCritSectEnter(&pSource->CritSect); 218 if (RT_SUCCESS(rc)) 219 { 220 /* 221 * Allocate an unique event ID. 222 */ 223 for (uint32_t cTries = 0;; cTries++) 224 { 225 SHCLEVENTID idEvent = ++pSource->idNextEvent; 226 if (idEvent < VBOX_SHCL_MAX_EVENTS) 227 { /* likely */ } 228 else 229 pSource->idNextEvent = idEvent = 1; /* zero == error, remember! */ 230 231 if (shclEventGet(pSource, idEvent) == NULL) 232 { 233 pEvent->pParent = pSource; 234 pEvent->idEvent = idEvent; 235 RTListAppend(&pSource->lstEvents, &pEvent->Node); 236 237 rc = RTCritSectLeave(&pSource->CritSect); 238 AssertRC(rc); 239 240 LogFlowFunc(("uSource=%RU16: New event: %#x\n", pSource->uID, idEvent)); 241 242 *ppEvent = pEvent; 243 244 return VINF_SUCCESS; 245 } 246 247 AssertBreak(cTries < 4096); 248 } 249 250 rc = RTCritSectLeave(&pSource->CritSect); 251 AssertRC(rc); 252 } 230 253 } 231 254 … … 235 258 pEvent->hEvtMulSem = NIL_RTSEMEVENTMULTI; 236 259 RTMemFree(pEvent); 237 return NIL_SHCLEVENTID; 260 return rc; 261 } 262 263 /** 264 * Destroys an event. 265 * 266 * @param pEvent Event to destroy. 267 */ 268 static void shClEventDestroy(PSHCLEVENT pEvent) 269 { 270 if (!pEvent) 271 return; 272 273 AssertMsgReturnVoid(pEvent->cRefs == 0, ("Event %RU32 still has %RU32 references\n", 274 pEvent->idEvent, pEvent->cRefs)); 275 276 LogFlowFunc(("Event %RU32\n", pEvent->idEvent)); 277 278 if (pEvent->hEvtMulSem != NIL_RTSEMEVENT) 279 { 280 RTSemEventMultiDestroy(pEvent->hEvtMulSem); 281 pEvent->hEvtMulSem = NIL_RTSEMEVENT; 282 } 283 284 ShClPayloadFree(pEvent->pPayload); 285 286 pEvent->idEvent = NIL_SHCLEVENTID; 287 } 288 289 /** 290 * Unregisters an event. 291 * 292 * @returns VBox status code. 293 * @param pSource Event source to unregister event for. 294 * @param pEvent Event to unregister. On success the pointer will be invalid. 295 */ 296 static int shClEventSourceUnregisterEventInternal(PSHCLEVENTSOURCE pSource, PSHCLEVENT pEvent) 297 { 298 LogFlowFunc(("idEvent=%RU32, cRefs=%RU32\n", pEvent->idEvent, pEvent->cRefs)); 299 300 AssertReturn(pEvent->cRefs == 0, VERR_WRONG_ORDER); 301 302 int rc = RTCritSectEnter(&pSource->CritSect); 303 if (RT_SUCCESS(rc)) 304 { 305 RTListNodeRemove(&pEvent->Node); 306 307 shClEventDestroy(pEvent); 308 309 rc = RTCritSectLeave(&pSource->CritSect); 310 if (RT_SUCCESS(rc)) 311 { 312 RTMemFree(pEvent); 313 pEvent = NULL; 314 } 315 } 316 317 return rc; 238 318 } 239 319 … … 262 342 * @returns Pointer to event if found, or NULL if not found. 263 343 * @param pSource Event source to get event from. 264 * @param uID Event ID to get. 265 */ 266 PSHCLEVENT ShClEventGet(PSHCLEVENTSOURCE pSource, SHCLEVENTID idEvent) 267 { 268 return shclEventGet(pSource, idEvent); 344 * @param idEvent ID of event to return. 345 */ 346 PSHCLEVENT ShClEventSourceGetFromId(PSHCLEVENTSOURCE pSource, SHCLEVENTID idEvent) 347 { 348 AssertPtrReturn(pSource, NULL); 349 350 int rc = RTCritSectEnter(&pSource->CritSect); 351 if (RT_SUCCESS(rc)) 352 { 353 PSHCLEVENT pEvent = shclEventGet(pSource, idEvent); 354 355 rc = RTCritSectLeave(&pSource->CritSect); 356 AssertRC(rc); 357 358 return pEvent; 359 } 360 361 return NULL; 269 362 } 270 363 … … 272 365 * Returns the last (newest) event ID which has been registered for an event source. 273 366 * 274 * @returns Last registered event ID, or 0if not found.367 * @returns Pointer to last registered event, or NULL if not found. 275 368 * @param pSource Event source to get last registered event from. 276 369 */ 277 SHCLEVENTID ShClEventGetLast(PSHCLEVENTSOURCE pSource) 278 { 279 AssertPtrReturn(pSource, 0); 280 PSHCLEVENT pEvent = RTListGetLast(&pSource->lstEvents, SHCLEVENT, Node); 281 if (pEvent) 282 return pEvent->idEvent; 283 284 return 0; 370 PSHCLEVENT ShClEventSourceGetLast(PSHCLEVENTSOURCE pSource) 371 { 372 AssertPtrReturn(pSource, NULL); 373 374 int rc = RTCritSectEnter(&pSource->CritSect); 375 if (RT_SUCCESS(rc)) 376 { 377 PSHCLEVENT pEvent = RTListGetLast(&pSource->lstEvents, SHCLEVENT, Node); 378 379 rc = RTCritSectLeave(&pSource->CritSect); 380 AssertRC(rc); 381 382 return pEvent; 383 } 384 385 return NULL; 285 386 } 286 387 … … 292 393 * @param idEvent Event ID to return reference count for. 293 394 */ 294 uint32_t ShClEventGetRefs(PSHCLEVENTSOURCE pSource, SHCLEVENTID idEvent) 295 { 296 PSHCLEVENT pEvent = shclEventGet(pSource, idEvent); 297 if (pEvent) 298 return pEvent->cRefs; 299 300 AssertMsgFailed(("No event with %RU32\n", idEvent)); 301 return 0; 395 uint32_t ShClEventGetRefs(PSHCLEVENT pEvent) 396 { 397 AssertPtrReturn(pEvent, 0); 398 399 return ASMAtomicReadU32(&pEvent->cRefs); 302 400 } 303 401 … … 322 420 323 421 /** 324 * Unregisters an event.422 * Waits for an event to get signalled. 325 423 * 326 424 * @returns VBox status code. 327 * @param pSource Event source to unregister event for. 328 * @param uID Event ID to unregister. 329 * 330 * @todo r=bird: The caller must enter crit sect protecting the event source 331 * here, must it? See explanation in ShClEventWait. 332 */ 333 int ShClEventUnregister(PSHCLEVENTSOURCE pSource, SHCLEVENTID uID) 334 { 335 AssertPtrReturn(pSource, VERR_INVALID_POINTER); 336 337 int rc; 338 339 LogFlowFunc(("uSource=%RU16, uEvent=%RU32\n", pSource->uID, uID)); 340 341 PSHCLEVENT pEvent = shclEventGet(pSource, uID); 342 if (pEvent) 343 { 344 LogFlowFunc(("Event %RU32\n", pEvent->idEvent)); 345 346 RTListNodeRemove(&pEvent->Node); 347 348 shClEventTerm(pEvent); 349 350 RTMemFree(pEvent); 351 pEvent = NULL; 352 353 rc = VINF_SUCCESS; 354 } 355 else 356 rc = VERR_NOT_FOUND; 357 358 LogFlowFuncLeaveRC(rc); 359 return rc; 360 } 361 362 /** 363 * Waits for an event to get signalled. 364 * 365 * @returns VBox status code. 366 * @param pSource Event source that contains the event to wait for. 367 * @param uID Event ID to wait for. 425 * @param pEvent Event to wait for. 368 426 * @param uTimeoutMs Timeout (in ms) to wait. 369 427 * @param ppPayload Where to store the (allocated) event payload on success. Needs to be free'd with 370 428 * SharedClipboardPayloadFree(). Optional. 371 * 372 * @todo r=bird: Locking protocol is totally buggered here, or at least not 373 * explained in any way whatsoever. We cannot really do shclEventGet 374 * and shclEventPayloadDetachInternal w/o holding the critical section 375 * protecting that list, otherwise wtf is the point of the locking. 376 * 377 * More to the point, ShClEventSignal is called on the HGCM service 378 * thread and would be racing the host clipboard worker thread/whomever 379 * sent the request and is making this call closely followed by 380 * ShClEventRelease and ShClEventUnregister. The waiting here might be 381 * safe if there can only ever be one single thread making these kind 382 * of requests, but the unregistering is _not_ safe w/o holding the 383 * lock and that isn't explained anywhere that I can see. 384 */ 385 int ShClEventWait(PSHCLEVENTSOURCE pSource, SHCLEVENTID uID, RTMSINTERVAL uTimeoutMs, PSHCLEVENTPAYLOAD *ppPayload) 386 { 387 AssertPtrReturn(pSource, VERR_INVALID_POINTER); 429 */ 430 int ShClEventWait(PSHCLEVENT pEvent, RTMSINTERVAL uTimeoutMs, PSHCLEVENTPAYLOAD *ppPayload) 431 { 432 AssertPtrReturn(pEvent, VERR_INVALID_POINTER); 388 433 AssertPtrNullReturn(ppPayload, VERR_INVALID_POINTER); 389 434 LogFlowFuncEnter(); 390 435 391 int rc; 392 393 PSHCLEVENT pEvent = shclEventGet(pSource, uID); 394 if (pEvent) 395 { 396 rc = RTSemEventMultiWait(pEvent->hEvtMulSem, uTimeoutMs); 397 if (RT_SUCCESS(rc)) 398 { 399 if (ppPayload) 400 { 401 /* Make sure to detach payload here, as the caller now owns the data. */ 402 *ppPayload = shclEventPayloadDetachInternal(pEvent); 403 } 404 } 405 406 if (RT_FAILURE(rc)) 407 LogRel2(("Shared Clipboard: Waiting for event %RU32 failed, rc=%Rrc\n", uID, rc)); 408 } 409 else 410 rc = VERR_NOT_FOUND; 436 int rc = RTSemEventMultiWait(pEvent->hEvtMulSem, uTimeoutMs); 437 if (RT_SUCCESS(rc)) 438 { 439 if (ppPayload) 440 { 441 /* Make sure to detach payload here, as the caller now owns the data. */ 442 *ppPayload = shclEventPayloadDetachInternal(pEvent); 443 } 444 } 445 446 if (RT_FAILURE(rc)) 447 LogRel2(("Shared Clipboard: Waiting for event %RU32 failed, rc=%Rrc\n", pEvent->idEvent, rc)); 411 448 412 449 LogFlowFuncLeaveRC(rc); … … 418 455 * 419 456 * @returns New reference count, or UINT32_MAX if failed. 420 * @param pSource Event source of event to retain. 421 * @param idEvent ID of event to retain. 422 */ 423 uint32_t ShClEventRetain(PSHCLEVENTSOURCE pSource, SHCLEVENTID idEvent) 424 { 425 PSHCLEVENT pEvent = shclEventGet(pSource, idEvent); 457 * @param pEvent Event to retain. 458 */ 459 uint32_t ShClEventRetain(PSHCLEVENT pEvent) 460 { 461 AssertPtrReturn(pEvent, UINT32_MAX); 462 AssertReturn(ASMAtomicReadU32(&pEvent->cRefs) < 64, UINT32_MAX); 463 return ASMAtomicIncU32(&pEvent->cRefs); 464 } 465 466 /** 467 * Releases an event by decreasing its reference count. 468 * 469 * @returns New reference count, or UINT32_MAX if failed. 470 * @param pEvent Event to release. 471 * If the reference count reaches 0, the event will 472 * be destroyed and \a pEvent will be invalid. 473 */ 474 uint32_t ShClEventRelease(PSHCLEVENT pEvent) 475 { 426 476 if (!pEvent) 427 { 428 AssertFailed(); 429 return UINT32_MAX; 430 } 431 432 AssertReturn(pEvent->cRefs < 64, UINT32_MAX); /* Sanity. Yeah, not atomic. */ 433 434 return ASMAtomicIncU32(&pEvent->cRefs); 435 } 436 437 /** 438 * Releases an event by decreasing its reference count. 439 * 440 * @returns New reference count, or UINT32_MAX if failed. 441 * @param pSource Event source of event to release. 442 * @param idEvent ID of event to release. 443 * 444 * @todo r=bird: The two places this is currently used make my head explode. 445 * First you release then you unregister it. Unregister frees is 446 * unconditionally. 447 * 448 * Any sane thinking person would assume that after we've release our 449 * reference to the @a idEvent, we cannot touch it any more because we 450 * don't have a valid reference any more. So, when ShClEventUnregister 451 * is then called and unconditionally frees the event: Boooooom! 452 * 453 * The locking interface here is generally not sane either, as the 454 * locking isn't done on the @a pSource but something the caller needs 455 * implements. Since we don't have access to the lock we cannot verify 456 * the locking protocol nor can we implement it (like in 457 * ShClEventWait). 458 * 459 * A better interface would return PSHCLEVENT instead of SHCLEVENTID, 460 * and then you could work directly on that as an object, rather via a 461 * slow object list. It would eliminate shclEventGet and any though 462 * that someone might be updating the list while shclEventGet traverses 463 * it. 464 */ 465 uint32_t ShClEventRelease(PSHCLEVENTSOURCE pSource, SHCLEVENTID idEvent) 466 { 467 PSHCLEVENT pEvent = shclEventGet(pSource, idEvent); 468 AssertReturn(pEvent, UINT32_MAX); 469 AssertReturn(pEvent->cRefs, UINT32_MAX); /* Sanity. Yeah, not atomic. */ 470 471 return ASMAtomicDecU32(&pEvent->cRefs); 477 return 0; 478 479 AssertReturn(ASMAtomicReadU32(&pEvent->cRefs) > 0, UINT32_MAX); 480 481 uint32_t const cRefs = ASMAtomicDecU32(&pEvent->cRefs); 482 if (cRefs == 0) 483 { 484 AssertPtr(pEvent->pParent); 485 int rc2 = shClEventSourceUnregisterEventInternal(pEvent->pParent, pEvent); 486 AssertRC(rc2); 487 488 return RT_SUCCESS(rc2) ? 0 : UINT32_MAX; 489 } 490 491 return cRefs; 472 492 } 473 493 … … 476 496 * 477 497 * @returns VBox status code. 478 * @param pSource Event source of event to signal. 479 * @param uID Event ID to signal. 498 * @param pEvent Event to signal. 480 499 * @param pPayload Event payload to associate. Takes ownership on 481 500 * success. Optional. 482 * 483 * @note Caller must enter crit sect protecting the event source! 484 */ 485 int ShClEventSignal(PSHCLEVENTSOURCE pSource, SHCLEVENTID uID, PSHCLEVENTPAYLOAD pPayload) 486 { 487 AssertPtrReturn(pSource, VERR_INVALID_POINTER); 488 489 int rc; 490 491 LogFlowFunc(("uSource=%RU16, uEvent=%RU32\n", pSource->uID, uID)); 492 493 PSHCLEVENT pEvent = shclEventGet(pSource, uID); 494 if (pEvent) 495 { 496 Assert(pEvent->pPayload == NULL); 497 498 pEvent->pPayload = pPayload; 499 500 rc = RTSemEventMultiSignal(pEvent->hEvtMulSem); 501 if (RT_FAILURE(rc)) 502 pEvent->pPayload = NULL; /* (no race condition if consumer also enters the critical section) */ 503 } 504 else 505 rc = VERR_NOT_FOUND; 501 */ 502 int ShClEventSignal(PSHCLEVENT pEvent, PSHCLEVENTPAYLOAD pPayload) 503 { 504 AssertPtrReturn(pEvent, VERR_INVALID_POINTER); 505 506 Assert(pEvent->pPayload == NULL); 507 508 pEvent->pPayload = pPayload; 509 510 int rc = RTSemEventMultiSignal(pEvent->hEvtMulSem); 511 if (RT_FAILURE(rc)) 512 pEvent->pPayload = NULL; /* (no race condition if consumer also enters the critical section) */ 506 513 507 514 LogFlowFuncLeaveRC(rc); -
trunk/src/VBox/GuestHost/SharedClipboard/clipboard-transfers.cpp
r87658 r92735 5 5 6 6 /* 7 * Copyright (C) 2019-202 0Oracle Corporation7 * Copyright (C) 2019-2021 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 1079 1079 1080 1080 /** 1081 * Duplica ates a transfer object data chunk.1081 * Duplicates a transfer object data chunk. 1082 1082 * 1083 1083 * @returns Duplicated object data chunk on success, or NULL on failure. … … 1158 1158 LogFlowFuncEnter(); 1159 1159 1160 PSHCLTRANSFER pTransfer = (PSHCLTRANSFER)RTMemAlloc(sizeof(SHCLTRANSFER)); 1161 if (!pTransfer) 1162 return VERR_NO_MEMORY; 1163 1164 int rc = VINF_SUCCESS; 1160 PSHCLTRANSFER pTransfer = (PSHCLTRANSFER)RTMemAllocZ(sizeof(SHCLTRANSFER)); 1161 AssertPtrReturn(pTransfer, VERR_NO_MEMORY); 1165 1162 1166 1163 pTransfer->State.uID = 0; … … 1181 1178 pTransfer->uTimeoutMs = RT_MS_30SEC; 1182 1179 #endif 1183 pTransfer->cbMaxChunkSize = _64K; /** @todo Make this configurable. */ 1180 pTransfer->cbMaxChunkSize = _64K; /** @todo Make this configurable. */ 1181 pTransfer->cMaxListHandles = _4K; /** @todo Ditto. */ 1182 pTransfer->cMaxObjHandles = _4K; /** @todo Ditto. */ 1184 1183 1185 1184 pTransfer->pvUser = NULL; … … 1192 1191 RTListInit(&pTransfer->lstRoots); 1193 1192 1194 RTListInit(&pTransfer->Events.lstEvents); 1195 pTransfer->Events.uID = 0; 1196 pTransfer->Events.idNextEvent = 1; 1197 1193 int rc = ShClEventSourceCreate(&pTransfer->Events, 0 /* uID */); 1198 1194 if (RT_SUCCESS(rc)) 1199 1195 { … … 1248 1244 int ShClTransferInit(PSHCLTRANSFER pTransfer, SHCLTRANSFERDIR enmDir, SHCLSOURCE enmSource) 1249 1245 { 1250 pTransfer->State.uID = 0;1251 1246 pTransfer->State.enmDir = enmDir; 1252 1247 pTransfer->State.enmSource = enmSource; … … 1255 1250 pTransfer->State.uID, pTransfer->State.enmDir, pTransfer->State.enmSource)); 1256 1251 1257 int rc = ShClEventSourceCreate(&pTransfer->Events, pTransfer->State.uID); 1258 if (RT_SUCCESS(rc)) 1259 { 1260 pTransfer->State.enmStatus = SHCLTRANSFERSTATUS_INITIALIZED; /* Now we're ready to run. */ 1261 1262 pTransfer->cListHandles = 0; 1263 pTransfer->cMaxListHandles = _4K; /** @todo Make this dynamic. */ 1264 pTransfer->uListHandleNext = 1; 1265 1266 pTransfer->cObjHandles = 0; 1267 pTransfer->cMaxObjHandles = _4K; /** @todo Ditto. */ 1268 pTransfer->uObjHandleNext = 1; 1269 1270 if (pTransfer->Callbacks.pfnOnInitialize) 1271 rc = pTransfer->Callbacks.pfnOnInitialize(&pTransfer->CallbackCtx); 1272 } 1252 pTransfer->State.enmStatus = SHCLTRANSFERSTATUS_INITIALIZED; /* Now we're ready to run. */ 1253 1254 pTransfer->cListHandles = 0; 1255 pTransfer->uListHandleNext = 1; 1256 1257 pTransfer->cObjHandles = 0; 1258 pTransfer->uObjHandleNext = 1; 1259 1260 int rc = VINF_SUCCESS; 1261 1262 if (pTransfer->Callbacks.pfnOnInitialize) 1263 rc = pTransfer->Callbacks.pfnOnInitialize(&pTransfer->CallbackCtx); 1273 1264 1274 1265 LogFlowFuncLeaveRC(rc); … … 3048 3039 #ifdef RT_OS_WINDOWS 3049 3040 if ((fShClFlags & SHCL_OBJ_CF_ACCESS_MASK_ATTR) != SHCL_OBJ_CF_ACCESS_ATTR_NONE) 3050 fOpen |= RTFILE_O_ ATTR_ONLY;3041 fOpen |= RTFILE_O_OPEN | RTFILE_O_ATTR_ONLY; 3051 3042 else 3052 3043 #endif 3053 fOpen |= RTFILE_O_ READ;3044 fOpen |= RTFILE_O_OPEN | RTFILE_O_READ; 3054 3045 LogFlowFunc(("SHCL_OBJ_CF_ACCESS_NONE\n")); 3055 3046 break; … … 3058 3049 case SHCL_OBJ_CF_ACCESS_READ: 3059 3050 { 3060 fOpen |= RTFILE_O_ READ;3051 fOpen |= RTFILE_O_OPEN | RTFILE_O_READ; 3061 3052 LogFlowFunc(("SHCL_OBJ_CF_ACCESS_READ\n")); 3062 3053 break; -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-internal.h
r91749 r92735 5 5 6 6 /* 7 * Copyright (C) 2006-202 0Oracle Corporation7 * Copyright (C) 2006-2021 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 293 293 * @{ 294 294 */ 295 int ShClSvcGuestDataRequest(PSHCLCLIENT pClient, SHCLFORMATS fFormats, PSHCLEVENT ID pidEvent);295 int ShClSvcGuestDataRequest(PSHCLCLIENT pClient, SHCLFORMATS fFormats, PSHCLEVENT *ppEvent); 296 296 int ShClSvcGuestDataSignal(PSHCLCLIENT pClient, PSHCLCLIENTCMDCTX pCmdCtx, SHCLFORMAT uFormat, void *pvData, uint32_t cbData); 297 297 int ShClSvcHostReportFormats(PSHCLCLIENT pClient, SHCLFORMATS fFormats); -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-transfers.cpp
r87658 r92735 5 5 6 6 /* 7 * Copyright (C) 2019-202 0Oracle Corporation7 * Copyright (C) 2019-2021 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 100 100 if (pMsgHdr) 101 101 { 102 SHCLEVENTID idEvent = ShClEventIdGenerateAndRegister(&pCtx->pTransfer->Events); 103 if (idEvent != NIL_SHCLEVENTID) 102 PSHCLEVENT pEvent; 103 rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvent); 104 if (RT_SUCCESS(rc)) 104 105 { 105 106 HGCMSvcSetU64(&pMsgHdr->aParms[0], VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID, 106 pCtx->pTransfer->State.uID, idEvent));107 pCtx->pTransfer->State.uID, pEvent->idEvent)); 107 108 HGCMSvcSetU32(&pMsgHdr->aParms[1], 0 /* fRoots */); 108 109 … … 117 118 { 118 119 PSHCLEVENTPAYLOAD pPayloadHdr; 119 rc = ShClEventWait(&pCtx->pTransfer->Events, idEvent, 120 pCtx->pTransfer->uTimeoutMs, &pPayloadHdr); 120 rc = ShClEventWait(pEvent, pCtx->pTransfer->uTimeoutMs, &pPayloadHdr); 121 121 if (RT_SUCCESS(rc)) 122 122 { … … 141 141 VBOX_SHCL_CPARMS_ROOT_LIST_ENTRY_READ_REQ); 142 142 143 idEvent = ShClEventIdGenerateAndRegister(&pCtx->pTransfer->Events); 144 if (idEvent != NIL_SHCLEVENTID) 143 PSHCLEVENT pEvRoot; 144 rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvRoot); 145 if (RT_SUCCESS(rc)) 145 146 { 146 147 HGCMSvcSetU64(&pMsgEntry->aParms[0], 147 148 VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uClientID, 148 pCtx->pTransfer->State.uID, idEvent));149 pCtx->pTransfer->State.uID, pEvRoot->idEvent)); 149 150 HGCMSvcSetU32(&pMsgEntry->aParms[1], 0 /* fRoots */); 150 151 HGCMSvcSetU32(&pMsgEntry->aParms[2], i /* uIndex */); … … 155 156 156 157 PSHCLEVENTPAYLOAD pPayloadEntry; 157 rc = ShClEventWait(&pCtx->pTransfer->Events, idEvent, 158 pCtx->pTransfer->uTimeoutMs, &pPayloadEntry); 158 rc = ShClEventWait(pEvent, pCtx->pTransfer->uTimeoutMs, &pPayloadEntry); 159 159 if (RT_FAILURE(rc)) 160 160 break; … … 167 167 ShClPayloadFree(pPayloadEntry); 168 168 169 ShClEventUnregister(&pCtx->pTransfer->Events, idEvent); 169 ShClEventRelease(pEvRoot); 170 pEvRoot = NULL; 170 171 } 171 172 else … … 197 198 } 198 199 199 ShClEvent Unregister(&pCtx->pTransfer->Events, idEvent);200 ShClEventRelease(pEvent); 200 201 } 201 202 else … … 223 224 if (pMsg) 224 225 { 225 const SHCLEVENTID idEvent = ShClEventIdGenerateAndRegister(&pCtx->pTransfer->Events); 226 if (idEvent != NIL_SHCLEVENTID) 226 PSHCLEVENT pEvent; 227 rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvent); 228 if (RT_SUCCESS(rc)) 227 229 { 228 230 pMsg->idCtx = VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID, pCtx->pTransfer->State.uID, 229 idEvent);231 pEvent->idEvent); 230 232 231 233 rc = shClSvcTransferSetListOpen(pMsg->cParms, pMsg->aParms, pMsg->idCtx, pOpenParms); … … 238 240 { 239 241 PSHCLEVENTPAYLOAD pPayload; 240 rc = ShClEventWait( &pCtx->pTransfer->Events, idEvent, pCtx->pTransfer->uTimeoutMs, &pPayload);242 rc = ShClEventWait(pEvent, pCtx->pTransfer->uTimeoutMs, &pPayload); 241 243 if (RT_SUCCESS(rc)) 242 244 { … … 257 259 } 258 260 259 ShClEvent Unregister(&pCtx->pTransfer->Events, idEvent);261 ShClEventRelease(pEvent); 260 262 } 261 263 else … … 282 284 if (pMsg) 283 285 { 284 const SHCLEVENTID idEvent = ShClEventIdGenerateAndRegister(&pCtx->pTransfer->Events); 285 if (idEvent != NIL_SHCLEVENTID) 286 PSHCLEVENT pEvent; 287 rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvent); 288 if (RT_SUCCESS(rc)) 286 289 { 287 290 pMsg->idCtx = VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID, pCtx->pTransfer->State.uID, 288 idEvent);291 pEvent->idEvent); 289 292 290 293 rc = shClSvcTransferSetListClose(pMsg->cParms, pMsg->aParms, pMsg->idCtx, hList); … … 297 300 { 298 301 PSHCLEVENTPAYLOAD pPayload; 299 rc = ShClEventWait( &pCtx->pTransfer->Events, idEvent, pCtx->pTransfer->uTimeoutMs, &pPayload);302 rc = ShClEventWait(pEvent, pCtx->pTransfer->uTimeoutMs, &pPayload); 300 303 if (RT_SUCCESS(rc)) 301 304 ShClPayloadFree(pPayload); … … 303 306 } 304 307 305 ShClEvent Unregister(&pCtx->pTransfer->Events, idEvent);308 ShClEventRelease(pEvent); 306 309 } 307 310 else … … 329 332 if (pMsg) 330 333 { 331 const SHCLEVENTID idEvent = ShClEventIdGenerateAndRegister(&pCtx->pTransfer->Events); 332 if (idEvent != NIL_SHCLEVENTID) 334 PSHCLEVENT pEvent; 335 rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvent); 336 if (RT_SUCCESS(rc)) 333 337 { 334 338 HGCMSvcSetU64(&pMsg->aParms[0], VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID, 335 pCtx->pTransfer->State.uID, idEvent));339 pCtx->pTransfer->State.uID, pEvent->idEvent)); 336 340 HGCMSvcSetU64(&pMsg->aParms[1], hList); 337 341 HGCMSvcSetU32(&pMsg->aParms[2], 0 /* fFlags */); … … 343 347 { 344 348 PSHCLEVENTPAYLOAD pPayload; 345 rc = ShClEventWait(&pCtx->pTransfer->Events, idEvent, 346 pCtx->pTransfer->uTimeoutMs, &pPayload); 349 rc = ShClEventWait(pEvent, pCtx->pTransfer->uTimeoutMs, &pPayload); 347 350 if (RT_SUCCESS(rc)) 348 351 { … … 355 358 } 356 359 357 ShClEvent Unregister(&pCtx->pTransfer->Events, idEvent);360 ShClEventRelease(pEvent); 358 361 } 359 362 else … … 391 394 if (pMsg) 392 395 { 393 const SHCLEVENTID idEvent = ShClEventIdGenerateAndRegister(&pCtx->pTransfer->Events); 394 if (idEvent != NIL_SHCLEVENTID) 396 PSHCLEVENT pEvent; 397 rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvent); 398 if (RT_SUCCESS(rc)) 395 399 { 396 400 HGCMSvcSetU64(&pMsg->aParms[0], VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID, 397 pCtx->pTransfer->State.uID, idEvent));401 pCtx->pTransfer->State.uID, pEvent->idEvent)); 398 402 HGCMSvcSetU64(&pMsg->aParms[1], hList); 399 403 HGCMSvcSetU32(&pMsg->aParms[2], 0 /* fInfo */); … … 405 409 { 406 410 PSHCLEVENTPAYLOAD pPayload; 407 rc = ShClEventWait( &pCtx->pTransfer->Events, idEvent, pCtx->pTransfer->uTimeoutMs, &pPayload);411 rc = ShClEventWait(pEvent, pCtx->pTransfer->uTimeoutMs, &pPayload); 408 412 if (RT_SUCCESS(rc)) 409 413 { … … 416 420 } 417 421 418 ShClEvent Unregister(&pCtx->pTransfer->Events, idEvent);422 ShClEventRelease(pEvent); 419 423 } 420 424 else … … 452 456 if (pMsg) 453 457 { 454 const SHCLEVENTID idEvent = ShClEventIdGenerateAndRegister(&pCtx->pTransfer->Events); 455 if (idEvent != NIL_SHCLEVENTID) 458 PSHCLEVENT pEvent; 459 rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvent); 460 if (RT_SUCCESS(rc)) 456 461 { 457 462 LogFlowFunc(("pszPath=%s, fCreate=0x%x\n", pCreateParms->pszPath, pCreateParms->fCreate)); … … 460 465 461 466 HGCMSvcSetU64(&pMsg->aParms[0], VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID, 462 pCtx->pTransfer->State.uID, idEvent));467 pCtx->pTransfer->State.uID, pEvent->idEvent)); 463 468 HGCMSvcSetU64(&pMsg->aParms[1], 0); /* uHandle */ 464 469 HGCMSvcSetU32(&pMsg->aParms[2], cbPath); … … 472 477 { 473 478 PSHCLEVENTPAYLOAD pPayload; 474 rc = ShClEventWait( &pCtx->pTransfer->Events, idEvent, pCtx->pTransfer->uTimeoutMs, &pPayload);479 rc = ShClEventWait(pEvent, pCtx->pTransfer->uTimeoutMs, &pPayload); 475 480 if (RT_SUCCESS(rc)) 476 481 { … … 490 495 } 491 496 492 ShClEvent Unregister(&pCtx->pTransfer->Events, idEvent);497 ShClEventRelease(pEvent); 493 498 } 494 499 else … … 515 520 if (pMsg) 516 521 { 517 const SHCLEVENTID idEvent = ShClEventIdGenerateAndRegister(&pCtx->pTransfer->Events); 518 if (idEvent != NIL_SHCLEVENTID) 522 PSHCLEVENT pEvent; 523 rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvent); 524 if (RT_SUCCESS(rc)) 519 525 { 520 526 HGCMSvcSetU64(&pMsg->aParms[0], VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID, 521 pCtx->pTransfer->State.uID, idEvent));527 pCtx->pTransfer->State.uID, pEvent->idEvent)); 522 528 HGCMSvcSetU64(&pMsg->aParms[1], hObj); 523 529 … … 528 534 { 529 535 PSHCLEVENTPAYLOAD pPayload; 530 rc = ShClEventWait( &pCtx->pTransfer->Events, idEvent, pCtx->pTransfer->uTimeoutMs, &pPayload);536 rc = ShClEventWait(pEvent, pCtx->pTransfer->uTimeoutMs, &pPayload); 531 537 if (RT_SUCCESS(rc)) 532 538 { … … 544 550 } 545 551 546 ShClEvent Unregister(&pCtx->pTransfer->Events, idEvent);552 ShClEventRelease(pEvent); 547 553 } 548 554 else … … 570 576 if (pMsg) 571 577 { 572 const SHCLEVENTID idEvent = ShClEventIdGenerateAndRegister(&pCtx->pTransfer->Events); 573 if (idEvent != NIL_SHCLEVENTID) 578 PSHCLEVENT pEvent; 579 rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvent); 580 if (RT_SUCCESS(rc)) 574 581 { 575 582 HGCMSvcSetU64(&pMsg->aParms[0], VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID, 576 pCtx->pTransfer->State.uID, idEvent));583 pCtx->pTransfer->State.uID, pEvent->idEvent)); 577 584 HGCMSvcSetU64(&pMsg->aParms[1], hObj); 578 585 HGCMSvcSetU32(&pMsg->aParms[2], cbData); … … 585 592 { 586 593 PSHCLEVENTPAYLOAD pPayload; 587 rc = ShClEventWait( &pCtx->pTransfer->Events, idEvent, pCtx->pTransfer->uTimeoutMs, &pPayload);594 rc = ShClEventWait(pEvent, pCtx->pTransfer->uTimeoutMs, &pPayload); 588 595 if (RT_SUCCESS(rc)) 589 596 { … … 604 611 } 605 612 606 ShClEvent Unregister(&pCtx->pTransfer->Events, idEvent);613 ShClEventRelease(pEvent); 607 614 } 608 615 else … … 630 637 if (pMsg) 631 638 { 632 const SHCLEVENTID idEvent = ShClEventIdGenerateAndRegister(&pCtx->pTransfer->Events); 633 if (idEvent != NIL_SHCLEVENTID) 639 PSHCLEVENT pEvent; 640 rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvent); 641 if (RT_SUCCESS(rc)) 634 642 { 635 643 HGCMSvcSetU64(&pMsg->aParms[0], VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID, 636 pCtx->pTransfer->State.uID, idEvent));644 pCtx->pTransfer->State.uID, pEvent->idEvent)); 637 645 HGCMSvcSetU64(&pMsg->aParms[1], hObj); 638 646 HGCMSvcSetU64(&pMsg->aParms[2], cbData); … … 645 653 { 646 654 PSHCLEVENTPAYLOAD pPayload; 647 rc = ShClEventWait( &pCtx->pTransfer->Events, idEvent, pCtx->pTransfer->uTimeoutMs, &pPayload);655 rc = ShClEventWait(pEvent, pCtx->pTransfer->uTimeoutMs, &pPayload); 648 656 if (RT_SUCCESS(rc)) 649 657 { … … 659 667 } 660 668 661 ShClEvent Unregister(&pCtx->pTransfer->Events, idEvent);669 ShClEventRelease(pEvent); 662 670 } 663 671 else … … 1191 1199 uint32_t cParms, VBOXHGCMSVCPARM aParms[]) 1192 1200 { 1193 RT_NOREF(pClient );1201 RT_NOREF(pClient, pTransfer); 1194 1202 1195 1203 int rc; … … 1225 1233 if (RT_SUCCESS(rc)) 1226 1234 { 1227 const SHCLEVENTID idEvent = VBOX_SHCL_CONTEXTID_GET_EVENT(uCID); 1228 1229 LogFlowFunc(("uCID=%RU64 -> idEvent=%RU32\n", uCID, idEvent)); 1230 1231 rc = ShClEventSignal(&pTransfer->Events, idEvent, pPayload); 1235 const PSHCLEVENT pEvent 1236 = ShClEventSourceGetFromId(&pClient->EventSrc, VBOX_SHCL_CONTEXTID_GET_EVENT(uCID)); 1237 if (pEvent) 1238 { 1239 LogFlowFunc(("uCID=%RU64 -> idEvent=%RU32\n", uCID, pEvent->idEvent)); 1240 1241 rc = ShClEventSignal(pEvent, pPayload); 1242 } 1243 /** @todo Silently skip? */ 1232 1244 } 1233 1245 break; … … 1382 1394 uint32_t cbData = sizeof(SHCLROOTLISTHDR); 1383 1395 1384 const SHCLEVENTID idEvent = VBOX_SHCL_CONTEXTID_GET_EVENT(uCID); 1385 1386 PSHCLEVENTPAYLOAD pPayload; 1387 rc = ShClPayloadAlloc(idEvent, pvData, cbData, &pPayload); 1388 if (RT_SUCCESS(rc)) 1389 { 1390 rc = ShClEventSignal(&pTransfer->Events, idEvent, pPayload); 1391 if (RT_FAILURE(rc)) 1392 ShClPayloadFree(pPayload); 1393 } 1396 const PSHCLEVENT pEvent = ShClEventSourceGetFromId(&pClient->EventSrc, VBOX_SHCL_CONTEXTID_GET_EVENT(uCID)); 1397 if (pEvent) 1398 { 1399 PSHCLEVENTPAYLOAD pPayload; 1400 rc = ShClPayloadAlloc(pEvent->idEvent, pvData, cbData, &pPayload); 1401 if (RT_SUCCESS(rc)) 1402 { 1403 rc = ShClEventSignal(pEvent, pPayload); 1404 if (RT_FAILURE(rc)) 1405 ShClPayloadFree(pPayload); 1406 } 1407 } 1408 else 1409 rc = VERR_SHCLPB_EVENT_ID_NOT_FOUND; 1394 1410 } 1395 1411 break; … … 1427 1443 uint32_t cbData = sizeof(SHCLROOTLISTENTRY); 1428 1444 1429 const SHCLEVENTID idEvent = VBOX_SHCL_CONTEXTID_GET_EVENT(uCID); 1430 1431 PSHCLEVENTPAYLOAD pPayload; 1432 rc = ShClPayloadAlloc(idEvent, pvData, cbData, &pPayload); 1433 if (RT_SUCCESS(rc)) 1434 { 1435 rc = ShClEventSignal(&pTransfer->Events, idEvent, pPayload); 1436 if (RT_FAILURE(rc)) 1437 ShClPayloadFree(pPayload); 1438 } 1445 const PSHCLEVENT pEvent = ShClEventSourceGetFromId(&pClient->EventSrc, VBOX_SHCL_CONTEXTID_GET_EVENT(uCID)); 1446 if (pEvent) 1447 { 1448 PSHCLEVENTPAYLOAD pPayload; 1449 rc = ShClPayloadAlloc(pEvent->idEvent, pvData, cbData, &pPayload); 1450 if (RT_SUCCESS(rc)) 1451 { 1452 rc = ShClEventSignal(pEvent, pPayload); 1453 if (RT_FAILURE(rc)) 1454 ShClPayloadFree(pPayload); 1455 } 1456 } 1457 else 1458 rc = VERR_SHCLPB_EVENT_ID_NOT_FOUND; 1439 1459 } 1440 1460 break; … … 1502 1522 uint32_t cbData = sizeof(SHCLLISTHDR); 1503 1523 1504 const SHCLEVENTID idEvent = VBOX_SHCL_CONTEXTID_GET_EVENT(uCID); 1505 1506 PSHCLEVENTPAYLOAD pPayload; 1507 rc = ShClPayloadAlloc(idEvent, pvData, cbData, &pPayload); 1508 if (RT_SUCCESS(rc)) 1524 const PSHCLEVENT pEvent = ShClEventSourceGetFromId(&pClient->EventSrc, VBOX_SHCL_CONTEXTID_GET_EVENT(uCID)); 1525 if (pEvent) 1509 1526 { 1510 rc = ShClEventSignal(&pTransfer->Events, idEvent, pPayload); 1511 if (RT_FAILURE(rc)) 1512 ShClPayloadFree(pPayload); 1527 PSHCLEVENTPAYLOAD pPayload; 1528 rc = ShClPayloadAlloc(pEvent->idEvent, pvData, cbData, &pPayload); 1529 if (RT_SUCCESS(rc)) 1530 { 1531 rc = ShClEventSignal(pEvent, pPayload); 1532 if (RT_FAILURE(rc)) 1533 ShClPayloadFree(pPayload); 1534 } 1513 1535 } 1536 else 1537 rc = VERR_SHCLPB_EVENT_ID_NOT_FOUND; 1514 1538 } 1515 1539 } … … 1551 1575 uint32_t cbData = sizeof(SHCLLISTENTRY); 1552 1576 1553 const SHCLEVENTID idEvent = VBOX_SHCL_CONTEXTID_GET_EVENT(uCID); 1554 1555 PSHCLEVENTPAYLOAD pPayload; 1556 rc = ShClPayloadAlloc(idEvent, pvData, cbData, &pPayload); 1557 if (RT_SUCCESS(rc)) 1577 const PSHCLEVENT pEvent = ShClEventSourceGetFromId(&pClient->EventSrc, VBOX_SHCL_CONTEXTID_GET_EVENT(uCID)); 1578 if (pEvent) 1558 1579 { 1559 rc = ShClEventSignal(&pTransfer->Events, idEvent, pPayload); 1560 if (RT_FAILURE(rc)) 1561 ShClPayloadFree(pPayload); 1580 PSHCLEVENTPAYLOAD pPayload; 1581 rc = ShClPayloadAlloc(pEvent->idEvent, pvData, cbData, &pPayload); 1582 if (RT_SUCCESS(rc)) 1583 { 1584 rc = ShClEventSignal(pEvent, pPayload); 1585 if (RT_FAILURE(rc)) 1586 ShClPayloadFree(pPayload); 1587 } 1562 1588 } 1589 else 1590 rc = VERR_SHCLPB_EVENT_ID_NOT_FOUND; 1563 1591 } 1564 1592 } … … 1656 1684 uint32_t cbData = sizeof(SHCLOBJDATACHUNK); 1657 1685 1658 const SHCLEVENTID idEvent = VBOX_SHCL_CONTEXTID_GET_EVENT(uCID); 1659 1660 PSHCLEVENTPAYLOAD pPayload; 1661 rc = ShClPayloadAlloc(idEvent, pvData, cbData, &pPayload); 1662 if (RT_SUCCESS(rc)) 1663 { 1664 rc = ShClEventSignal(&pTransfer->Events, idEvent, pPayload); 1665 if (RT_FAILURE(rc)) 1666 ShClPayloadFree(pPayload); 1667 } 1686 const PSHCLEVENT pEvent = ShClEventSourceGetFromId(&pClient->EventSrc, VBOX_SHCL_CONTEXTID_GET_EVENT(uCID)); 1687 if (pEvent) 1688 { 1689 PSHCLEVENTPAYLOAD pPayload; 1690 rc = ShClPayloadAlloc(pEvent->idEvent, pvData, cbData, &pPayload); 1691 if (RT_SUCCESS(rc)) 1692 { 1693 rc = ShClEventSignal(pEvent, pPayload); 1694 if (RT_FAILURE(rc)) 1695 ShClPayloadFree(pPayload); 1696 } 1697 } 1698 else 1699 rc = VERR_SHCLPB_EVENT_ID_NOT_FOUND; 1668 1700 } 1669 1701 … … 1738 1770 * @param uStatus Status to report. 1739 1771 * @param rcTransfer Result code to report. Optional and depending on status. 1740 * @param pidEvent Where to store the created wait event. Optional. 1772 * @param ppEvent Where to return the wait event on success. Optional. 1773 * Must be released by the caller with ShClEventRelease(). 1741 1774 */ 1742 1775 int shClSvcTransferSendStatus(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer, SHCLTRANSFERSTATUS uStatus, 1743 int rcTransfer, PSHCLEVENT ID pidEvent)1776 int rcTransfer, PSHCLEVENT *ppEvent) 1744 1777 { 1745 1778 AssertPtrReturn(pClient, VERR_INVALID_POINTER); 1746 1779 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER); 1747 /* p idEvent is optional. */1780 /* ppEvent is optional. */ 1748 1781 1749 1782 PSHCLCLIENTMSG pMsgReadData = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_TRANSFER_STATUS, … … 1752 1785 return VERR_NO_MEMORY; 1753 1786 1754 int rc; 1755 1756 const SHCLEVENTID idEvent = ShClEventIdGenerateAndRegister(&pTransfer->Events); 1757 if (idEvent != NIL_SHCLEVENTID) 1787 PSHCLEVENT pEvent; 1788 int rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvent); 1789 if (RT_SUCCESS(rc)) 1758 1790 { 1759 1791 HGCMSvcSetU64(&pMsgReadData->aParms[0], VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID, 1760 pTransfer->State.uID, idEvent));1792 pTransfer->State.uID, pEvent->idEvent)); 1761 1793 HGCMSvcSetU32(&pMsgReadData->aParms[1], pTransfer->State.enmDir); 1762 1794 HGCMSvcSetU32(&pMsgReadData->aParms[2], uStatus); … … 1772 1804 ShClTransferStatusToStr(uStatus), rcTransfer, pTransfer->State.uID)); 1773 1805 1774 if (p idEvent)1775 { 1776 *p idEvent = idEvent;1777 } 1778 else /* If event is not consumed by the caller, unregisterevent again. */1779 ShClEvent Unregister(&pTransfer->Events, idEvent);1806 if (ppEvent) 1807 { 1808 *ppEvent = pEvent; /* Takes ownership. */ 1809 } 1810 else /* If event is not consumed by the caller, release the event again. */ 1811 ShClEventRelease(pEvent); 1780 1812 } 1781 1813 else 1782 ShClEvent Unregister(&pTransfer->Events, idEvent);1814 ShClEventRelease(pEvent); 1783 1815 } 1784 1816 else … … 1869 1901 if (RT_SUCCESS(rc)) 1870 1902 { 1871 SHCLEVENTID idEvent;1903 PSHCLEVENT pEvent; 1872 1904 rc = shClSvcTransferSendStatus(pClient, pTransfer, 1873 SHCLTRANSFERSTATUS_INITIALIZED, VINF_SUCCESS, 1874 &idEvent); 1905 SHCLTRANSFERSTATUS_INITIALIZED, VINF_SUCCESS, &pEvent); 1875 1906 if (RT_SUCCESS(rc)) 1876 1907 { … … 1882 1913 1883 1914 PSHCLEVENTPAYLOAD pPayload = NULL; 1884 rc = ShClEventWait( &pTransfer->Events, idEvent, pTransfer->uTimeoutMs, &pPayload);1915 rc = ShClEventWait(pEvent, pTransfer->uTimeoutMs, &pPayload); 1885 1916 if (RT_SUCCESS(rc)) 1886 1917 { … … 1907 1938 1908 1939 ShClPayloadFree(pPayload); 1940 ShClEventRelease(pEvent); 1909 1941 1910 1942 /* Re-enter the client's critical section again. */ … … 1954 1986 int shClSvcTransferStop(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer) 1955 1987 { 1956 SHCLEVENTID idEvent;1988 PSHCLEVENT pEvent; 1957 1989 int rc = shClSvcTransferSendStatus(pClient, pTransfer, 1958 SHCLTRANSFERSTATUS_STOPPED, VINF_SUCCESS, 1959 &idEvent); 1990 SHCLTRANSFERSTATUS_STOPPED, VINF_SUCCESS, &pEvent); 1960 1991 if (RT_SUCCESS(rc)) 1961 1992 { 1962 1993 LogRel2(("Shared Clipboard: Waiting for stop of transfer %RU32 on guest ...\n", pTransfer->State.uID)); 1963 1994 1964 rc = ShClEventWait( &pTransfer->Events, idEvent, pTransfer->uTimeoutMs, NULL);1995 rc = ShClEventWait(pEvent, pTransfer->uTimeoutMs, NULL /* ppPayload */); 1965 1996 if (RT_SUCCESS(rc)) 1966 1997 LogRel2(("Shared Clipboard: Stopped transfer %RU32 on guest\n", pTransfer->State.uID)); 1998 1999 ShClEventRelease(pEvent); 1967 2000 } 1968 2001 -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-win.cpp
r91749 r92735 5 5 6 6 /* 7 * Copyright (C) 2006-202 0Oracle Corporation7 * Copyright (C) 2006-2021 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 207 207 208 208 ShClEventRelease(&pCtx->pClient->EventSrc, idEvent); 209 ShClEventUnregister(&pCtx->pClient->EventSrc, idEvent);210 209 } 211 210 -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-x11.cpp
r91749 r92735 5 5 6 6 /* 7 * Copyright (C) 2006-202 0Oracle Corporation7 * Copyright (C) 2006-2021 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 218 218 pClient, uFormat, pvData, cbData, pcbActual)); 219 219 220 int rc = VINF_SUCCESS;220 int rc; 221 221 222 222 CLIPREADCBREQ *pReq = (CLIPREADCBREQ *)RTMemAllocZ(sizeof(CLIPREADCBREQ)); 223 223 if (pReq) 224 224 { 225 pReq->pv = pvData; 226 pReq->cb = cbData; 227 pReq->pcbActual = pcbActual; 228 const SHCLEVENTID idEvent = ShClEventIdGenerateAndRegister(&pClient->EventSrc); 229 pReq->idEvent = idEvent; 230 if (idEvent != NIL_SHCLEVENTID) 231 { 225 PSHCLEVENT pEvent; 226 rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvent); 227 if (RT_SUCCESS(rc)) 228 { 229 pReq->pv = pvData; 230 pReq->cb = cbData; 231 pReq->pcbActual = pcbActual; 232 pReq->idEvent = pEvent->idEvent; 233 232 234 /* Note: ShClX11ReadDataFromX11() will consume pReq on success. */ 233 235 rc = ShClX11ReadDataFromX11(&pClient->State.pCtx->X11, uFormat, pReq); … … 235 237 { 236 238 PSHCLEVENTPAYLOAD pPayload; 237 rc = ShClEventWait( &pClient->EventSrc, idEvent, 30 * 1000, &pPayload);239 rc = ShClEventWait(pEvent, 30 * 1000, &pPayload); 238 240 if (RT_SUCCESS(rc)) 239 241 { … … 251 253 } 252 254 253 ShClEventUnregister(&pClient->EventSrc, idEvent); 254 } 255 else 256 rc = VERR_SHCLPB_MAX_EVENTS_REACHED; 255 ShClEventRelease(pEvent); 256 } 257 257 258 258 if (RT_FAILURE(rc)) … … 331 331 if (RT_SUCCESS(rc2)) 332 332 { 333 rc2 = ShClEventSignal(&pCtx->pClient->EventSrc, pReq->idEvent, pPayload); 333 const PSHCLEVENT pEvent = ShClEventSourceGetFromId(&pCtx->pClient->EventSrc, pReq->idEvent); 334 if (pEvent) 335 rc2 = ShClEventSignal(pEvent, pPayload); 336 334 337 RTCritSectLeave(&pCtx->pClient->CritSect); 338 335 339 if (RT_SUCCESS(rc2)) 336 340 pPayload = NULL; … … 394 398 { 395 399 /* Request data from the guest. */ 396 SHCLEVENTID idEvent;397 rc = ShClSvcGuestDataRequest(pCtx->pClient, uFmt, & idEvent);400 PSHCLEVENT pEvent; 401 rc = ShClSvcGuestDataRequest(pCtx->pClient, uFmt, &pEvent); 398 402 if (RT_SUCCESS(rc)) 399 403 { … … 401 405 402 406 PSHCLEVENTPAYLOAD pPayload; 403 rc = ShClEventWait( &pCtx->pClient->EventSrc, idEvent, 30 * 1000, &pPayload);407 rc = ShClEventWait(pEvent, 30 * 1000, &pPayload); 404 408 if (RT_SUCCESS(rc)) 405 409 { … … 418 422 RTCritSectEnter(&pClient->CritSect); 419 423 420 ShClEventRelease(&pCtx->pClient->EventSrc, idEvent); 421 ShClEventUnregister(&pCtx->pClient->EventSrc, idEvent); 424 ShClEventRelease(pEvent); 422 425 } 423 426 } … … 459 462 LogFlowFuncEnter(); 460 463 461 int rc; 462 463 SHCLEVENTID idEvent = ShClEventIdGenerateAndRegister(&pClient->EventSrc); 464 if (idEvent != NIL_SHCLEVENTID) 464 PSHCLEVENT pEvent; 465 int rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvent); 466 if (RT_SUCCESS(rc)) 465 467 { 466 468 CLIPREADCBREQ *pReq = (CLIPREADCBREQ *)RTMemAllocZ(sizeof(CLIPREADCBREQ)); 467 469 if (pReq) 468 470 { 469 pReq->idEvent = idEvent;471 pReq->idEvent = pEvent->idEvent; 470 472 471 473 rc = ShClX11ReadDataFromX11(&pClient->State.pCtx->X11, VBOX_SHCL_FMT_URI_LIST, pReq); … … 474 476 /* X supplies the data asynchronously, so we need to wait for data to arrive first. */ 475 477 PSHCLEVENTPAYLOAD pPayload; 476 rc = ShClEventWait( &pClient->EventSrc, idEvent, 30 * 1000, &pPayload);478 rc = ShClEventWait(pEvent, 30 * 1000, &pPayload); 477 479 if (RT_SUCCESS(rc)) 478 480 { … … 485 487 rc = VERR_NO_MEMORY; 486 488 487 ShClEvent Unregister(&pClient->EventSrc, idEvent);489 ShClEventRelease(pEvent); 488 490 } 489 491 else -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc.cpp
r92240 r92735 5 5 6 6 /* 7 * Copyright (C) 2006-202 0Oracle Corporation7 * Copyright (C) 2006-2021 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 1201 1201 * @param pClient Client to request to read data form. 1202 1202 * @param fFormats The formats being requested, OR'ed together (VBOX_SHCL_FMT_XXX). 1203 * @param pidEvent Event ID for waiting for new data. Optional. 1204 * Must be released by the caller with ShClEventRelease() before unregistering then. 1205 */ 1206 int ShClSvcGuestDataRequest(PSHCLCLIENT pClient, SHCLFORMATS fFormats, PSHCLEVENTID pidEvent) 1207 { 1208 LogFlowFuncEnter(); 1209 if (pidEvent) 1210 *pidEvent = NIL_SHCLEVENTID; 1211 AssertPtrReturn(pClient, VERR_INVALID_POINTER); 1203 * @param ppEvent Where to return the event for waiting for new data on success. Optional. 1204 * Must be released by the caller with ShClEventRelease(). 1205 */ 1206 int ShClSvcGuestDataRequest(PSHCLCLIENT pClient, SHCLFORMATS fFormats, PSHCLEVENT *ppEvent) 1207 { 1208 AssertPtrReturn(pClient, VERR_INVALID_POINTER); 1212 1209 1213 1210 LogFlowFunc(("fFormats=%#x\n", fFormats)); 1214 1211 1215 1212 int rc = VERR_NOT_SUPPORTED; 1216 1217 SHCLEVENTID idEvent = NIL_SHCLEVENTID;1218 1213 1219 1214 /* Generate a separate message for every (valid) format we support. */ … … 1255 1250 RTCritSectEnter(&pClient->CritSect); 1256 1251 1257 idEvent = ShClEventIdGenerateAndRegister(&pClient->EventSrc); 1258 if (idEvent != NIL_SHCLEVENTID) 1252 PSHCLEVENT pEvent; 1253 rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvent); 1254 if (RT_SUCCESS(rc)) 1259 1255 { 1260 LogFlowFunc(("fFormats=%#x -> fFormat=%#x, idEvent=%#x\n", fFormats, fFormat, idEvent));1261 1262 const uint64_t uCID = VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID, pClient->EventSrc.uID, idEvent);1256 LogFlowFunc(("fFormats=%#x -> fFormat=%#x, idEvent=%#x\n", fFormats, fFormat, pEvent->idEvent)); 1257 1258 const uint64_t uCID = VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID, pClient->EventSrc.uID, pEvent->idEvent); 1263 1259 1264 1260 rc = VINF_SUCCESS; … … 1296 1292 1297 1293 shClSvcMsgAdd(pClient, pMsg, true /* fAppend */); 1294 1295 /* Retain the last event generated (in case there were multiple clipboard formats) 1296 * if we need to return the event to the caller. */ 1297 if (ppEvent) 1298 { 1299 ShClEventRetain(pEvent); 1300 *ppEvent = pEvent; 1301 } 1302 1303 shClSvcClientWakeup(pClient); 1298 1304 } 1299 1305 } … … 1311 1317 if (RT_FAILURE(rc)) 1312 1318 break; 1313 }1314 1315 if (RT_SUCCESS(rc))1316 {1317 RTCritSectEnter(&pClient->CritSect);1318 1319 /* Retain the last event generated (in case there were multiple clipboard formats)1320 * if we need to return the event ID to the caller. */1321 if (pidEvent)1322 {1323 ShClEventRetain(&pClient->EventSrc, idEvent);1324 *pidEvent = idEvent;1325 }1326 1327 shClSvcClientWakeup(pClient);1328 1329 RTCritSectLeave(&pClient->CritSect);1330 1319 } 1331 1320 … … 1355 1344 1356 1345 /* 1357 * Validate in tput.1346 * Validate input. 1358 1347 */ 1359 1348 AssertPtrReturn(pClient, VERR_INVALID_POINTER); … … 1364 1353 const SHCLEVENTID idEvent = VBOX_SHCL_CONTEXTID_GET_EVENT(pCmdCtx->uContextID); 1365 1354 AssertMsgReturn(idEvent != NIL_SHCLEVENTID, ("NIL event in context ID %#RX64\n", pCmdCtx->uContextID), VERR_WRONG_ORDER); 1366 AssertMsg(ShClEventGet(&pClient->EventSrc, idEvent) != NULL, ("Event %#x not found\n", idEvent)); 1355 1356 PSHCLEVENT pEvent = ShClEventSourceGetFromId(&pClient->EventSrc, idEvent); 1357 AssertMsg(pEvent != NULL, ("Event %#x not found\n", idEvent)); 1367 1358 1368 1359 /* … … 1380 1371 * Signal the event. 1381 1372 */ 1382 RTCritSectEnter(&pClient->CritSect); 1383 int rc2 = ShClEventSignal(&pClient->EventSrc, idEvent, pPayload); 1384 RTCritSectLeave(&pClient->CritSect); 1373 int rc2 = ShClEventSignal(pEvent, pPayload); 1385 1374 if (RT_FAILURE(rc2)) 1386 1375 { … … 1391 1380 1392 1381 /* 1393 * No one holding a reference to the event anymore? Unregister it. 1394 */ 1395 /** @todo r=bird: This isn't how reference counting is supposed to be 1396 * implemented, is it now? */ 1397 if (ShClEventGetRefs(&pClient->EventSrc, idEvent) == 0) 1398 { 1399 rc2 = ShClEventUnregister(&pClient->EventSrc, idEvent); 1400 if (RT_SUCCESS(rc)) 1401 rc = rc2; 1402 } 1382 * Release reference (and free it if not used anymore). 1383 */ 1384 ShClEventRelease(pEvent); 1403 1385 1404 1386 LogFlowFuncLeaveRC(rc);
Note:
See TracChangeset
for help on using the changeset viewer.