VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-uri.cpp@ 79497

Last change on this file since 79497 was 79497, checked in by vboxsync, 6 years ago

Shared Clipboard/URI: Update.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 41.0 KB
Line 
1/* $Id: VBoxSharedClipboardSvc-uri.cpp 79497 2019-07-03 13:28:33Z vboxsync $ */
2/** @file
3 * Shared Clipboard Service - Internal code for URI (list) handling.
4 */
5
6/*
7 * Copyright (C) 2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_SHARED_CLIPBOARD
23#include <VBox/log.h>
24
25#include <VBox/err.h>
26
27#include <VBox/HostServices/VBoxClipboardSvc.h>
28#include <VBox/HostServices/VBoxClipboardExt.h>
29
30#include <iprt/dir.h>
31#include <iprt/file.h>
32#include <iprt/path.h>
33
34#include "VBoxSharedClipboardSvc-internal.h"
35#include "VBoxSharedClipboardSvc-uri.h"
36
37
38/*********************************************************************************************************************************
39* Externals *
40*********************************************************************************************************************************/
41extern PFNHGCMSVCEXT g_pfnExtension;
42extern void *g_pvExtension;
43
44extern ClipboardClientQueue g_listClientsDeferred;
45
46
47/*********************************************************************************************************************************
48* Provider implementation *
49*********************************************************************************************************************************/
50
51DECLCALLBACK(int) vboxSvcClipboardURITransferOpen(PSHAREDCLIPBOARDPROVIDERCTX pCtx)
52{
53 RT_NOREF(pCtx);
54
55 LogFlowFuncLeave();
56 return VINF_SUCCESS;
57}
58
59DECLCALLBACK(int) vboxSvcClipboardURITransferClose(PSHAREDCLIPBOARDPROVIDERCTX pCtx)
60{
61 RT_NOREF(pCtx);
62
63 LogFlowFuncLeave();
64 return VINF_SUCCESS;
65}
66
67DECLCALLBACK(int) vboxSvcClipboardURIListOpen(PSHAREDCLIPBOARDPROVIDERCTX pCtx,
68 PVBOXCLIPBOARDLISTHDR pListHdr, PVBOXCLIPBOARDLISTHANDLE phList)
69{
70 RT_NOREF(pCtx, pListHdr, phList);
71
72 LogFlowFuncEnter();
73
74 int rc = VINF_SUCCESS;
75
76 LogFlowFuncLeaveRC(rc);
77 return rc;
78}
79
80DECLCALLBACK(int) vboxSvcClipboardURIListClose(PSHAREDCLIPBOARDPROVIDERCTX pCtx, VBOXCLIPBOARDLISTHANDLE hList)
81{
82 RT_NOREF(pCtx, hList);
83
84 LogFlowFuncEnter();
85
86 int rc = VINF_SUCCESS;
87
88 LogFlowFuncLeaveRC(rc);
89 return rc;
90}
91
92DECLCALLBACK(int) vboxSvcClipboardURIListHdrRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx,
93 VBOXCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTHDR pListHdr)
94{
95 RT_NOREF(pCtx, hList, pListHdr);
96
97 LogFlowFuncEnter();
98
99 PVBOXCLIPBOARDCLIENT pClient = (PVBOXCLIPBOARDCLIENT)pCtx->pvUser;
100 AssertPtr(pClient);
101
102 int rc;
103
104 PVBOXCLIPBOARDCLIENTMSG pMsg = vboxSvcClipboardMsgAlloc(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_HDR_READ,
105 VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR_READ);
106 if (pMsg)
107 {
108 rc = vboxSvcClipboardMsgAdd(&pClient->pData->State, pMsg, true /* fAppend */);
109 if (RT_SUCCESS(rc))
110 rc = vboxSvcClipboardClientDeferredComplete(pClient, VINF_SUCCESS);
111 }
112 else
113 rc = VERR_NO_MEMORY;
114
115 if (RT_SUCCESS(rc))
116 {
117 PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
118 rc = SharedClipboardURITransferEventWait(pCtx->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_HDR_READ,
119 30 * 1000 /* Timeout in ms */, &pPayload);
120 if (RT_SUCCESS(rc))
121 {
122 Assert(pPayload->cbData == sizeof(VBOXCLIPBOARDLISTHDR));
123 //*ppListHdr = (PVBOXCLIPBOARDLISTHDR)pPayload->pvData;
124
125 RTMemFree(pPayload);
126 }
127 }
128
129 LogFlowFuncLeaveRC(rc);
130 return rc;
131}
132
133DECLCALLBACK(int) vboxSvcClipboardURIListHdrWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx,
134 VBOXCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTHDR pListHdr)
135{
136 RT_NOREF(pCtx, hList, pListHdr);
137
138 LogFlowFuncEnter();
139
140 return VERR_NOT_IMPLEMENTED;
141}
142
143DECLCALLBACK(int) vboxSvcClipboardURIListEntryRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx,
144 VBOXCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTENTRY pListEntry)
145{
146 RT_NOREF(pCtx, hList, pListEntry);
147
148 LogFlowFuncEnter();
149
150 PVBOXCLIPBOARDCLIENTDATA pClientData = (PVBOXCLIPBOARDCLIENTDATA)pCtx->pvUser;
151 AssertPtr(pClientData);
152
153 PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
154 int rc = SharedClipboardURITransferEventWait(pCtx->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_ENTRY_READ,
155 30 * 1000 /* Timeout in ms */, &pPayload);
156 if (RT_SUCCESS(rc))
157 {
158 Assert(pPayload->cbData == sizeof(VBOXCLIPBOARDLISTENTRY));
159
160 PVBOXCLIPBOARDLISTENTRY pListEntry = (PVBOXCLIPBOARDLISTENTRY)pPayload->pvData;
161 AssertPtr(pListEntry);
162
163 /* const uint32_t cbToRead = RT_MIN(cbChunk, pListEntry->cbData);
164
165 memcpy(pvChunk, pListEntry->pvData, cbToRead);*/
166
167 SharedClipboardURITransferPayloadFree(pPayload);
168
169/* if (pcbRead)
170 *pcbRead = cbToRead;*/
171 }
172
173 LogFlowFuncLeaveRC(rc);
174 return rc;
175}
176
177DECLCALLBACK(int) vboxSvcClipboardURIListEntryWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx,
178 VBOXCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTENTRY pListEntry)
179{
180 RT_NOREF(pCtx, hList, pListEntry);
181
182 LogFlowFuncEnter();
183
184 return VERR_NOT_IMPLEMENTED;
185}
186
187int vboxSvcClipboardURIObjOpen(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const char *pszPath,
188 PVBOXCLIPBOARDCREATEPARMS pCreateParms, PSHAREDCLIPBOARDOBJHANDLE phObj)
189{
190 RT_NOREF(pCtx, pszPath, pCreateParms, phObj);
191
192 LogFlowFuncEnter();
193
194 return VERR_NOT_IMPLEMENTED;
195}
196
197int vboxSvcClipboardURIObjClose(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDOBJHANDLE hObj)
198{
199 RT_NOREF(pCtx, hObj);
200
201 LogFlowFuncEnter();
202
203 int rc = VINF_SUCCESS;
204
205 PVBOXCLIPBOARDCONTEXT pThisCtx = (PVBOXCLIPBOARDCONTEXT)pCtx->pvUser;
206 AssertPtr(pThisCtx);
207
208 LogFlowFuncLeaveRC(rc);
209 return rc;
210}
211
212int vboxSvcClipboardURIObjRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDOBJHANDLE hObj,
213 void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbRead)
214{
215 RT_NOREF(pCtx, pCtx, hObj, pvData, cbData, fFlags, pcbRead);
216
217 LogFlowFuncEnter();
218
219 return VERR_NOT_IMPLEMENTED;
220}
221
222int vboxSvcClipboardURIObjWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDOBJHANDLE hObj,
223 void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbWritten)
224{
225 RT_NOREF(pCtx, pCtx, hObj, pvData, cbData, fFlags, pcbWritten);
226
227 LogFlowFuncEnter();
228
229 return VERR_NOT_IMPLEMENTED;
230}
231
232
233/*********************************************************************************************************************************
234* URI callbacks *
235*********************************************************************************************************************************/
236
237DECLCALLBACK(void) VBoxSvcClipboardURITransferPrepareCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData)
238{
239 LogFlowFuncEnter();
240
241 AssertPtrReturnVoid(pData);
242
243 PVBOXCLIPBOARDCLIENTDATA pClientData = (PVBOXCLIPBOARDCLIENTDATA)pData->pvUser;
244 AssertPtrReturnVoid(pClientData);
245
246 PSHAREDCLIPBOARDURITRANSFER pTransfer = pData->pTransfer;
247 AssertPtrReturnVoid(pTransfer);
248
249 /* Register needed events. */
250 int rc2 = SharedClipboardURITransferEventRegister(pData->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_HDR_READ);
251 AssertRC(rc2);
252 rc2 = SharedClipboardURITransferEventRegister(pData->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_ENTRY_READ);
253 AssertRC(rc2);
254
255#if 0
256 /* Tell the guest that it can start sending URI data. */
257 rc2 = vboxSvcClipboardReportMsg(pClientData, VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_TRANSFER_START,
258 0 /* u32Formats == 0 means reading data */);
259 AssertRC(rc2);
260#endif
261}
262
263DECLCALLBACK(void) VBoxSvcClipboardURITransferCompleteCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData, int rc)
264{
265 LogFlowFuncEnter();
266
267 RT_NOREF(pData, rc);
268
269 LogRel2(("Shared Clipboard: Transfer complete\n"));
270}
271
272DECLCALLBACK(void) VBoxSvcClipboardURITransferCanceledCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData)
273{
274 LogFlowFuncEnter();
275
276 RT_NOREF(pData);
277
278 LogRel2(("Shared Clipboard: Transfer canceled\n"));
279}
280
281DECLCALLBACK(void) VBoxSvcClipboardURITransferErrorCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData, int rc)
282{
283 LogFlowFuncEnter();
284
285 RT_NOREF(pData, rc);
286
287 LogRel(("Shared Clipboard: Transfer failed with %Rrc\n", rc));
288}
289
290/**
291 * Gets an URI list header from HGCM service parameters.
292 *
293 * @returns VBox status code.
294 * @param cParms Number of HGCM parameters supplied in \a paParms.
295 * @param paParms Array of HGCM parameters.
296 * @param phList Where to store the list handle.
297 * @param pListHdr Where to store the list header.
298 */
299int VBoxSvcClipboardURIGetListHdr(uint32_t cParms, VBOXHGCMSVCPARM paParms[],
300 PVBOXCLIPBOARDLISTHANDLE phList, PVBOXCLIPBOARDLISTHDR pListHdr)
301{
302 int rc;
303
304 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR_WRITE)
305 {
306 /* Note: Context ID (paParms[0]) not used yet. */
307 rc = HGCMSvcGetU64(&paParms[1], phList);
308 if (RT_SUCCESS(rc))
309 rc = HGCMSvcGetU64(&paParms[2], &pListHdr->cTotalObjects);
310 if (RT_SUCCESS(rc))
311 rc = HGCMSvcGetU64(&paParms[3], &pListHdr->cbTotalSize);
312 if (RT_SUCCESS(rc))
313 rc = HGCMSvcGetU32(&paParms[4], &pListHdr->enmCompression);
314 if (RT_SUCCESS(rc))
315 rc = HGCMSvcGetU32(&paParms[5], (uint32_t *)&pListHdr->enmChecksumType);
316
317 if (RT_SUCCESS(rc))
318 {
319 /** @todo Validate pvMetaFmt + cbMetaFmt. */
320 /** @todo Validate header checksum. */
321 }
322 }
323 else
324 rc = VERR_INVALID_PARAMETER;
325
326 LogFlowFuncLeaveRC(rc);
327 return rc;
328}
329
330/**
331 * Sets an URI list header to HGCM service parameters.
332 *
333 * @returns VBox status code.
334 * @param cParms Number of HGCM parameters supplied in \a paParms.
335 * @param paParms Array of HGCM parameters.
336 * @param pListHdr Pointer to data to set to the HGCM parameters.
337 */
338int VBoxSvcClipboardURISetListHdr(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDLISTHDR pListHdr)
339{
340 int rc;
341
342 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR_READ)
343 {
344 /** @todo Set pvMetaFmt + cbMetaFmt. */
345 /** @todo Calculate header checksum. */
346
347 /* Note: Context ID (paParms[0]) not used yet. */
348 HGCMSvcSetU32(&paParms[1], pListHdr->fList);
349 HGCMSvcSetU32(&paParms[2], pListHdr->fFeatures);
350 HGCMSvcSetU32(&paParms[3], pListHdr->cbFilter);
351 HGCMSvcSetPv (&paParms[4], pListHdr->pszFilter, pListHdr->cbFilter);
352 HGCMSvcSetU64(&paParms[5], pListHdr->cTotalObjects);
353 HGCMSvcSetU64(&paParms[6], pListHdr->cbTotalSize);
354 HGCMSvcSetU32(&paParms[7], pListHdr->enmCompression);
355 HGCMSvcSetU32(&paParms[8], (uint32_t)pListHdr->enmChecksumType);
356
357 rc = VINF_SUCCESS;
358 }
359 else
360 rc = VERR_INVALID_PARAMETER;
361
362 LogFlowFuncLeaveRC(rc);
363 return rc;
364}
365
366/**
367 * Gets an URI list entry from HGCM service parameters.
368 *
369 * @returns VBox status code.
370 * @param cParms Number of HGCM parameters supplied in \a paParms.
371 * @param paParms Array of HGCM parameters.
372 * @param phList Where to store the list handle.
373 * @param pListEntry Where to store the list entry.
374 */
375int VBoxSvcClipboardURIGetListEntry(uint32_t cParms, VBOXHGCMSVCPARM paParms[],
376 PVBOXCLIPBOARDLISTHANDLE phList, PVBOXCLIPBOARDLISTENTRY pListEntry)
377{
378 int rc;
379
380 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY_WRITE)
381 {
382 /* Note: Context ID (paParms[0]) not used yet. */
383 rc = HGCMSvcGetU64(&paParms[1], phList);
384 if (RT_SUCCESS(rc))
385 rc = HGCMSvcGetU32(&paParms[2], &pListEntry->fInfo);
386 if (RT_SUCCESS(rc))
387 rc = HGCMSvcGetU32(&paParms[3], &pListEntry->cbInfo);
388 if (RT_SUCCESS(rc))
389 rc = HGCMSvcGetPv(&paParms[4], &pListEntry->pvInfo, &pListEntry->cbInfo);
390
391 if (RT_SUCCESS(rc))
392 {
393 if (!SharedClipboardURIListEntryIsValid(pListEntry))
394 rc = VERR_INVALID_PARAMETER;
395 }
396 }
397 else
398 rc = VERR_INVALID_PARAMETER;
399
400 LogFlowFuncLeaveRC(rc);
401 return rc;
402}
403
404/**
405 * Sets an URI data chunk to HGCM service parameters.
406 *
407 * @returns VBox status code.
408 * @param cParms Number of HGCM parameters supplied in \a paParms.
409 * @param paParms Array of HGCM parameters.
410 * @param pListEntry Pointer to data to set to the HGCM parameters.
411 */
412int VBoxSvcClipboardURISetListEntry(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDLISTENTRY pListEntry)
413{
414 int rc;
415
416 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY_READ)
417 {
418 /** @todo Calculate chunk checksum. */
419
420 /* Note: Context ID (paParms[0]) not used yet. */
421 HGCMSvcSetU32(&paParms[1], pListEntry->fInfo);
422 HGCMSvcSetU32(&paParms[2], pListEntry->cbInfo);
423 HGCMSvcSetPv (&paParms[3], pListEntry->pvInfo, pListEntry->cbInfo);
424
425 rc = VINF_SUCCESS;
426 }
427 else
428 rc = VERR_INVALID_PARAMETER;
429
430 LogFlowFuncLeaveRC(rc);
431 return rc;
432}
433
434int VBoxSvcClipboardURIGetError(uint32_t cParms, VBOXHGCMSVCPARM paParms[], int *pRc)
435{
436 AssertPtrReturn(paParms, VERR_INVALID_PARAMETER);
437 AssertPtrReturn(pRc, VERR_INVALID_PARAMETER);
438
439 int rc;
440
441 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_ERROR)
442 {
443 /* Note: Context ID (paParms[0]) not used yet. */
444 rc = HGCMSvcGetU32(&paParms[1], (uint32_t *)pRc); /** @todo int vs. uint32_t !!! */
445 }
446 else
447 rc = VERR_INVALID_PARAMETER;
448
449 LogFlowFuncLeaveRC(rc);
450 return rc;
451}
452
453/**
454 * URI client (guest) handler for the Shared Clipboard host service.
455 *
456 * @returns VBox status code.
457 * @param pClient Pointer to associated client.
458 * @param callHandle The client's call handle of this call.
459 * @param u32Function Function number being called.
460 * @param cParms Number of function parameters supplied.
461 * @param paParms Array function parameters supplied.
462 * @param tsArrival Timestamp of arrival.
463 */
464int vboxSvcClipboardURIHandler(PVBOXCLIPBOARDCLIENT pClient,
465 VBOXHGCMCALLHANDLE callHandle,
466 uint32_t u32Function,
467 uint32_t cParms,
468 VBOXHGCMSVCPARM paParms[],
469 uint64_t tsArrival)
470{
471 RT_NOREF(paParms, tsArrival);
472
473 LogFlowFunc(("uClient=%RU32, u32Function=%RU32, cParms=%RU32, g_pfnExtension=%p\n",
474 pClient->uClientID, u32Function, cParms, g_pfnExtension));
475
476 const PVBOXCLIPBOARDCLIENTDATA pClientData = pClient->pData;
477 AssertPtrReturn(pClientData, VERR_INVALID_POINTER);
478
479 /* Check if we've the right mode set. */
480 if (!vboxSvcClipboardURIMsgIsAllowed(vboxSvcClipboardGetMode(), u32Function))
481 {
482 LogFunc(("Wrong clipboard mode, denying access\n"));
483 return VERR_ACCESS_DENIED;
484 }
485
486 /* A (valid) service extension is needed because VBoxSVC needs to keep track of the
487 * clipboard areas cached on the host. */
488 if (!g_pfnExtension)
489 {
490#ifdef DEBUG_andy
491 AssertPtr(g_pfnExtension);
492#endif
493 LogFunc(("Invalid / no service extension set, skipping URI handling\n"));
494 return VERR_NOT_SUPPORTED;
495 }
496
497 int rc = VINF_SUCCESS;
498
499 /*
500 * Pre-check: For certain messages we need to make sure that a (right) transfer is present.
501 */
502 PSHAREDCLIPBOARDURITRANSFER pTransfer = NULL;
503 switch (u32Function)
504 {
505 case VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG:
506 RT_FALL_THROUGH();
507 case VBOX_SHARED_CLIPBOARD_GUEST_FN_TRANSFER_REPORT:
508 break;
509 default:
510 {
511 if (!SharedClipboardURICtxGetTotalTransfers(&pClientData->URI))
512 {
513 LogFunc(("No transfers found\n"));
514 rc = VERR_WRONG_ORDER;
515 break;
516 }
517
518 const uint32_t uTransferID = 0; /* Only one transfer per client is supported at the moment. */
519
520 pTransfer = SharedClipboardURICtxGetTransfer(&pClientData->URI, uTransferID);
521 if (!pTransfer)
522 {
523 LogFunc(("Transfer with ID %RU32 not found\n", uTransferID));
524 rc = VERR_WRONG_ORDER;
525 }
526 break;
527 }
528 }
529
530 if (RT_FAILURE(rc))
531 return rc;
532
533 rc = VERR_INVALID_PARAMETER; /* Play safe. */
534
535 switch (u32Function)
536 {
537 case VBOX_SHARED_CLIPBOARD_GUEST_FN_TRANSFER_REPORT:
538 {
539 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_TRANSFER_REPORT\n"));
540
541 if (!SharedClipboardURICtxTransfersMaximumReached(&pClientData->URI))
542 {
543 SharedClipboardURICtxTransfersCleanup(&pClientData->URI);
544
545 SHAREDCLIPBOARDURITRANSFERDIR enmDir = SHAREDCLIPBOARDURITRANSFERDIR_READ;
546
547 PSHAREDCLIPBOARDURITRANSFER pTransfer;
548 rc = SharedClipboardURITransferCreate(enmDir,
549 SHAREDCLIPBOARDSOURCE_REMOTE, &pTransfer);
550 if (RT_SUCCESS(rc))
551 {
552 rc = vboxSvcClipboardURIAreaRegister(&pClientData->State, pTransfer);
553 if (RT_SUCCESS(rc))
554 {
555 SHAREDCLIPBOARDPROVIDERCREATIONCTX creationCtx;
556 RT_ZERO(creationCtx);
557
558 creationCtx.enmSource = pClientData->State.enmSource;
559
560 RT_ZERO(creationCtx.Interface);
561 creationCtx.Interface.pfnTransferOpen = vboxSvcClipboardURITransferOpen;
562 creationCtx.Interface.pfnTransferClose = vboxSvcClipboardURITransferClose;
563 creationCtx.Interface.pfnListOpen = vboxSvcClipboardURIListOpen;
564 creationCtx.Interface.pfnListClose = vboxSvcClipboardURIListClose;
565 creationCtx.Interface.pfnObjOpen = vboxSvcClipboardURIObjOpen;
566 creationCtx.Interface.pfnObjClose = vboxSvcClipboardURIObjClose;
567
568 if (enmDir == SHAREDCLIPBOARDURITRANSFERDIR_READ)
569 {
570 creationCtx.Interface.pfnListHdrRead = vboxSvcClipboardURIListHdrRead;
571 creationCtx.Interface.pfnListEntryRead = vboxSvcClipboardURIListEntryRead;
572 creationCtx.Interface.pfnObjRead = vboxSvcClipboardURIObjRead;
573 }
574 else
575 {
576 AssertFailed();
577 }
578
579 creationCtx.pvUser = pClient;
580
581 /* Register needed callbacks so that we can wait for the meta data to arrive here. */
582 SHAREDCLIPBOARDURITRANSFERCALLBACKS Callbacks;
583 RT_ZERO(Callbacks);
584
585 Callbacks.pvUser = pClientData;
586
587 Callbacks.pfnTransferPrepare = VBoxSvcClipboardURITransferPrepareCallback;
588 Callbacks.pfnTransferComplete = VBoxSvcClipboardURITransferCompleteCallback;
589 Callbacks.pfnTransferCanceled = VBoxSvcClipboardURITransferCanceledCallback;
590 Callbacks.pfnTransferError = VBoxSvcClipboardURITransferErrorCallback;
591
592 SharedClipboardURITransferSetCallbacks(pTransfer, &Callbacks);
593
594 rc = SharedClipboardURITransferProviderCreate(pTransfer, &creationCtx);
595 if (RT_SUCCESS(rc))
596 rc = SharedClipboardURICtxTransferAdd(&pClientData->URI, pTransfer);
597 }
598
599 if (RT_SUCCESS(rc))
600 {
601 rc = VBoxClipboardSvcImplURITransferCreate(pClientData, pTransfer);
602 if (RT_SUCCESS(rc))
603 rc = VBoxClipboardSvcImplFormatAnnounce(pClientData, VBOX_SHARED_CLIPBOARD_FMT_URI_LIST);
604 }
605
606 if (RT_FAILURE(rc))
607 {
608 VBoxClipboardSvcImplURITransferDestroy(pClientData, pTransfer);
609 SharedClipboardURITransferDestroy(pTransfer);
610 }
611 }
612 }
613 else
614 rc = VERR_SHCLPB_MAX_TRANSFERS_REACHED;
615
616 LogFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_TRANSFER_REPORT: %Rrc\n", rc));
617
618 if (RT_FAILURE(rc))
619 LogRel(("Shared Clipboard: Initializing transfer failed with %Rrc\n", rc));
620
621 break;
622 }
623
624 case VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG:
625 {
626 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_GET_HOST_MSG)
627 {
628 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG\n"));
629 rc = vboxSvcClipboardMsgGetNextInfo(&pClientData->State,
630 &paParms[0].u.uint32 /* uMsg */, &paParms[1].u.uint32 /* cParms */);
631
632 /* No (new) messages available or some error occurred? */
633 if ( rc == VERR_NO_DATA
634 || RT_FAILURE(rc))
635 {
636 uint32_t fFlags = 0;
637 int rc2 = HGCMSvcGetU32(&paParms[2], &fFlags);
638 if ( RT_SUCCESS(rc2)
639 && fFlags) /* Blocking flag set? */
640 {
641 /* Defer client returning. */
642 rc = VINF_HGCM_ASYNC_EXECUTE;
643 }
644 else
645 rc = VERR_INVALID_PARAMETER;
646
647 LogFlowFunc(("Message queue is empty, returning %Rrc to guest\n", rc));
648 }
649 }
650 break;
651 }
652
653 case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_OPEN:
654 {
655 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_OPEN\n"));
656 rc = VINF_SUCCESS;
657 break;
658 }
659
660 case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_CLOSE:
661 {
662 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_CLOSE\n"));
663 rc = VINF_SUCCESS;
664 break;
665 }
666
667 case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_READ:
668 {
669 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_LIST_HDR\n"));
670
671 VBOXCLIPBOARDLISTHANDLE hList;
672 VBOXCLIPBOARDLISTHDR hdrList;
673 rc = VBoxSvcClipboardURIGetListHdr(cParms, paParms, &hList, &hdrList);
674 if (RT_SUCCESS(rc))
675 {
676 if (RT_SUCCESS(rc))
677 rc = VBoxSvcClipboardURISetListHdr(cParms, paParms, &hdrList);
678 }
679 break;
680 }
681
682 case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_WRITE:
683 {
684 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_LIST_HDR\n"));
685
686 VBOXCLIPBOARDLISTHDR hdrList;
687 rc = SharedClipboardURIListHdrInit(&hdrList);
688 if (RT_SUCCESS(rc))
689 {
690 VBOXCLIPBOARDLISTHANDLE hList;
691 rc = VBoxSvcClipboardURIGetListHdr(cParms, paParms, &hList, &hdrList);
692 if (RT_SUCCESS(rc))
693 {
694 void *pvData = SharedClipboardURIListHdrDup(&hdrList);
695 uint32_t cbData = sizeof(VBOXCLIPBOARDLISTHDR);
696
697 PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
698 rc = SharedClipboardURITransferPayloadAlloc(SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_HDR_READ,
699 pvData, cbData, &pPayload);
700 if (RT_SUCCESS(rc))
701 {
702 rc = SharedClipboardURITransferEventSignal(pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_HDR_READ,
703 pPayload);
704 }
705 }
706 }
707 break;
708 }
709
710 case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_ENTRY_READ:
711 {
712 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_LIST_ENTRY\n"));
713 break;
714 }
715
716 case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_ENTRY_WRITE:
717 {
718 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_LIST_ENTRY\n"));
719
720 VBOXCLIPBOARDLISTENTRY entryList;
721 rc = SharedClipboardURIListEntryInit(&entryList);
722 if (RT_SUCCESS(rc))
723 {
724 VBOXCLIPBOARDLISTHANDLE hList;
725 rc = VBoxSvcClipboardURIGetListEntry(cParms, paParms, &hList, &entryList);
726 if (RT_SUCCESS(rc))
727 {
728 void *pvData = SharedClipboardURIListEntryDup(&entryList);
729 uint32_t cbData = sizeof(VBOXCLIPBOARDLISTENTRY);
730
731 PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
732 rc = SharedClipboardURITransferPayloadAlloc(SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_ENTRY_READ,
733 pvData, cbData, &pPayload);
734 if (RT_SUCCESS(rc))
735 {
736 rc = SharedClipboardURITransferEventSignal(pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_ENTRY_READ,
737 pPayload);
738 }
739
740 }
741 }
742 break;
743 }
744#if 0
745 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DIR:
746 {
747 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DIR\n"));
748
749 VBOXCLIPBOARDDIRDATA dirData;
750 rc = VBoxSvcClipboardURIGetDir(cParms, paParms, &dirData);
751 if (RT_SUCCESS(rc))
752 {
753 SharedClipboardArea *pArea = SharedClipboardURITransferGetArea(pTransfer);
754 AssertPtrBreakStmt(pArea, rc = VERR_INVALID_POINTER);
755
756 const char *pszCacheDir = pArea->GetDirAbs();
757 char *pszDir = RTPathJoinA(pszCacheDir, dirData.pszPath);
758 if (pszDir)
759 {
760 LogFlowFunc(("pszDir=%s\n", pszDir));
761
762 rc = RTDirCreateFullPath(pszDir, dirData.fMode);
763 if (RT_SUCCESS(rc))
764 {
765 SHAREDCLIPBOARDAREAOBJ Obj = { SHAREDCLIPBOARDAREAOBJTYPE_DIR, SHAREDCLIPBOARDAREAOBJSTATE_COMPLETE };
766 int rc2 = pArea->AddObject(pszDir, Obj);
767 AssertRC(rc2);
768 }
769
770 RTStrFree(pszDir);
771 }
772 else
773 rc = VERR_NO_MEMORY;
774 }
775 break;
776 }
777
778 case VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_FILE_HDR:
779 {
780 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_FILE_HDR\n"));
781
782 VBOXCLIPBOARDFILEHDR fileHdr;
783 rc = VBoxSvcClipboardURISetFileHdr(cParms, paParms, &fileHdr);
784 break;
785 }
786
787 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_FILE_HDR:
788 {
789 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_FILE_HDR\n"));
790
791 if (!SharedClipboardURIObjCtxIsValid(SharedClipboardURITransferGetCurrentObjCtx(pTransfer)))
792 {
793 pTransfer->State.ObjCtx.pObj = new SharedClipboardURIObject(SharedClipboardURIObject::Type_File);
794 if (pTransfer->State.ObjCtx.pObj) /** @todo Can this throw? */
795 {
796 rc = VINF_SUCCESS;
797 }
798 else
799 rc = VERR_NO_MEMORY;
800 }
801 else /* There still is another object being processed? */
802 rc = VERR_WRONG_ORDER;
803
804 if (RT_FAILURE(rc))
805 break;
806
807 VBOXCLIPBOARDFILEHDR fileHdr;
808 rc = VBoxSvcClipboardURIGetFileHdr(cParms, paParms, &fileHdr);
809 if (RT_SUCCESS(rc))
810 {
811 SharedClipboardArea *pArea = SharedClipboardURITransferGetArea(pTransfer);
812 AssertPtrBreakStmt(pArea, rc = VERR_WRONG_ORDER);
813
814 const char *pszCacheDir = pArea->GetDirAbs();
815
816 char pszPathAbs[RTPATH_MAX];
817 rc = RTPathJoin(pszPathAbs, sizeof(pszPathAbs), pszCacheDir, fileHdr.pszFilePath);
818 if (RT_SUCCESS(rc))
819 {
820 rc = SharedClipboardPathSanitize(pszPathAbs, sizeof(pszPathAbs));
821 if (RT_SUCCESS(rc))
822 {
823 PSHAREDCLIPBOARDCLIENTURIOBJCTX pObjCtx = SharedClipboardURITransferGetCurrentObjCtx(pTransfer);
824 AssertPtrBreakStmt(pObjCtx, VERR_INVALID_POINTER);
825
826 SharedClipboardURIObject *pObj = pObjCtx->pObj;
827 AssertPtrBreakStmt(pObj, VERR_INVALID_POINTER);
828
829 LogFlowFunc(("pszFile=%s\n", pszPathAbs));
830
831 /** @todo Add sparse file support based on fFlags? (Use Open(..., fFlags | SPARSE). */
832 rc = pObj->OpenFileEx(pszPathAbs, SharedClipboardURIObject::View_Target,
833 RTFILE_O_CREATE_REPLACE | RTFILE_O_WRITE | RTFILE_O_DENY_WRITE,
834 (fileHdr.fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR);
835 if (RT_SUCCESS(rc))
836 {
837 rc = pObj->SetSize(fileHdr.cbSize);
838
839 /** @todo Unescape path before printing. */
840 LogRel2(("Clipboard: Transferring guest file '%s' to host (%RU64 bytes, mode 0x%x)\n",
841 pObj->GetDestPathAbs().c_str(), pObj->GetSize(), pObj->GetMode()));
842
843 if (pObj->IsComplete()) /* 0-byte file? We're done already. */
844 {
845 /** @todo Sanitize path. */
846 LogRel2(("Clipboard: Transferring guest file '%s' (0 bytes) to host complete\n",
847 pObj->GetDestPathAbs().c_str()));
848
849 SharedClipboardURIObjCtxDestroy(&pTransfer->State.ObjCtx);
850 }
851
852 SHAREDCLIPBOARDAREAOBJ Obj = { SHAREDCLIPBOARDAREAOBJTYPE_FILE, SHAREDCLIPBOARDAREAOBJSTATE_NONE };
853 int rc2 = pArea->AddObject(pszPathAbs, Obj);
854 AssertRC(rc2);
855 }
856 else
857 LogRel(("Clipboard: Error opening/creating guest file '%s' on host, rc=%Rrc\n", pszPathAbs, rc));
858 }
859 }
860 }
861 break;
862 }
863
864 case VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_FILE_DATA:
865 {
866 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_READ_FILE_DATA\n"));
867
868 VBOXCLIPBOARDFILEDATA fileData;
869 rc = VBoxSvcClipboardURISetFileData(cParms, paParms, &fileData);
870 break;
871 }
872
873 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_FILE_DATA:
874 {
875 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_FILE_DATA\n"));
876
877 if (!SharedClipboardURIObjCtxIsValid(&pTransfer->State.ObjCtx))
878 {
879 rc = VERR_WRONG_ORDER;
880 break;
881 }
882
883 VBOXCLIPBOARDFILEDATA fileData;
884 rc = VBoxSvcClipboardURIGetFileData(cParms, paParms, &fileData);
885 if (RT_SUCCESS(rc))
886 {
887 PSHAREDCLIPBOARDCLIENTURIOBJCTX pObjCtx = SharedClipboardURITransferGetCurrentObjCtx(pTransfer);
888 AssertPtrBreakStmt(pObjCtx, VERR_INVALID_POINTER);
889
890 SharedClipboardURIObject *pObj = pObjCtx->pObj;
891 AssertPtrBreakStmt(pObj, VERR_INVALID_POINTER);
892
893 uint32_t cbWritten;
894 rc = pObj->Write(fileData.pvData, fileData.cbData, &cbWritten);
895 if (RT_SUCCESS(rc))
896 {
897 Assert(cbWritten <= fileData.cbData);
898 if (cbWritten < fileData.cbData)
899 {
900 /** @todo What to do when the host's disk is full? */
901 rc = VERR_DISK_FULL;
902 }
903
904 if ( pObj->IsComplete()
905 || RT_FAILURE(rc))
906 SharedClipboardURIObjCtxDestroy(&pTransfer->State.ObjCtx);
907 }
908 else
909 LogRel(("Clipboard: Error writing guest file data for '%s', rc=%Rrc\n", pObj->GetDestPathAbs().c_str(), rc));
910 }
911 break;
912 }
913#endif
914 case VBOX_SHARED_CLIPBOARD_GUEST_FN_CANCEL:
915 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_CANCEL\n"));
916
917 LogRel2(("Shared Clipboard: Transfer canceled\n"));
918 break;
919
920 case VBOX_SHARED_CLIPBOARD_GUEST_FN_ERROR:
921 {
922 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_ERROR\n"));
923
924 int rcGuest;
925 rc = VBoxSvcClipboardURIGetError(cParms,paParms, &rcGuest);
926 if (RT_SUCCESS(rc))
927 LogRel(("Shared Clipboard: Transfer error: %Rrc\n", rcGuest));
928 break;
929 }
930
931 default:
932 AssertMsgFailed(("Not implemented\n"));
933 break;
934 }
935
936 if (rc == VINF_HGCM_ASYNC_EXECUTE)
937 {
938 try
939 {
940 vboxSvcClipboardClientDefer(pClient, callHandle, u32Function, cParms, paParms);
941 g_listClientsDeferred.push_back(pClient->uClientID);
942 }
943 catch (std::bad_alloc &)
944 {
945 rc = VERR_NO_MEMORY;
946 /* Don't report to guest. */
947 }
948 }
949 else if (pClient)
950 {
951 int rc2 = vboxSvcClipboardClientComplete(pClient, callHandle, rc);
952 AssertRC(rc2);
953 }
954
955 LogFlowFunc(("Returning uClient=%RU32, rc=%Rrc\n", pClient->uClientID, rc));
956 return rc;
957}
958
959/**
960 * URI host handler for the Shared Clipboard host service.
961 *
962 * @returns VBox status code.
963 * @param u32Function Function number being called.
964 * @param cParms Number of function parameters supplied.
965 * @param paParms Array function parameters supplied.
966 */
967int vboxSvcClipboardURIHostHandler(uint32_t u32Function,
968 uint32_t cParms,
969 VBOXHGCMSVCPARM paParms[])
970{
971 RT_NOREF(cParms, paParms);
972
973 int rc = VERR_NOT_IMPLEMENTED; /* Play safe. */
974
975 switch (u32Function)
976 {
977 case VBOX_SHARED_CLIPBOARD_HOST_FN_CANCEL:
978 /** @todo */
979 break;
980
981 case VBOX_SHARED_CLIPBOARD_HOST_FN_ERROR:
982 /** @todo */
983 break;
984
985 default:
986 break;
987
988 }
989
990 LogFlowFuncLeaveRC(rc);
991 return rc;
992}
993
994/**
995 * Registers an URI clipboard area.
996 *
997 * @returns VBox status code.
998 * @param pClientState Client state to use.
999 * @param pTransfer URI transfer to register a clipboard area for.
1000 */
1001int vboxSvcClipboardURIAreaRegister(PVBOXCLIPBOARDCLIENTSTATE pClientState, PSHAREDCLIPBOARDURITRANSFER pTransfer)
1002{
1003 LogFlowFuncEnter();
1004
1005 AssertMsgReturn(pTransfer->pArea == NULL, ("An area already is registered for this transfer\n"),
1006 VERR_WRONG_ORDER);
1007
1008 pTransfer->pArea = new SharedClipboardArea();
1009 if (!pTransfer->pArea)
1010 return VERR_NO_MEMORY;
1011
1012 int rc;
1013
1014 if (g_pfnExtension)
1015 {
1016 VBOXCLIPBOARDEXTAREAPARMS parms;
1017 RT_ZERO(parms);
1018
1019 parms.uID = NIL_SHAREDCLIPBOARDAREAID;
1020
1021 /* As the meta data is now complete, register a new clipboard on the host side. */
1022 rc = g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_AREA_REGISTER, &parms, sizeof(parms));
1023 if (RT_SUCCESS(rc))
1024 {
1025 /* Note: Do *not* specify SHAREDCLIPBOARDAREA_OPEN_FLAGS_MUST_NOT_EXIST as flags here, as VBoxSVC took care of the
1026 * clipboard area creation already. */
1027 rc = pTransfer->pArea->OpenTemp(parms.uID /* Area ID */,
1028 SHAREDCLIPBOARDAREA_OPEN_FLAGS_NONE);
1029 }
1030
1031 LogFlowFunc(("Registered new clipboard area (%RU32) by client %RU32 with rc=%Rrc\n",
1032 parms.uID, pClientState->u32ClientID, rc));
1033 }
1034 else
1035 rc = VERR_NOT_SUPPORTED;
1036
1037 LogFlowFuncLeaveRC(rc);
1038 return rc;
1039}
1040
1041/**
1042 * Unregisters an URI clipboard area.
1043 *
1044 * @returns VBox status code.
1045 * @param pClientState Client state to use.
1046 * @param pTransfer URI transfer to unregister a clipboard area from.
1047 */
1048int vboxSvcClipboardURIAreaUnregister(PVBOXCLIPBOARDCLIENTSTATE pClientState, PSHAREDCLIPBOARDURITRANSFER pTransfer)
1049{
1050 LogFlowFuncEnter();
1051
1052 if (!pTransfer->pArea)
1053 return VINF_SUCCESS;
1054
1055 int rc = VINF_SUCCESS;
1056
1057 if (g_pfnExtension)
1058 {
1059 VBOXCLIPBOARDEXTAREAPARMS parms;
1060 RT_ZERO(parms);
1061
1062 parms.uID = pTransfer->pArea->GetID();
1063
1064 rc = g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_AREA_UNREGISTER, &parms, sizeof(parms));
1065 if (RT_SUCCESS(rc))
1066 {
1067 rc = pTransfer->pArea->Close();
1068 if (RT_SUCCESS(rc))
1069 {
1070 delete pTransfer->pArea;
1071 pTransfer->pArea = NULL;
1072 }
1073 }
1074
1075 LogFlowFunc(("Unregistered clipboard area (%RU32) by client %RU32 with rc=%Rrc\n",
1076 parms.uID, pClientState->u32ClientID, rc));
1077 }
1078
1079 delete pTransfer->pArea;
1080 pTransfer->pArea = NULL;
1081
1082 LogFlowFuncLeaveRC(rc);
1083 return rc;
1084}
1085
1086/**
1087 * Attaches to an existing (registered) URI clipboard area.
1088 *
1089 * @returns VBox status code.
1090 * @param pClientState Client state to use.
1091 * @param pTransfer URI transfer to attach a clipboard area to.
1092 * @param uID ID of clipboard area to to attach to. Specify 0 to attach to the most recent one.
1093 */
1094int vboxSvcClipboardURIAreaAttach(PVBOXCLIPBOARDCLIENTSTATE pClientState, PSHAREDCLIPBOARDURITRANSFER pTransfer,
1095 SHAREDCLIPBOARDAREAID uID)
1096{
1097 LogFlowFuncEnter();
1098
1099 AssertMsgReturn(pTransfer->pArea == NULL, ("An area already is attached to this transfer\n"),
1100 VERR_WRONG_ORDER);
1101
1102 pTransfer->pArea = new SharedClipboardArea();
1103 if (!pTransfer->pArea)
1104 return VERR_NO_MEMORY;
1105
1106 int rc = VINF_SUCCESS;
1107
1108 if (g_pfnExtension)
1109 {
1110 VBOXCLIPBOARDEXTAREAPARMS parms;
1111 RT_ZERO(parms);
1112
1113 parms.uID = uID; /* 0 means most recent clipboard area. */
1114
1115 /* The client now needs to attach to the most recent clipboard area
1116 * to keep a reference to it. The host does the actual book keeping / cleanup then.
1117 *
1118 * This might fail if the host does not have a most recent clipboard area (yet). */
1119 rc = g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_AREA_ATTACH, &parms, sizeof(parms));
1120 if (RT_SUCCESS(rc))
1121 rc = pTransfer->pArea->OpenTemp(parms.uID /* Area ID */);
1122
1123 LogFlowFunc(("Attached client %RU32 to clipboard area %RU32 with rc=%Rrc\n",
1124 pClientState->u32ClientID, parms.uID, rc));
1125 }
1126 else
1127 rc = VERR_NOT_SUPPORTED;
1128
1129 LogFlowFuncLeaveRC(rc);
1130 return rc;
1131}
1132
1133/**
1134 * Detaches from an URI clipboard area.
1135 *
1136 * @returns VBox status code.
1137 * @param pClientState Client state to use.
1138 * @param pTransfer URI transfer to detach a clipboard area from.
1139 */
1140int vboxSvcClipboardURIAreaDetach(PVBOXCLIPBOARDCLIENTSTATE pClientState, PSHAREDCLIPBOARDURITRANSFER pTransfer)
1141{
1142 LogFlowFuncEnter();
1143
1144 if (!pTransfer->pArea)
1145 return VINF_SUCCESS;
1146
1147 const uint32_t uAreaID = pTransfer->pArea->GetID();
1148
1149 int rc = VINF_SUCCESS;
1150
1151 if (g_pfnExtension)
1152 {
1153 VBOXCLIPBOARDEXTAREAPARMS parms;
1154 RT_ZERO(parms);
1155 parms.uID = uAreaID;
1156
1157 rc = g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_AREA_DETACH, &parms, sizeof(parms));
1158
1159 LogFlowFunc(("Detached client %RU32 from clipboard area %RU32 with rc=%Rrc\n",
1160 pClientState->u32ClientID, uAreaID, rc));
1161 }
1162
1163 delete pTransfer->pArea;
1164 pTransfer->pArea = NULL;
1165
1166 LogFlowFuncLeaveRC(rc);
1167 return rc;
1168}
1169
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette