VirtualBox

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

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

Shared Clipboard/URI: SCM fix.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 61.2 KB
Line 
1/* $Id: VBoxSharedClipboardSvc-uri.cpp 79704 2019-07-11 19:38:32Z 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;
43extern PVBOXHGCMSVCHELPERS g_pHelpers;
44
45extern ClipboardClientQueue g_listClientsDeferred;
46
47
48/*********************************************************************************************************************************
49* Prototypes *
50*********************************************************************************************************************************/
51int VBoxSvcClipboardURISetListOpen(uint32_t cParms, VBOXHGCMSVCPARM paParms[],
52 PVBOXCLIPBOARDLISTOPENPARMS pOpenParms);
53int VBoxSvcClipboardURISetListClose(uint32_t cParms, VBOXHGCMSVCPARM paParms[],
54 SHAREDCLIPBOARDLISTHANDLE hList);
55
56
57/*********************************************************************************************************************************
58* Provider implementation *
59*********************************************************************************************************************************/
60
61DECLCALLBACK(int) vboxSvcClipboardURITransferOpen(PSHAREDCLIPBOARDPROVIDERCTX pCtx)
62{
63 RT_NOREF(pCtx);
64
65 LogFlowFuncLeave();
66 return VINF_SUCCESS;
67}
68
69DECLCALLBACK(int) vboxSvcClipboardURITransferClose(PSHAREDCLIPBOARDPROVIDERCTX pCtx)
70{
71 RT_NOREF(pCtx);
72
73 LogFlowFuncLeave();
74 return VINF_SUCCESS;
75}
76
77DECLCALLBACK(int) vboxSvcClipboardURIGetRoots(PSHAREDCLIPBOARDPROVIDERCTX pCtx,
78 char **ppapszRoots, uint32_t *pcRoots)
79{
80 LogFlowFuncEnter();
81
82 PVBOXCLIPBOARDCLIENT pClient = (PVBOXCLIPBOARDCLIENT)pCtx->pvUser;
83 AssertPtr(pClient);
84
85 int rc;
86
87 size_t cbRootsRecv = 0;
88
89 char *pszRoots = NULL;
90 uint32_t cRoots = 0;
91
92 /* There might be more than one message needed for retrieving all root items. */
93 for (;;)
94 {
95 PVBOXCLIPBOARDCLIENTMSG pMsg = vboxSvcClipboardMsgAlloc(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_ROOTS,
96 VBOX_SHARED_CLIPBOARD_CPARMS_ROOTS);
97 if (pMsg)
98 {
99 HGCMSvcSetU32(&pMsg->m_paParms[0], 0 /* uContextID */);
100 HGCMSvcSetU32(&pMsg->m_paParms[1], 0 /* fRoots */);
101 HGCMSvcSetU32(&pMsg->m_paParms[2], 0 /* fMore */);
102 HGCMSvcSetU32(&pMsg->m_paParms[3], 0 /* cRoots */);
103
104 uint32_t cbData = _64K;
105 void *pvData = RTMemAlloc(cbData);
106 AssertPtrBreakStmt(pvData, rc = VERR_NO_MEMORY);
107
108 HGCMSvcSetU32(&pMsg->m_paParms[4], cbData);
109 HGCMSvcSetPv (&pMsg->m_paParms[5], pvData, cbData);
110
111 rc = vboxSvcClipboardMsgAdd(pClient->pData, pMsg, true /* fAppend */);
112 if (RT_SUCCESS(rc))
113 {
114 int rc2 = SharedClipboardURITransferEventRegister(pCtx->pTransfer,
115 SHAREDCLIPBOARDURITRANSFEREVENTTYPE_GET_ROOTS);
116 AssertRC(rc2);
117
118 vboxSvcClipboardClientWakeup(pClient);
119 }
120 }
121 else
122 rc = VERR_NO_MEMORY;
123
124 if (RT_SUCCESS(rc))
125 {
126 PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
127 rc = SharedClipboardURITransferEventWait(pCtx->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_GET_ROOTS,
128 30 * 1000 /* Timeout in ms */, &pPayload);
129 if (RT_SUCCESS(rc))
130 {
131 PVBOXCLIPBOARDROOTS pRoots = (PVBOXCLIPBOARDROOTS)pPayload->pvData;
132 Assert(pPayload->cbData == sizeof(VBOXCLIPBOARDROOTS));
133
134 LogFlowFunc(("cbRoots=%RU32, fRoots=%RU32, fMore=%RTbool\n", pRoots->cbRoots, pRoots->fRoots, pRoots->fMore));
135
136 if (!pRoots->cbRoots)
137 break;
138 AssertPtr(pRoots->pszRoots);
139
140 if (pszRoots == NULL)
141 pszRoots = (char *)RTMemDup((void *)pRoots->pszRoots, pRoots->cbRoots);
142 else
143 pszRoots = (char *)RTMemRealloc(pszRoots, cbRootsRecv + pRoots->cbRoots);
144
145 AssertPtrBreakStmt(pszRoots, rc = VERR_NO_MEMORY);
146
147 cbRootsRecv += pRoots->cbRoots;
148
149 if (cbRootsRecv > _32M) /* Don't allow more than 32MB root entries for now. */
150 {
151 rc = VERR_ALLOCATION_TOO_BIG; /** @todo Find a better rc. */
152 break;
153 }
154
155 cRoots += pRoots->cRoots;
156
157 const bool fDone = !RT_BOOL(pRoots->fMore); /* More root entries to be retrieved? Otherwise bail out. */
158
159 SharedClipboardURITransferPayloadFree(pPayload);
160
161 if (fDone)
162 break;
163 }
164 }
165
166 if (RT_FAILURE(rc))
167 break;
168 }
169
170 if (RT_SUCCESS(rc))
171 {
172 LogFlowFunc(("cRoots=%RU32\n", cRoots));
173
174 *ppapszRoots = pszRoots;
175 *pcRoots = cRoots;
176 }
177 else
178 {
179 RTMemFree(pszRoots);
180 pszRoots = NULL;
181 }
182
183 LogFlowFuncLeave();
184 return rc;
185}
186
187DECLCALLBACK(int) vboxSvcClipboardURIListOpen(PSHAREDCLIPBOARDPROVIDERCTX pCtx,
188 PVBOXCLIPBOARDLISTOPENPARMS pOpenParms, PSHAREDCLIPBOARDLISTHANDLE phList)
189{
190 LogFlowFuncEnter();
191
192 PVBOXCLIPBOARDCLIENT pClient = (PVBOXCLIPBOARDCLIENT)pCtx->pvUser;
193 AssertPtr(pClient);
194
195 int rc;
196
197 PVBOXCLIPBOARDCLIENTMSG pMsg = vboxSvcClipboardMsgAlloc(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_OPEN,
198 VBOX_SHARED_CLIPBOARD_CPARMS_LIST_OPEN);
199 if (pMsg)
200 {
201 rc = VBoxSvcClipboardURISetListOpen(pMsg->m_cParms, pMsg->m_paParms, pOpenParms);
202 if (RT_SUCCESS(rc))
203 {
204 rc = vboxSvcClipboardMsgAdd(pClient->pData, pMsg, true /* fAppend */);
205 if (RT_SUCCESS(rc))
206 {
207 int rc2 = SharedClipboardURITransferEventRegister(pCtx->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_OPEN);
208 AssertRC(rc2);
209
210 vboxSvcClipboardClientWakeup(pClient);
211 }
212 }
213 }
214 else
215 rc = VERR_NO_MEMORY;
216
217 if (RT_SUCCESS(rc))
218 {
219 PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
220 rc = SharedClipboardURITransferEventWait(pCtx->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_OPEN,
221 30 * 1000 /* Timeout in ms */, &pPayload);
222 if (RT_SUCCESS(rc))
223 {
224 Assert(pPayload->cbData == sizeof(VBOXCLIPBOARDREPLY));
225
226 PVBOXCLIPBOARDREPLY pReply = (PVBOXCLIPBOARDREPLY)pPayload->pvData;
227 AssertPtr(pReply);
228
229 Assert(pReply->uType == VBOX_SHAREDCLIPBOARD_REPLYMSGTYPE_LIST_OPEN);
230
231 *phList = pReply->u.ListOpen.uHandle;
232
233 SharedClipboardURITransferPayloadFree(pPayload);
234 }
235 }
236
237 LogFlowFuncLeaveRC(rc);
238 return rc;
239}
240
241DECLCALLBACK(int) vboxSvcClipboardURIListClose(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDLISTHANDLE hList)
242{
243 LogFlowFuncEnter();
244
245 PVBOXCLIPBOARDCLIENT pClient = (PVBOXCLIPBOARDCLIENT)pCtx->pvUser;
246 AssertPtr(pClient);
247
248 int rc;
249
250 PVBOXCLIPBOARDCLIENTMSG pMsg = vboxSvcClipboardMsgAlloc(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_CLOSE,
251 VBOX_SHARED_CLIPBOARD_CPARMS_LIST_CLOSE);
252 if (pMsg)
253 {
254 rc = VBoxSvcClipboardURISetListClose(pMsg->m_cParms, pMsg->m_paParms, hList);
255 if (RT_SUCCESS(rc))
256 {
257 rc = vboxSvcClipboardMsgAdd(pClient->pData, pMsg, true /* fAppend */);
258 if (RT_SUCCESS(rc))
259 {
260 int rc2 = SharedClipboardURITransferEventRegister(pCtx->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_CLOSE);
261 AssertRC(rc2);
262
263 vboxSvcClipboardClientWakeup(pClient);
264 }
265 }
266 }
267 else
268 rc = VERR_NO_MEMORY;
269
270 if (RT_SUCCESS(rc))
271 {
272 PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
273 rc = SharedClipboardURITransferEventWait(pCtx->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_CLOSE,
274 30 * 1000 /* Timeout in ms */, &pPayload);
275 if (RT_SUCCESS(rc))
276 SharedClipboardURITransferPayloadFree(pPayload);
277 }
278
279 LogFlowFuncLeaveRC(rc);
280 return rc;
281}
282
283DECLCALLBACK(int) vboxSvcClipboardURIListHdrRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx,
284 SHAREDCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTHDR pListHdr)
285{
286 LogFlowFuncEnter();
287
288 PVBOXCLIPBOARDCLIENT pClient = (PVBOXCLIPBOARDCLIENT)pCtx->pvUser;
289 AssertPtr(pClient);
290
291 int rc;
292
293 PVBOXCLIPBOARDCLIENTMSG pMsg = vboxSvcClipboardMsgAlloc(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_HDR_READ,
294 VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR_READ_REQ);
295 if (pMsg)
296 {
297 HGCMSvcSetU32(&pMsg->m_paParms[0], 0 /* uContextID */);
298 HGCMSvcSetU64(&pMsg->m_paParms[1], hList);
299 HGCMSvcSetU32(&pMsg->m_paParms[2], 0 /* fFlags */);
300
301 rc = vboxSvcClipboardMsgAdd(pClient->pData, pMsg, true /* fAppend */);
302 if (RT_SUCCESS(rc))
303 {
304 int rc2 = SharedClipboardURITransferEventRegister(pCtx->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_HDR_WRITE);
305 AssertRC(rc2);
306
307 vboxSvcClipboardClientWakeup(pClient);
308 }
309 }
310 else
311 rc = VERR_NO_MEMORY;
312
313 if (RT_SUCCESS(rc))
314 {
315 PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
316 rc = SharedClipboardURITransferEventWait(pCtx->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_HDR_WRITE,
317 30 * 1000 /* Timeout in ms */, &pPayload);
318 if (RT_SUCCESS(rc))
319 {
320 Assert(pPayload->cbData == sizeof(VBOXCLIPBOARDLISTHDR));
321
322 *pListHdr = *(PVBOXCLIPBOARDLISTHDR)pPayload->pvData;
323
324 SharedClipboardURITransferPayloadFree(pPayload);
325 }
326 }
327
328 LogFlowFuncLeaveRC(rc);
329 return rc;
330}
331
332DECLCALLBACK(int) vboxSvcClipboardURIListHdrWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx,
333 SHAREDCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTHDR pListHdr)
334{
335 RT_NOREF(pCtx, hList, pListHdr);
336
337 LogFlowFuncEnter();
338
339 return VERR_NOT_IMPLEMENTED;
340}
341
342DECLCALLBACK(int) vboxSvcClipboardURIListEntryRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx,
343 SHAREDCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTENTRY pListEntry)
344{
345 LogFlowFuncEnter();
346
347 PVBOXCLIPBOARDCLIENT pClient = (PVBOXCLIPBOARDCLIENT)pCtx->pvUser;
348 AssertPtr(pClient);
349
350 int rc;
351
352 PVBOXCLIPBOARDCLIENTMSG pMsg = vboxSvcClipboardMsgAlloc(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_ENTRY_READ,
353 VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY_READ_REQ);
354 if (pMsg)
355 {
356 HGCMSvcSetU32(&pMsg->m_paParms[0], 0 /* uContextID */);
357 HGCMSvcSetU64(&pMsg->m_paParms[1], hList);
358 HGCMSvcSetU32(&pMsg->m_paParms[2], 0 /* fInfo */);
359
360 rc = vboxSvcClipboardMsgAdd(pClient->pData, pMsg, true /* fAppend */);
361 if (RT_SUCCESS(rc))
362 {
363 int rc2 = SharedClipboardURITransferEventRegister(pCtx->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_ENTRY_WRITE);
364 if (rc2 == VERR_ALREADY_EXISTS)
365 rc2 = VINF_SUCCESS;
366 AssertRC(rc2);
367
368 vboxSvcClipboardClientWakeup(pClient);
369 }
370 }
371 else
372 rc = VERR_NO_MEMORY;
373
374 if (RT_SUCCESS(rc))
375 {
376 PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
377 rc = SharedClipboardURITransferEventWait(pCtx->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_ENTRY_WRITE,
378 30 * 1000 /* Timeout in ms */, &pPayload);
379 if (RT_SUCCESS(rc))
380 {
381 Assert(pPayload->cbData == sizeof(VBOXCLIPBOARDLISTENTRY));
382
383 rc = SharedClipboardURIListEntryCopy(pListEntry, (PVBOXCLIPBOARDLISTENTRY)pPayload->pvData);
384
385 SharedClipboardURITransferPayloadFree(pPayload);
386 }
387 }
388
389 LogFlowFuncLeaveRC(rc);
390 return rc;
391}
392
393DECLCALLBACK(int) vboxSvcClipboardURIListEntryWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx,
394 SHAREDCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTENTRY pListEntry)
395{
396 RT_NOREF(pCtx, hList, pListEntry);
397
398 LogFlowFuncEnter();
399
400 return VERR_NOT_IMPLEMENTED;
401}
402
403int vboxSvcClipboardURIObjOpen(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const char *pszPath,
404 PVBOXCLIPBOARDCREATEPARMS pCreateParms, PSHAREDCLIPBOARDOBJHANDLE phObj)
405{
406 RT_NOREF(pCtx, pszPath, pCreateParms, phObj);
407
408 LogFlowFuncEnter();
409
410 int rc = VINF_SUCCESS;
411
412 PVBOXCLIPBOARDCONTEXT pThisCtx = (PVBOXCLIPBOARDCONTEXT)pCtx->pvUser;
413 AssertPtr(pThisCtx);
414
415 LogFlowFuncLeaveRC(rc);
416 return rc;
417}
418
419int vboxSvcClipboardURIObjClose(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDOBJHANDLE hObj)
420{
421 RT_NOREF(pCtx, hObj);
422
423 LogFlowFuncEnter();
424
425 int rc = VINF_SUCCESS;
426
427 PVBOXCLIPBOARDCONTEXT pThisCtx = (PVBOXCLIPBOARDCONTEXT)pCtx->pvUser;
428 AssertPtr(pThisCtx);
429
430 LogFlowFuncLeaveRC(rc);
431 return rc;
432}
433
434int vboxSvcClipboardURIObjRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDOBJHANDLE hObj,
435 void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbRead)
436{
437 RT_NOREF(pCtx, hObj, pvData, cbData, fFlags, pcbRead);
438
439 LogFlowFuncEnter();
440
441 int rc = VINF_SUCCESS;
442
443 *pcbRead = cbData;
444
445 LogFlowFuncLeaveRC(rc);
446 return rc;
447}
448
449int vboxSvcClipboardURIObjWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDOBJHANDLE hObj,
450 void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbWritten)
451{
452 RT_NOREF(pCtx, pCtx, hObj, pvData, cbData, fFlags, pcbWritten);
453
454 LogFlowFuncEnter();
455
456 return VERR_NOT_IMPLEMENTED;
457}
458
459
460/*********************************************************************************************************************************
461* URI callbacks *
462*********************************************************************************************************************************/
463
464DECLCALLBACK(void) VBoxSvcClipboardURITransferPrepareCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData)
465{
466 RT_NOREF(pData);
467
468 LogFlowFuncEnter();
469}
470
471DECLCALLBACK(void) VBoxSvcClipboardURITransferCompleteCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData, int rc)
472{
473 RT_NOREF(pData, rc);
474
475 LogFlowFuncEnter();
476
477 LogRel2(("Shared Clipboard: Transfer complete\n"));
478}
479
480DECLCALLBACK(void) VBoxSvcClipboardURITransferCanceledCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData)
481{
482 LogFlowFuncEnter();
483
484 RT_NOREF(pData);
485
486 LogRel2(("Shared Clipboard: Transfer canceled\n"));
487}
488
489DECLCALLBACK(void) VBoxSvcClipboardURITransferErrorCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData, int rc)
490{
491 LogFlowFuncEnter();
492
493 RT_NOREF(pData, rc);
494
495 LogRel(("Shared Clipboard: Transfer failed with %Rrc\n", rc));
496}
497
498
499/*********************************************************************************************************************************
500* HGCM getters / setters *
501*********************************************************************************************************************************/
502
503/**
504 * Gets an URI message reply from HGCM service parameters.
505 *
506 * @returns VBox status code.
507 * @param cParms Number of HGCM parameters supplied in \a paParms.
508 * @param paParms Array of HGCM parameters.
509 * @param pReply Where to store the reply.
510 */
511int VBoxSvcClipboardURIGetReply(uint32_t cParms, VBOXHGCMSVCPARM paParms[],
512 PVBOXCLIPBOARDREPLY pReply)
513{
514 int rc;
515
516 if (cParms >= VBOX_SHARED_CLIPBOARD_CPARMS_REPLY_MIN)
517 {
518 uint32_t cbPayload = 0;
519
520 /* Note: Context ID (paParms[0]) not used yet. */
521 rc = HGCMSvcGetU32(&paParms[1], &pReply->uType);
522 if (RT_SUCCESS(rc))
523 rc = HGCMSvcGetU32(&paParms[2], &pReply->rc);
524 if (RT_SUCCESS(rc))
525 rc = HGCMSvcGetU32(&paParms[3], &cbPayload);
526 if (RT_SUCCESS(rc))
527 {
528 rc = HGCMSvcGetPv(&paParms[4], &pReply->pvPayload, &pReply->cbPayload);
529 AssertReturn(cbPayload == pReply->cbPayload, VERR_INVALID_PARAMETER);
530 }
531
532 if (RT_SUCCESS(rc))
533 {
534 switch (pReply->uType)
535 {
536 case VBOX_SHAREDCLIPBOARD_REPLYMSGTYPE_LIST_OPEN:
537 {
538 if (cParms >= 6)
539 {
540 rc = HGCMSvcGetU64(&paParms[5], &pReply->u.ListOpen.uHandle);
541 }
542 else
543 rc = VERR_INVALID_PARAMETER;
544 break;
545 }
546
547 case VBOX_SHAREDCLIPBOARD_REPLYMSGTYPE_OBJ_OPEN:
548 {
549 if (cParms >= 6)
550 {
551 rc = HGCMSvcGetU64(&paParms[5], &pReply->u.ObjOpen.uHandle);
552 }
553 else
554 rc = VERR_INVALID_PARAMETER;
555 break;
556 }
557
558 default:
559 break;
560 }
561 }
562 }
563 else
564 rc = VERR_INVALID_PARAMETER;
565
566 LogFlowFuncLeaveRC(rc);
567 return rc;
568}
569
570/**
571 * Gets the URI root entries from HGCM service parameters.
572 *
573 * @returns VBox status code.
574 * @param cParms Number of HGCM parameters supplied in \a paParms.
575 * @param paParms Array of HGCM parameters.
576 * @param pRoots Where to store the URI root entries on success.
577 */
578int VBoxSvcClipboardURIGetRoots(uint32_t cParms, VBOXHGCMSVCPARM paParms[],
579 PVBOXCLIPBOARDROOTS pRoots)
580{
581 int rc;
582
583 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_ROOTS)
584 {
585 /* Note: Context ID (paParms[0]) not used yet. */
586 rc = HGCMSvcGetU32(&paParms[1], &pRoots->fRoots);
587 if (RT_SUCCESS(rc))
588 {
589 uint32_t fMore;
590 rc = HGCMSvcGetU32(&paParms[2], &fMore);
591 if (RT_SUCCESS(rc))
592 pRoots->fMore = RT_BOOL(fMore);
593 }
594 if (RT_SUCCESS(rc))
595 rc = HGCMSvcGetU32(&paParms[3], &pRoots->cRoots);
596 if (RT_SUCCESS(rc))
597 {
598 uint32_t cbRoots;
599 rc = HGCMSvcGetU32(&paParms[4], &cbRoots);
600 if (RT_SUCCESS(rc))
601 rc = HGCMSvcGetPv(&paParms[5], (void **)&pRoots->pszRoots, &pRoots->cbRoots);
602
603 AssertReturn(cbRoots == pRoots->cbRoots, VERR_INVALID_PARAMETER);
604 }
605 }
606 else
607 rc = VERR_INVALID_PARAMETER;
608
609 LogFlowFuncLeaveRC(rc);
610 return rc;
611}
612
613/**
614 * Gets an URI list open request from HGCM service parameters.
615 *
616 * @returns VBox status code.
617 * @param cParms Number of HGCM parameters supplied in \a paParms.
618 * @param paParms Array of HGCM parameters.
619 * @param pOpenParms Where to store the open parameters of the request.
620 */
621int VBoxSvcClipboardURIGetListOpen(uint32_t cParms, VBOXHGCMSVCPARM paParms[],
622 PVBOXCLIPBOARDLISTOPENPARMS pOpenParms)
623{
624 int rc;
625
626 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_OPEN)
627 {
628 uint32_t cbPath = 0;
629 uint32_t cbFilter = 0;
630
631 /* Note: Context ID (paParms[0]) not used yet. */
632 rc = HGCMSvcGetU32(&paParms[1], &pOpenParms->fList);
633 if (RT_SUCCESS(rc))
634 rc = HGCMSvcGetU32(&paParms[2], &cbPath);
635 if (RT_SUCCESS(rc))
636 {
637 rc = HGCMSvcGetStr(&paParms[3], &pOpenParms->pszPath, &pOpenParms->cbPath);
638 AssertReturn(cbPath == pOpenParms->cbPath, VERR_INVALID_PARAMETER);
639 }
640 if (RT_SUCCESS(rc))
641 rc = HGCMSvcGetU32(&paParms[4], &cbFilter);
642 if (RT_SUCCESS(rc))
643 {
644 rc = HGCMSvcGetStr(&paParms[5], &pOpenParms->pszFilter, &pOpenParms->cbFilter);
645 AssertReturn(cbFilter == pOpenParms->cbFilter, VERR_INVALID_PARAMETER);
646 }
647
648 if (RT_SUCCESS(rc))
649 {
650 /** @todo Some more validation. */
651 }
652 }
653 else
654 rc = VERR_INVALID_PARAMETER;
655
656 LogFlowFuncLeaveRC(rc);
657 return rc;
658}
659
660/**
661 * Sets an URI list open request to HGCM service parameters.
662 *
663 * @returns VBox status code.
664 * @param cParms Number of HGCM parameters supplied in \a paParms.
665 * @param paParms Array of HGCM parameters.
666 * @param pOpenParms List open parameters to set.
667 */
668int VBoxSvcClipboardURISetListOpen(uint32_t cParms, VBOXHGCMSVCPARM paParms[],
669 PVBOXCLIPBOARDLISTOPENPARMS pOpenParms)
670{
671 int rc;
672
673 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_OPEN)
674 {
675 HGCMSvcSetU32(&paParms[0], 0 /* uContextID */);
676 HGCMSvcSetU32(&paParms[1], pOpenParms->fList);
677 HGCMSvcSetU32(&paParms[2], pOpenParms->cbFilter);
678 HGCMSvcSetPv (&paParms[3], pOpenParms->pszFilter, pOpenParms->cbFilter);
679 HGCMSvcSetU32(&paParms[4], pOpenParms->cbPath);
680 HGCMSvcSetPv (&paParms[5], pOpenParms->pszPath, pOpenParms->cbPath);
681 HGCMSvcSetU64(&paParms[6], 0); /* OUT: uHandle */
682
683 rc = VINF_SUCCESS;
684 }
685 else
686 rc = VERR_INVALID_PARAMETER;
687
688 LogFlowFuncLeaveRC(rc);
689 return rc;
690}
691
692/**
693 * Sets an URI list close request to HGCM service parameters.
694 *
695 * @returns VBox status code.
696 * @param cParms Number of HGCM parameters supplied in \a paParms.
697 * @param paParms Array of HGCM parameters.
698 * @param hList Handle of list to close.
699 */
700int VBoxSvcClipboardURISetListClose(uint32_t cParms, VBOXHGCMSVCPARM paParms[],
701 SHAREDCLIPBOARDLISTHANDLE hList)
702{
703 int rc;
704
705 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_CLOSE)
706 {
707 HGCMSvcSetU32(&paParms[0], 0 /* uContextID */);
708 HGCMSvcSetU64(&paParms[1], hList);
709
710 rc = VINF_SUCCESS;
711 }
712 else
713 rc = VERR_INVALID_PARAMETER;
714
715 LogFlowFuncLeaveRC(rc);
716 return rc;
717}
718
719/**
720 * Gets an URI list header from HGCM service parameters.
721 *
722 * @returns VBox status code.
723 * @param cParms Number of HGCM parameters supplied in \a paParms.
724 * @param paParms Array of HGCM parameters.
725 * @param phList Where to store the list handle.
726 * @param pListHdr Where to store the list header.
727 */
728int VBoxSvcClipboardURIGetListHdr(uint32_t cParms, VBOXHGCMSVCPARM paParms[],
729 PSHAREDCLIPBOARDLISTHANDLE phList, PVBOXCLIPBOARDLISTHDR pListHdr)
730{
731 int rc;
732
733 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR)
734 {
735 /* Note: Context ID (paParms[0]) not used yet. */
736 rc = HGCMSvcGetU64(&paParms[1], phList);
737 /* Note: Flags (paParms[2]) not used here. */
738 if (RT_SUCCESS(rc))
739 rc = HGCMSvcGetU32(&paParms[3], &pListHdr->fFeatures);
740 if (RT_SUCCESS(rc))
741 rc = HGCMSvcGetU64(&paParms[4], &pListHdr->cTotalObjects);
742 if (RT_SUCCESS(rc))
743 rc = HGCMSvcGetU64(&paParms[5], &pListHdr->cbTotalSize);
744 if (RT_SUCCESS(rc))
745 rc = HGCMSvcGetU32(&paParms[6], &pListHdr->enmCompression);
746 if (RT_SUCCESS(rc))
747 rc = HGCMSvcGetU32(&paParms[7], (uint32_t *)&pListHdr->enmChecksumType);
748
749 if (RT_SUCCESS(rc))
750 {
751 /** @todo Validate pvMetaFmt + cbMetaFmt. */
752 /** @todo Validate header checksum. */
753 }
754 }
755 else
756 rc = VERR_INVALID_PARAMETER;
757
758 LogFlowFuncLeaveRC(rc);
759 return rc;
760}
761
762/**
763 * Sets an URI list header to HGCM service parameters.
764 *
765 * @returns VBox status code.
766 * @param cParms Number of HGCM parameters supplied in \a paParms.
767 * @param paParms Array of HGCM parameters.
768 * @param pListHdr Pointer to data to set to the HGCM parameters.
769 */
770int VBoxSvcClipboardURISetListHdr(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDLISTHDR pListHdr)
771{
772 int rc;
773
774 if ( cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR
775 || cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR)
776 {
777 /** @todo Set pvMetaFmt + cbMetaFmt. */
778 /** @todo Calculate header checksum. */
779
780 HGCMSvcSetU32(&paParms[0], 0 /* uContextID */);
781 HGCMSvcSetU32(&paParms[1], pListHdr->fFeatures);
782 HGCMSvcSetU32(&paParms[2], 0 /* Features, will be returned on success */);
783 HGCMSvcSetU64(&paParms[3], pListHdr->cTotalObjects);
784 HGCMSvcSetU64(&paParms[4], pListHdr->cbTotalSize);
785 HGCMSvcSetU32(&paParms[5], pListHdr->enmCompression);
786 HGCMSvcSetU32(&paParms[6], pListHdr->enmChecksumType);
787
788 rc = VINF_SUCCESS;
789 }
790 else
791 rc = VERR_INVALID_PARAMETER;
792
793 LogFlowFuncLeaveRC(rc);
794 return rc;
795}
796
797/**
798 * Gets an URI list entry from HGCM service parameters.
799 *
800 * @returns VBox status code.
801 * @param cParms Number of HGCM parameters supplied in \a paParms.
802 * @param paParms Array of HGCM parameters.
803 * @param phList Where to store the list handle.
804 * @param pListEntry Where to store the list entry.
805 */
806int VBoxSvcClipboardURIGetListEntry(uint32_t cParms, VBOXHGCMSVCPARM paParms[],
807 PSHAREDCLIPBOARDLISTHANDLE phList, PVBOXCLIPBOARDLISTENTRY pListEntry)
808{
809 int rc;
810
811 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY)
812 {
813 /* Note: Context ID (paParms[0]) not used yet. */
814 rc = HGCMSvcGetU64(&paParms[1], phList);
815 if (RT_SUCCESS(rc))
816 rc = HGCMSvcGetU32(&paParms[2], &pListEntry->fInfo);
817 if (RT_SUCCESS(rc))
818 rc = HGCMSvcGetPv(&paParms[3], (void **)&pListEntry->pszName, &pListEntry->cbName);
819 if (RT_SUCCESS(rc))
820 {
821 uint32_t cbInfo;
822 rc = HGCMSvcGetU32(&paParms[4], &cbInfo);
823 if (RT_SUCCESS(rc))
824 {
825 rc = HGCMSvcGetPv(&paParms[5], &pListEntry->pvInfo, &pListEntry->cbInfo);
826 AssertReturn(cbInfo == pListEntry->cbInfo, VERR_INVALID_PARAMETER);
827 }
828 }
829
830 if (RT_SUCCESS(rc))
831 {
832 if (!SharedClipboardURIListEntryIsValid(pListEntry))
833 rc = VERR_INVALID_PARAMETER;
834 }
835 }
836 else
837 rc = VERR_INVALID_PARAMETER;
838
839 LogFlowFuncLeaveRC(rc);
840 return rc;
841}
842
843/**
844 * Sets an URI data chunk to HGCM service parameters.
845 *
846 * @returns VBox status code.
847 * @param cParms Number of HGCM parameters supplied in \a paParms.
848 * @param paParms Array of HGCM parameters.
849 * @param pListEntry Pointer to data to set to the HGCM parameters.
850 */
851int VBoxSvcClipboardURISetListEntry(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDLISTENTRY pListEntry)
852{
853 int rc;
854
855 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY)
856 {
857 /** @todo Calculate chunk checksum. */
858
859 HGCMSvcSetU32(&paParms[0], 0 /* uContextID */);
860 HGCMSvcSetU32(&paParms[1], pListEntry->fInfo);
861 HGCMSvcSetU32(&paParms[2], pListEntry->cbInfo);
862 HGCMSvcSetPv (&paParms[3], pListEntry->pvInfo, pListEntry->cbInfo);
863
864 rc = VINF_SUCCESS;
865 }
866 else
867 rc = VERR_INVALID_PARAMETER;
868
869 LogFlowFuncLeaveRC(rc);
870 return rc;
871}
872
873/**
874 * Gets an URI error from HGCM service parameters.
875 *
876 * @returns VBox status code.
877 * @param cParms Number of HGCM parameters supplied in \a paParms.
878 * @param paParms Array of HGCM parameters.
879 * @param pRc Where to store the received error code.
880 */
881int VBoxSvcClipboardURIGetError(uint32_t cParms, VBOXHGCMSVCPARM paParms[], int *pRc)
882{
883 AssertPtrReturn(paParms, VERR_INVALID_PARAMETER);
884 AssertPtrReturn(pRc, VERR_INVALID_PARAMETER);
885
886 int rc;
887
888 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_ERROR)
889 {
890 /* Note: Context ID (paParms[0]) not used yet. */
891 rc = HGCMSvcGetU32(&paParms[1], (uint32_t *)pRc); /** @todo int vs. uint32_t !!! */
892 }
893 else
894 rc = VERR_INVALID_PARAMETER;
895
896 LogFlowFuncLeaveRC(rc);
897 return rc;
898}
899
900/**
901 * Handles a guest reply (VBOX_SHARED_CLIPBOARD_GUEST_FN_REPLY) message.
902 *
903 * @returns VBox status code.
904 * @param pClient Pointer to associated client.
905 * @param pTransfer Pointer to transfer to handle guest reply for.
906 * @param cParms Number of function parameters supplied.
907 * @param paParms Array function parameters supplied.
908 */
909int VBoxSvcClipboardURITransferHandleReply(PVBOXCLIPBOARDCLIENT pClient, PSHAREDCLIPBOARDURITRANSFER pTransfer,
910 uint32_t cParms, VBOXHGCMSVCPARM paParms[])
911{
912 RT_NOREF(pClient);
913
914 int rc;
915
916 uint32_t cbReply = sizeof(VBOXCLIPBOARDREPLY);
917 PVBOXCLIPBOARDREPLY pReply = (PVBOXCLIPBOARDREPLY)RTMemAlloc(cbReply);
918 if (pReply)
919 {
920 rc = VBoxSvcClipboardURIGetReply(cParms, paParms, pReply);
921 if (RT_SUCCESS(rc))
922 {
923 PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload
924 = (PSHAREDCLIPBOARDURITRANSFERPAYLOAD)RTMemAlloc(sizeof(SHAREDCLIPBOARDURITRANSFERPAYLOAD));
925 if (pPayload)
926 {
927 pPayload->pvData = pReply;
928 pPayload->cbData = cbReply;
929
930 switch (pReply->uType)
931 {
932 case VBOX_SHAREDCLIPBOARD_REPLYMSGTYPE_LIST_OPEN:
933 {
934 rc = SharedClipboardURITransferEventSignal(pTransfer,
935 SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_OPEN, pPayload);
936 break;
937 }
938
939 case VBOX_SHAREDCLIPBOARD_REPLYMSGTYPE_LIST_CLOSE:
940 {
941 rc = SharedClipboardURITransferEventSignal(pTransfer,
942 SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_CLOSE, pPayload);
943 break;
944 }
945
946 case VBOX_SHAREDCLIPBOARD_REPLYMSGTYPE_OBJ_OPEN:
947 {
948 rc = SharedClipboardURITransferEventSignal(pTransfer,
949 SHAREDCLIPBOARDURITRANSFEREVENTTYPE_OBJ_OPEN, pPayload);
950 break;
951 }
952
953 case VBOX_SHAREDCLIPBOARD_REPLYMSGTYPE_OBJ_CLOSE:
954 {
955 rc = SharedClipboardURITransferEventSignal(pTransfer,
956 SHAREDCLIPBOARDURITRANSFEREVENTTYPE_OBJ_CLOSE, pPayload);
957 break;
958 }
959
960 default:
961 rc = VERR_NOT_FOUND;
962 break;
963 }
964
965 if (RT_FAILURE(rc))
966 {
967 if (pPayload)
968 RTMemFree(pPayload);
969 }
970 }
971 else
972 rc = VERR_NO_MEMORY;
973 }
974 }
975 else
976 rc = VERR_NO_MEMORY;
977
978 if (RT_FAILURE(rc))
979 {
980 if (pReply)
981 RTMemFree(pReply);
982 }
983
984 LogFlowFuncLeaveRC(rc);
985 return rc;
986}
987
988/**
989 * URI client (guest) handler for the Shared Clipboard host service.
990 *
991 * @returns VBox status code.
992 * @param pClient Pointer to associated client.
993 * @param callHandle The client's call handle of this call.
994 * @param u32Function Function number being called.
995 * @param cParms Number of function parameters supplied.
996 * @param paParms Array function parameters supplied.
997 * @param tsArrival Timestamp of arrival.
998 */
999int vboxSvcClipboardURIHandler(PVBOXCLIPBOARDCLIENT pClient,
1000 VBOXHGCMCALLHANDLE callHandle,
1001 uint32_t u32Function,
1002 uint32_t cParms,
1003 VBOXHGCMSVCPARM paParms[],
1004 uint64_t tsArrival)
1005{
1006 RT_NOREF(paParms, tsArrival);
1007
1008 LogFlowFunc(("uClient=%RU32, u32Function=%RU32 (%s), cParms=%RU32, g_pfnExtension=%p\n",
1009 pClient->uClientID, u32Function, VBoxSvcClipboardGuestMsgToStr(u32Function), cParms, g_pfnExtension));
1010
1011 const PVBOXCLIPBOARDCLIENTDATA pClientData = pClient->pData;
1012 AssertPtrReturn(pClientData, VERR_INVALID_POINTER);
1013
1014 /* Check if we've the right mode set. */
1015 if (!vboxSvcClipboardURIMsgIsAllowed(vboxSvcClipboardGetMode(), u32Function))
1016 {
1017 LogFunc(("Wrong clipboard mode, denying access\n"));
1018 return VERR_ACCESS_DENIED;
1019 }
1020
1021 /* A (valid) service extension is needed because VBoxSVC needs to keep track of the
1022 * clipboard areas cached on the host. */
1023 if (!g_pfnExtension)
1024 {
1025#ifdef DEBUG_andy
1026 AssertPtr(g_pfnExtension);
1027#endif
1028 LogFunc(("Invalid / no service extension set, skipping URI handling\n"));
1029 return VERR_NOT_SUPPORTED;
1030 }
1031
1032 int rc = VINF_SUCCESS;
1033
1034 /*
1035 * Pre-check: For certain messages we need to make sure that a (right) transfer is present.
1036 */
1037 PSHAREDCLIPBOARDURITRANSFER pTransfer = NULL;
1038 switch (u32Function)
1039 {
1040 case VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_NOWAIT:
1041 RT_FALL_THROUGH();
1042 case VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_WAIT:
1043 RT_FALL_THROUGH();
1044 case VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_GET:
1045 RT_FALL_THROUGH();
1046 case VBOX_SHARED_CLIPBOARD_GUEST_FN_STATUS:
1047 break;
1048 default:
1049 {
1050 if (!SharedClipboardURICtxGetTotalTransfers(&pClientData->URI))
1051 {
1052 LogFunc(("No transfers found\n"));
1053 rc = VERR_WRONG_ORDER;
1054 break;
1055 }
1056
1057 const uint32_t uTransferID = 0; /* Only one transfer per client is supported at the moment. */
1058
1059 pTransfer = SharedClipboardURICtxGetTransfer(&pClientData->URI, uTransferID);
1060 if (!pTransfer)
1061 {
1062 LogFunc(("Transfer with ID %RU32 not found\n", uTransferID));
1063 rc = VERR_WRONG_ORDER;
1064 }
1065 break;
1066 }
1067 }
1068
1069 if (RT_FAILURE(rc))
1070 return rc;
1071
1072 rc = VERR_INVALID_PARAMETER; /* Play safe. */
1073
1074 switch (u32Function)
1075 {
1076 case VBOX_SHARED_CLIPBOARD_GUEST_FN_STATUS:
1077 {
1078 LogFlowFunc(("[Client %RU32] VBOX_SHARED_CLIPBOARD_GUEST_FN_STATUS\n", pClient->uClientID));
1079
1080 if (cParms != VBOX_SHARED_CLIPBOARD_CPARMS_STATUS)
1081 break;
1082
1083 SHAREDCLIPBOARDURITRANSFERSTATUS uStatus = SHAREDCLIPBOARDURITRANSFERSTATUS_NONE;
1084 rc = HGCMSvcGetU32(&paParms[1], &uStatus);
1085 if (RT_FAILURE(rc))
1086 break;
1087
1088 LogFlowFunc(("uStatus: %RU32\n", uStatus));
1089
1090 if ( uStatus == SHAREDCLIPBOARDURITRANSFERSTATUS_RUNNING
1091 && !SharedClipboardURICtxTransfersMaximumReached(&pClientData->URI))
1092 {
1093 SharedClipboardURICtxTransfersCleanup(&pClientData->URI);
1094
1095 SHAREDCLIPBOARDURITRANSFERDIR enmDir = SHAREDCLIPBOARDURITRANSFERDIR_READ;
1096
1097 PSHAREDCLIPBOARDURITRANSFER pTransfer;
1098 rc = SharedClipboardURITransferCreate(enmDir,
1099 SHAREDCLIPBOARDSOURCE_REMOTE, &pTransfer);
1100 if (RT_SUCCESS(rc))
1101 {
1102 rc = vboxSvcClipboardURIAreaRegister(&pClientData->State, pTransfer);
1103 if (RT_SUCCESS(rc))
1104 {
1105 SHAREDCLIPBOARDPROVIDERCREATIONCTX creationCtx;
1106 RT_ZERO(creationCtx);
1107
1108 creationCtx.enmSource = pClientData->State.enmSource;
1109
1110 RT_ZERO(creationCtx.Interface);
1111 creationCtx.Interface.pfnTransferOpen = vboxSvcClipboardURITransferOpen;
1112 creationCtx.Interface.pfnTransferClose = vboxSvcClipboardURITransferClose;
1113 creationCtx.Interface.pfnListOpen = vboxSvcClipboardURIListOpen;
1114 creationCtx.Interface.pfnListClose = vboxSvcClipboardURIListClose;
1115 creationCtx.Interface.pfnObjOpen = vboxSvcClipboardURIObjOpen;
1116 creationCtx.Interface.pfnObjClose = vboxSvcClipboardURIObjClose;
1117
1118 if (enmDir == SHAREDCLIPBOARDURITRANSFERDIR_READ)
1119 {
1120 creationCtx.Interface.pfnGetRoots = vboxSvcClipboardURIGetRoots;
1121 creationCtx.Interface.pfnListHdrRead = vboxSvcClipboardURIListHdrRead;
1122 creationCtx.Interface.pfnListEntryRead = vboxSvcClipboardURIListEntryRead;
1123 creationCtx.Interface.pfnObjRead = vboxSvcClipboardURIObjRead;
1124 }
1125 else
1126 {
1127 AssertFailed();
1128 }
1129
1130 creationCtx.pvUser = pClient;
1131
1132 /* Register needed callbacks so that we can wait for the meta data to arrive here. */
1133 SHAREDCLIPBOARDURITRANSFERCALLBACKS Callbacks;
1134 RT_ZERO(Callbacks);
1135
1136 Callbacks.pvUser = pClientData;
1137
1138 Callbacks.pfnTransferPrepare = VBoxSvcClipboardURITransferPrepareCallback;
1139 Callbacks.pfnTransferComplete = VBoxSvcClipboardURITransferCompleteCallback;
1140 Callbacks.pfnTransferCanceled = VBoxSvcClipboardURITransferCanceledCallback;
1141 Callbacks.pfnTransferError = VBoxSvcClipboardURITransferErrorCallback;
1142
1143 SharedClipboardURITransferSetCallbacks(pTransfer, &Callbacks);
1144
1145 rc = SharedClipboardURITransferSetInterface(pTransfer, &creationCtx);
1146 if (RT_SUCCESS(rc))
1147 rc = SharedClipboardURICtxTransferAdd(&pClientData->URI, pTransfer);
1148 }
1149
1150 if (RT_SUCCESS(rc))
1151 {
1152 rc = VBoxClipboardSvcImplURITransferCreate(pClientData, pTransfer);
1153 if (RT_SUCCESS(rc))
1154 rc = VBoxClipboardSvcImplFormatAnnounce(pClientData, VBOX_SHARED_CLIPBOARD_FMT_URI_LIST);
1155 }
1156
1157 if (RT_FAILURE(rc))
1158 {
1159 VBoxClipboardSvcImplURITransferDestroy(pClientData, pTransfer);
1160 SharedClipboardURITransferDestroy(pTransfer);
1161 }
1162 }
1163 }
1164 else
1165 rc = VERR_SHCLPB_MAX_TRANSFERS_REACHED;
1166
1167 LogFlowFunc(("[Client %RU32] VBOX_SHARED_CLIPBOARD_GUEST_FN_STATUS: %Rrc\n", pClient->uClientID, rc));
1168
1169 if (RT_FAILURE(rc))
1170 LogRel(("Shared Clipboard: Initializing transfer failed with %Rrc\n", rc));
1171
1172 break;
1173 }
1174
1175 case VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_NOWAIT:
1176 {
1177 rc = vboxSvcClipboardMsgPeek(pClient, callHandle, cParms, paParms, false /*fWait*/);
1178 break;
1179 }
1180
1181 case VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_WAIT:
1182 {
1183 rc = vboxSvcClipboardMsgPeek(pClient, callHandle, cParms, paParms, true /*fWait*/);
1184 break;
1185 }
1186
1187 case VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_GET:
1188 {
1189 rc = vboxSvcClipboardMsgGet(pClient, callHandle, cParms, paParms);
1190 break;
1191 }
1192
1193 case VBOX_SHARED_CLIPBOARD_GUEST_FN_REPLY:
1194 {
1195 rc = VBoxSvcClipboardURITransferHandleReply(pClient, pTransfer, cParms, paParms);
1196 break;
1197 }
1198
1199 case VBOX_SHARED_CLIPBOARD_GUEST_FN_ROOTS:
1200 {
1201 VBOXCLIPBOARDROOTS Roots;
1202 rc = VBoxSvcClipboardURIGetRoots(cParms, paParms, &Roots);
1203 if (RT_SUCCESS(rc))
1204 {
1205 void *pvData = SharedClipboardURIRootsDup(&Roots);
1206 uint32_t cbData = sizeof(VBOXCLIPBOARDROOTS);
1207
1208 PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
1209 rc = SharedClipboardURITransferPayloadAlloc(SHAREDCLIPBOARDURITRANSFEREVENTTYPE_GET_ROOTS,
1210 pvData, cbData, &pPayload);
1211 if (RT_SUCCESS(rc))
1212 rc = SharedClipboardURITransferEventSignal(pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_GET_ROOTS,
1213 pPayload);
1214 }
1215 break;
1216 }
1217
1218 case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_OPEN:
1219 {
1220 VBOXCLIPBOARDLISTOPENPARMS listOpenParms;
1221 rc = VBoxSvcClipboardURIGetListOpen(cParms, paParms, &listOpenParms);
1222 if (RT_SUCCESS(rc))
1223 {
1224 SHAREDCLIPBOARDLISTHANDLE hList;
1225 rc = SharedClipboardURITransferListOpen(pTransfer, &listOpenParms, &hList);
1226 if (RT_SUCCESS(rc))
1227 {
1228 /* Return list handle. */
1229 HGCMSvcSetU32(&paParms[1], hList);
1230 }
1231 }
1232 break;
1233 }
1234
1235 case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_CLOSE:
1236 {
1237 if (cParms != VBOX_SHARED_CLIPBOARD_CPARMS_LIST_CLOSE)
1238 break;
1239
1240 SHAREDCLIPBOARDLISTHANDLE hList;
1241 /* Note: Context ID (paParms[0]) not used yet. */
1242 rc = HGCMSvcGetU64(&paParms[1], &hList);
1243 if (RT_SUCCESS(rc))
1244 {
1245 rc = SharedClipboardURITransferListClose(pTransfer, hList);
1246 }
1247 break;
1248 }
1249
1250 case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_READ:
1251 {
1252 if (cParms != VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR)
1253 break;
1254
1255 SHAREDCLIPBOARDLISTHANDLE hList;
1256 /* Note: Context ID (paParms[0]) not used yet. */
1257 rc = HGCMSvcGetU64(&paParms[1], &hList); /* Get list handle. */
1258 if (RT_SUCCESS(rc))
1259 {
1260 VBOXCLIPBOARDLISTHDR hdrList;
1261 rc = SharedClipboardURITransferListGetHeader(pTransfer, hList, &hdrList);
1262 if (RT_SUCCESS(rc))
1263 rc = VBoxSvcClipboardURISetListHdr(cParms, paParms, &hdrList);
1264 }
1265 break;
1266 }
1267
1268 case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_WRITE:
1269 {
1270 VBOXCLIPBOARDLISTHDR hdrList;
1271 rc = SharedClipboardURIListHdrInit(&hdrList);
1272 if (RT_SUCCESS(rc))
1273 {
1274 SHAREDCLIPBOARDLISTHANDLE hList;
1275 rc = VBoxSvcClipboardURIGetListHdr(cParms, paParms, &hList, &hdrList);
1276 if (RT_SUCCESS(rc))
1277 {
1278 void *pvData = SharedClipboardURIListHdrDup(&hdrList);
1279 uint32_t cbData = sizeof(VBOXCLIPBOARDLISTHDR);
1280
1281 PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
1282 rc = SharedClipboardURITransferPayloadAlloc(SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_HDR_WRITE,
1283 pvData, cbData, &pPayload);
1284 if (RT_SUCCESS(rc))
1285 {
1286 rc = SharedClipboardURITransferEventSignal(pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_HDR_WRITE,
1287 pPayload);
1288 }
1289 }
1290 }
1291 break;
1292 }
1293
1294 case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_ENTRY_READ:
1295 {
1296 if (cParms != VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY)
1297 break;
1298
1299 SHAREDCLIPBOARDLISTHANDLE hList;
1300 /* Note: Context ID (paParms[0]) not used yet. */
1301 rc = HGCMSvcGetU64(&paParms[1], &hList); /* Get list handle. */
1302 if (RT_SUCCESS(rc))
1303 {
1304 VBOXCLIPBOARDLISTENTRY entryList;
1305 rc = SharedClipboardURITransferListRead(pTransfer, hList, &entryList);
1306 }
1307 break;
1308 }
1309
1310 case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_ENTRY_WRITE:
1311 {
1312 VBOXCLIPBOARDLISTENTRY entryList;
1313 rc = SharedClipboardURIListEntryInit(&entryList);
1314 if (RT_SUCCESS(rc))
1315 {
1316 SHAREDCLIPBOARDLISTHANDLE hList;
1317 rc = VBoxSvcClipboardURIGetListEntry(cParms, paParms, &hList, &entryList);
1318 if (RT_SUCCESS(rc))
1319 {
1320 void *pvData = SharedClipboardURIListEntryDup(&entryList);
1321 uint32_t cbData = sizeof(VBOXCLIPBOARDLISTENTRY);
1322
1323 PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
1324 rc = SharedClipboardURITransferPayloadAlloc(SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_ENTRY_WRITE,
1325 pvData, cbData, &pPayload);
1326 if (RT_SUCCESS(rc))
1327 {
1328 rc = SharedClipboardURITransferEventSignal(pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_ENTRY_WRITE,
1329 pPayload);
1330 }
1331
1332 }
1333 }
1334 break;
1335 }
1336
1337 #if 0
1338 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DIR:
1339 {
1340 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DIR\n"));
1341
1342 VBOXCLIPBOARDDIRDATA dirData;
1343 rc = VBoxSvcClipboardURIGetDir(cParms, paParms, &dirData);
1344 if (RT_SUCCESS(rc))
1345 {
1346 SharedClipboardArea *pArea = SharedClipboardURITransferGetArea(pTransfer);
1347 AssertPtrBreakStmt(pArea, rc = VERR_INVALID_POINTER);
1348
1349 const char *pszCacheDir = pArea->GetDirAbs();
1350 char *pszDir = RTPathJoinA(pszCacheDir, dirData.pszPath);
1351 if (pszDir)
1352 {
1353 LogFlowFunc(("pszDir=%s\n", pszDir));
1354
1355 rc = RTDirCreateFullPath(pszDir, dirData.fMode);
1356 if (RT_SUCCESS(rc))
1357 {
1358 SHAREDCLIPBOARDAREAOBJ Obj = { SHAREDCLIPBOARDAREAOBJTYPE_DIR, SHAREDCLIPBOARDAREAOBJSTATE_COMPLETE };
1359 int rc2 = pArea->AddObject(pszDir, Obj);
1360 AssertRC(rc2);
1361 }
1362
1363 RTStrFree(pszDir);
1364 }
1365 else
1366 rc = VERR_NO_MEMORY;
1367 }
1368 break;
1369 }
1370
1371 case VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_FILE_HDR:
1372 {
1373 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_FILE_HDR\n"));
1374
1375 VBOXCLIPBOARDFILEHDR fileHdr;
1376 rc = VBoxSvcClipboardURISetFileHdr(cParms, paParms, &fileHdr);
1377 break;
1378 }
1379
1380 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_FILE_HDR:
1381 {
1382 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_FILE_HDR\n"));
1383
1384 if (!SharedClipboardURIObjCtxIsValid(SharedClipboardURITransferGetCurrentObjCtx(pTransfer)))
1385 {
1386 pTransfer->State.ObjCtx.pObj = new SharedClipboardURIObject(SharedClipboardURIObject::Type_File);
1387 if (pTransfer->State.ObjCtx.pObj) /** @todo Can this throw? */
1388 {
1389 rc = VINF_SUCCESS;
1390 }
1391 else
1392 rc = VERR_NO_MEMORY;
1393 }
1394 else /* There still is another object being processed? */
1395 rc = VERR_WRONG_ORDER;
1396
1397 if (RT_FAILURE(rc))
1398 break;
1399
1400 VBOXCLIPBOARDFILEHDR fileHdr;
1401 rc = VBoxSvcClipboardURIGetFileHdr(cParms, paParms, &fileHdr);
1402 if (RT_SUCCESS(rc))
1403 {
1404 SharedClipboardArea *pArea = SharedClipboardURITransferGetArea(pTransfer);
1405 AssertPtrBreakStmt(pArea, rc = VERR_WRONG_ORDER);
1406
1407 const char *pszCacheDir = pArea->GetDirAbs();
1408
1409 char pszPathAbs[RTPATH_MAX];
1410 rc = RTPathJoin(pszPathAbs, sizeof(pszPathAbs), pszCacheDir, fileHdr.pszFilePath);
1411 if (RT_SUCCESS(rc))
1412 {
1413 rc = SharedClipboardPathSanitize(pszPathAbs, sizeof(pszPathAbs));
1414 if (RT_SUCCESS(rc))
1415 {
1416 PSHAREDCLIPBOARDCLIENTURIOBJCTX pObjCtx = SharedClipboardURITransferGetCurrentObjCtx(pTransfer);
1417 AssertPtrBreakStmt(pObjCtx, VERR_INVALID_POINTER);
1418
1419 SharedClipboardURIObject *pObj = pObjCtx->pObj;
1420 AssertPtrBreakStmt(pObj, VERR_INVALID_POINTER);
1421
1422 LogFlowFunc(("pszFile=%s\n", pszPathAbs));
1423
1424 /** @todo Add sparse file support based on fFlags? (Use Open(..., fFlags | SPARSE). */
1425 rc = pObj->OpenFileEx(pszPathAbs, SharedClipboardURIObject::View_Target,
1426 RTFILE_O_CREATE_REPLACE | RTFILE_O_WRITE | RTFILE_O_DENY_WRITE,
1427 (fileHdr.fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR);
1428 if (RT_SUCCESS(rc))
1429 {
1430 rc = pObj->SetSize(fileHdr.cbSize);
1431
1432 /** @todo Unescape path before printing. */
1433 LogRel2(("Clipboard: Transferring guest file '%s' to host (%RU64 bytes, mode 0x%x)\n",
1434 pObj->GetDestPathAbs().c_str(), pObj->GetSize(), pObj->GetMode()));
1435
1436 if (pObj->IsComplete()) /* 0-byte file? We're done already. */
1437 {
1438 /** @todo Sanitize path. */
1439 LogRel2(("Clipboard: Transferring guest file '%s' (0 bytes) to host complete\n",
1440 pObj->GetDestPathAbs().c_str()));
1441
1442 SharedClipboardURIObjCtxDestroy(&pTransfer->State.ObjCtx);
1443 }
1444
1445 SHAREDCLIPBOARDAREAOBJ Obj = { SHAREDCLIPBOARDAREAOBJTYPE_FILE, SHAREDCLIPBOARDAREAOBJSTATE_NONE };
1446 int rc2 = pArea->AddObject(pszPathAbs, Obj);
1447 AssertRC(rc2);
1448 }
1449 else
1450 LogRel(("Clipboard: Error opening/creating guest file '%s' on host, rc=%Rrc\n", pszPathAbs, rc));
1451 }
1452 }
1453 }
1454 break;
1455 }
1456
1457 case VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_FILE_DATA:
1458 {
1459 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_READ_FILE_DATA\n"));
1460
1461 VBOXCLIPBOARDFILEDATA fileData;
1462 rc = VBoxSvcClipboardURISetFileData(cParms, paParms, &fileData);
1463 break;
1464 }
1465
1466 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_FILE_DATA:
1467 {
1468 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_FILE_DATA\n"));
1469
1470 if (!SharedClipboardURIObjCtxIsValid(&pTransfer->State.ObjCtx))
1471 {
1472 rc = VERR_WRONG_ORDER;
1473 break;
1474 }
1475
1476 VBOXCLIPBOARDFILEDATA fileData;
1477 rc = VBoxSvcClipboardURIGetFileData(cParms, paParms, &fileData);
1478 if (RT_SUCCESS(rc))
1479 {
1480 PSHAREDCLIPBOARDCLIENTURIOBJCTX pObjCtx = SharedClipboardURITransferGetCurrentObjCtx(pTransfer);
1481 AssertPtrBreakStmt(pObjCtx, VERR_INVALID_POINTER);
1482
1483 SharedClipboardURIObject *pObj = pObjCtx->pObj;
1484 AssertPtrBreakStmt(pObj, VERR_INVALID_POINTER);
1485
1486 uint32_t cbWritten;
1487 rc = pObj->Write(fileData.pvData, fileData.cbData, &cbWritten);
1488 if (RT_SUCCESS(rc))
1489 {
1490 Assert(cbWritten <= fileData.cbData);
1491 if (cbWritten < fileData.cbData)
1492 {
1493 /** @todo What to do when the host's disk is full? */
1494 rc = VERR_DISK_FULL;
1495 }
1496
1497 if ( pObj->IsComplete()
1498 || RT_FAILURE(rc))
1499 SharedClipboardURIObjCtxDestroy(&pTransfer->State.ObjCtx);
1500 }
1501 else
1502 LogRel(("Clipboard: Error writing guest file data for '%s', rc=%Rrc\n", pObj->GetDestPathAbs().c_str(), rc));
1503 }
1504 break;
1505 }
1506#endif
1507 case VBOX_SHARED_CLIPBOARD_GUEST_FN_CANCEL:
1508 {
1509 LogRel2(("Shared Clipboard: Transfer canceled\n"));
1510 break;
1511 }
1512
1513 case VBOX_SHARED_CLIPBOARD_GUEST_FN_ERROR:
1514 {
1515 int rcGuest;
1516 rc = VBoxSvcClipboardURIGetError(cParms,paParms, &rcGuest);
1517 if (RT_SUCCESS(rc))
1518 LogRel(("Shared Clipboard: Transfer error: %Rrc\n", rcGuest));
1519 break;
1520 }
1521
1522 default:
1523 LogFunc(("Not implemented\n"));
1524 break;
1525 }
1526
1527 if (rc != VINF_HGCM_ASYNC_EXECUTE)
1528 {
1529 /* Tell the client that the call is complete (unblocks waiting). */
1530 LogFlowFunc(("[Client %RU32] Calling pfnCallComplete w/ rc=%Rrc\n", pClient->uClientID, rc));
1531 AssertPtr(g_pHelpers);
1532 g_pHelpers->pfnCallComplete(callHandle, rc);
1533 }
1534
1535 LogFlowFunc(("[Client %RU32] Returning rc=%Rrc\n", pClient->uClientID, rc));
1536 return rc;
1537}
1538
1539/**
1540 * URI host handler for the Shared Clipboard host service.
1541 *
1542 * @returns VBox status code.
1543 * @param u32Function Function number being called.
1544 * @param cParms Number of function parameters supplied.
1545 * @param paParms Array function parameters supplied.
1546 */
1547int vboxSvcClipboardURIHostHandler(uint32_t u32Function,
1548 uint32_t cParms,
1549 VBOXHGCMSVCPARM paParms[])
1550{
1551 RT_NOREF(cParms, paParms);
1552
1553 int rc = VERR_NOT_IMPLEMENTED; /* Play safe. */
1554
1555 switch (u32Function)
1556 {
1557 case VBOX_SHARED_CLIPBOARD_HOST_FN_CANCEL:
1558 /** @todo */
1559 break;
1560
1561 case VBOX_SHARED_CLIPBOARD_HOST_FN_ERROR:
1562 /** @todo */
1563 break;
1564
1565 default:
1566 break;
1567
1568 }
1569
1570 LogFlowFuncLeaveRC(rc);
1571 return rc;
1572}
1573
1574/**
1575 * Registers an URI clipboard area.
1576 *
1577 * @returns VBox status code.
1578 * @param pClientState Client state to use.
1579 * @param pTransfer URI transfer to register a clipboard area for.
1580 */
1581int vboxSvcClipboardURIAreaRegister(PVBOXCLIPBOARDCLIENTSTATE pClientState, PSHAREDCLIPBOARDURITRANSFER pTransfer)
1582{
1583 LogFlowFuncEnter();
1584
1585 AssertMsgReturn(pTransfer->pArea == NULL, ("An area already is registered for this transfer\n"),
1586 VERR_WRONG_ORDER);
1587
1588 pTransfer->pArea = new SharedClipboardArea();
1589 if (!pTransfer->pArea)
1590 return VERR_NO_MEMORY;
1591
1592 int rc;
1593
1594 if (g_pfnExtension)
1595 {
1596 VBOXCLIPBOARDEXTAREAPARMS parms;
1597 RT_ZERO(parms);
1598
1599 parms.uID = NIL_SHAREDCLIPBOARDAREAID;
1600
1601 /* As the meta data is now complete, register a new clipboard on the host side. */
1602 rc = g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_AREA_REGISTER, &parms, sizeof(parms));
1603 if (RT_SUCCESS(rc))
1604 {
1605 /* Note: Do *not* specify SHAREDCLIPBOARDAREA_OPEN_FLAGS_MUST_NOT_EXIST as flags here, as VBoxSVC took care of the
1606 * clipboard area creation already. */
1607 rc = pTransfer->pArea->OpenTemp(parms.uID /* Area ID */,
1608 SHAREDCLIPBOARDAREA_OPEN_FLAGS_NONE);
1609 }
1610
1611 LogFlowFunc(("Registered new clipboard area (%RU32) by client %RU32 with rc=%Rrc\n",
1612 parms.uID, pClientState->u32ClientID, rc));
1613 }
1614 else
1615 rc = VERR_NOT_SUPPORTED;
1616
1617 LogFlowFuncLeaveRC(rc);
1618 return rc;
1619}
1620
1621/**
1622 * Unregisters an URI clipboard area.
1623 *
1624 * @returns VBox status code.
1625 * @param pClientState Client state to use.
1626 * @param pTransfer URI transfer to unregister a clipboard area from.
1627 */
1628int vboxSvcClipboardURIAreaUnregister(PVBOXCLIPBOARDCLIENTSTATE pClientState, PSHAREDCLIPBOARDURITRANSFER pTransfer)
1629{
1630 LogFlowFuncEnter();
1631
1632 if (!pTransfer->pArea)
1633 return VINF_SUCCESS;
1634
1635 int rc = VINF_SUCCESS;
1636
1637 if (g_pfnExtension)
1638 {
1639 VBOXCLIPBOARDEXTAREAPARMS parms;
1640 RT_ZERO(parms);
1641
1642 parms.uID = pTransfer->pArea->GetID();
1643
1644 rc = g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_AREA_UNREGISTER, &parms, sizeof(parms));
1645 if (RT_SUCCESS(rc))
1646 {
1647 rc = pTransfer->pArea->Close();
1648 if (RT_SUCCESS(rc))
1649 {
1650 delete pTransfer->pArea;
1651 pTransfer->pArea = NULL;
1652 }
1653 }
1654
1655 LogFlowFunc(("Unregistered clipboard area (%RU32) by client %RU32 with rc=%Rrc\n",
1656 parms.uID, pClientState->u32ClientID, rc));
1657 }
1658
1659 delete pTransfer->pArea;
1660 pTransfer->pArea = NULL;
1661
1662 LogFlowFuncLeaveRC(rc);
1663 return rc;
1664}
1665
1666/**
1667 * Attaches to an existing (registered) URI clipboard area.
1668 *
1669 * @returns VBox status code.
1670 * @param pClientState Client state to use.
1671 * @param pTransfer URI transfer to attach a clipboard area to.
1672 * @param uID ID of clipboard area to to attach to. Specify 0 to attach to the most recent one.
1673 */
1674int vboxSvcClipboardURIAreaAttach(PVBOXCLIPBOARDCLIENTSTATE pClientState, PSHAREDCLIPBOARDURITRANSFER pTransfer,
1675 SHAREDCLIPBOARDAREAID uID)
1676{
1677 LogFlowFuncEnter();
1678
1679 AssertMsgReturn(pTransfer->pArea == NULL, ("An area already is attached to this transfer\n"),
1680 VERR_WRONG_ORDER);
1681
1682 pTransfer->pArea = new SharedClipboardArea();
1683 if (!pTransfer->pArea)
1684 return VERR_NO_MEMORY;
1685
1686 int rc = VINF_SUCCESS;
1687
1688 if (g_pfnExtension)
1689 {
1690 VBOXCLIPBOARDEXTAREAPARMS parms;
1691 RT_ZERO(parms);
1692
1693 parms.uID = uID; /* 0 means most recent clipboard area. */
1694
1695 /* The client now needs to attach to the most recent clipboard area
1696 * to keep a reference to it. The host does the actual book keeping / cleanup then.
1697 *
1698 * This might fail if the host does not have a most recent clipboard area (yet). */
1699 rc = g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_AREA_ATTACH, &parms, sizeof(parms));
1700 if (RT_SUCCESS(rc))
1701 rc = pTransfer->pArea->OpenTemp(parms.uID /* Area ID */);
1702
1703 LogFlowFunc(("Attached client %RU32 to clipboard area %RU32 with rc=%Rrc\n",
1704 pClientState->u32ClientID, parms.uID, rc));
1705 }
1706 else
1707 rc = VERR_NOT_SUPPORTED;
1708
1709 LogFlowFuncLeaveRC(rc);
1710 return rc;
1711}
1712
1713/**
1714 * Detaches from an URI clipboard area.
1715 *
1716 * @returns VBox status code.
1717 * @param pClientState Client state to use.
1718 * @param pTransfer URI transfer to detach a clipboard area from.
1719 */
1720int vboxSvcClipboardURIAreaDetach(PVBOXCLIPBOARDCLIENTSTATE pClientState, PSHAREDCLIPBOARDURITRANSFER pTransfer)
1721{
1722 LogFlowFuncEnter();
1723
1724 if (!pTransfer->pArea)
1725 return VINF_SUCCESS;
1726
1727 const uint32_t uAreaID = pTransfer->pArea->GetID();
1728
1729 int rc = VINF_SUCCESS;
1730
1731 if (g_pfnExtension)
1732 {
1733 VBOXCLIPBOARDEXTAREAPARMS parms;
1734 RT_ZERO(parms);
1735 parms.uID = uAreaID;
1736
1737 rc = g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_AREA_DETACH, &parms, sizeof(parms));
1738
1739 LogFlowFunc(("Detached client %RU32 from clipboard area %RU32 with rc=%Rrc\n",
1740 pClientState->u32ClientID, uAreaID, rc));
1741 }
1742
1743 delete pTransfer->pArea;
1744 pTransfer->pArea = NULL;
1745
1746 LogFlowFuncLeaveRC(rc);
1747 return rc;
1748}
1749
Note: See TracBrowser for help on using the repository browser.

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