VirtualBox

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

Last change on this file since 79702 was 79702, 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: 61.2 KB
Line 
1/* $Id: VBoxSharedClipboardSvc-uri.cpp 79702 2019-07-11 19:34:05Z 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* HGCM getters / setters *
500*********************************************************************************************************************************/
501
502/**
503 * Gets an URI message reply from HGCM service parameters.
504 *
505 * @returns VBox status code.
506 * @param cParms Number of HGCM parameters supplied in \a paParms.
507 * @param paParms Array of HGCM parameters.
508 * @param pReply Where to store the reply.
509 */
510int VBoxSvcClipboardURIGetReply(uint32_t cParms, VBOXHGCMSVCPARM paParms[],
511 PVBOXCLIPBOARDREPLY pReply)
512{
513 int rc;
514
515 if (cParms >= VBOX_SHARED_CLIPBOARD_CPARMS_REPLY_MIN)
516 {
517 uint32_t cbPayload = 0;
518
519 /* Note: Context ID (paParms[0]) not used yet. */
520 rc = HGCMSvcGetU32(&paParms[1], &pReply->uType);
521 if (RT_SUCCESS(rc))
522 rc = HGCMSvcGetU32(&paParms[2], &pReply->rc);
523 if (RT_SUCCESS(rc))
524 rc = HGCMSvcGetU32(&paParms[3], &cbPayload);
525 if (RT_SUCCESS(rc))
526 {
527 rc = HGCMSvcGetPv(&paParms[4], &pReply->pvPayload, &pReply->cbPayload);
528 AssertReturn(cbPayload == pReply->cbPayload, VERR_INVALID_PARAMETER);
529 }
530
531 if (RT_SUCCESS(rc))
532 {
533 switch (pReply->uType)
534 {
535 case VBOX_SHAREDCLIPBOARD_REPLYMSGTYPE_LIST_OPEN:
536 {
537 if (cParms >= 6)
538 {
539 rc = HGCMSvcGetU64(&paParms[5], &pReply->u.ListOpen.uHandle);
540 }
541 else
542 rc = VERR_INVALID_PARAMETER;
543 break;
544 }
545
546 case VBOX_SHAREDCLIPBOARD_REPLYMSGTYPE_OBJ_OPEN:
547 {
548 if (cParms >= 6)
549 {
550 rc = HGCMSvcGetU64(&paParms[5], &pReply->u.ObjOpen.uHandle);
551 }
552 else
553 rc = VERR_INVALID_PARAMETER;
554 break;
555 }
556
557 default:
558 break;
559 }
560 }
561 }
562 else
563 rc = VERR_INVALID_PARAMETER;
564
565 LogFlowFuncLeaveRC(rc);
566 return rc;
567}
568
569/**
570 * Gets the URI root entries from HGCM service parameters.
571 *
572 * @returns VBox status code.
573 * @param cParms Number of HGCM parameters supplied in \a paParms.
574 * @param paParms Array of HGCM parameters.
575 * @param pRoots Where to store the URI root entries on success.
576 */
577int VBoxSvcClipboardURIGetRoots(uint32_t cParms, VBOXHGCMSVCPARM paParms[],
578 PVBOXCLIPBOARDROOTS pRoots)
579{
580 int rc;
581
582 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_ROOTS)
583 {
584 /* Note: Context ID (paParms[0]) not used yet. */
585 rc = HGCMSvcGetU32(&paParms[1], &pRoots->fRoots);
586 if (RT_SUCCESS(rc))
587 {
588 uint32_t fMore;
589 rc = HGCMSvcGetU32(&paParms[2], &fMore);
590 if (RT_SUCCESS(rc))
591 pRoots->fMore = RT_BOOL(fMore);
592 }
593 if (RT_SUCCESS(rc))
594 rc = HGCMSvcGetU32(&paParms[3], &pRoots->cRoots);
595 if (RT_SUCCESS(rc))
596 {
597 uint32_t cbRoots;
598 rc = HGCMSvcGetU32(&paParms[4], &cbRoots);
599 if (RT_SUCCESS(rc))
600 rc = HGCMSvcGetPv(&paParms[5], (void **)&pRoots->pszRoots, &pRoots->cbRoots);
601
602 AssertReturn(cbRoots == pRoots->cbRoots, VERR_INVALID_PARAMETER);
603 }
604 }
605 else
606 rc = VERR_INVALID_PARAMETER;
607
608 LogFlowFuncLeaveRC(rc);
609 return rc;
610}
611
612/**
613 * Gets an URI list open request from HGCM service parameters.
614 *
615 * @returns VBox status code.
616 * @param cParms Number of HGCM parameters supplied in \a paParms.
617 * @param paParms Array of HGCM parameters.
618 * @param pOpenParms Where to store the open parameters of the request.
619 */
620int VBoxSvcClipboardURIGetListOpen(uint32_t cParms, VBOXHGCMSVCPARM paParms[],
621 PVBOXCLIPBOARDLISTOPENPARMS pOpenParms)
622{
623 int rc;
624
625 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_OPEN)
626 {
627 uint32_t cbPath = 0;
628 uint32_t cbFilter = 0;
629
630 /* Note: Context ID (paParms[0]) not used yet. */
631 rc = HGCMSvcGetU32(&paParms[1], &pOpenParms->fList);
632 if (RT_SUCCESS(rc))
633 rc = HGCMSvcGetU32(&paParms[2], &cbPath);
634 if (RT_SUCCESS(rc))
635 {
636 rc = HGCMSvcGetStr(&paParms[3], &pOpenParms->pszPath, &pOpenParms->cbPath);
637 AssertReturn(cbPath == pOpenParms->cbPath, VERR_INVALID_PARAMETER);
638 }
639 if (RT_SUCCESS(rc))
640 rc = HGCMSvcGetU32(&paParms[4], &cbFilter);
641 if (RT_SUCCESS(rc))
642 {
643 rc = HGCMSvcGetStr(&paParms[5], &pOpenParms->pszFilter, &pOpenParms->cbFilter);
644 AssertReturn(cbFilter == pOpenParms->cbFilter, VERR_INVALID_PARAMETER);
645 }
646
647 if (RT_SUCCESS(rc))
648 {
649 /** @todo Some more validation. */
650 }
651 }
652 else
653 rc = VERR_INVALID_PARAMETER;
654
655 LogFlowFuncLeaveRC(rc);
656 return rc;
657}
658
659/**
660 * Sets an URI list open request to HGCM service parameters.
661 *
662 * @returns VBox status code.
663 * @param cParms Number of HGCM parameters supplied in \a paParms.
664 * @param paParms Array of HGCM parameters.
665 * @param pOpenParms List open parameters to set.
666 */
667int VBoxSvcClipboardURISetListOpen(uint32_t cParms, VBOXHGCMSVCPARM paParms[],
668 PVBOXCLIPBOARDLISTOPENPARMS pOpenParms)
669{
670 int rc;
671
672 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_OPEN)
673 {
674 HGCMSvcSetU32(&paParms[0], 0 /* uContextID */);
675 HGCMSvcSetU32(&paParms[1], pOpenParms->fList);
676 HGCMSvcSetU32(&paParms[2], pOpenParms->cbFilter);
677 HGCMSvcSetPv (&paParms[3], pOpenParms->pszFilter, pOpenParms->cbFilter);
678 HGCMSvcSetU32(&paParms[4], pOpenParms->cbPath);
679 HGCMSvcSetPv (&paParms[5], pOpenParms->pszPath, pOpenParms->cbPath);
680 HGCMSvcSetU64(&paParms[6], 0); /* OUT: uHandle */
681
682 rc = VINF_SUCCESS;
683 }
684 else
685 rc = VERR_INVALID_PARAMETER;
686
687 LogFlowFuncLeaveRC(rc);
688 return rc;
689}
690
691/**
692 * Sets an URI list close request to HGCM service parameters.
693 *
694 * @returns VBox status code.
695 * @param cParms Number of HGCM parameters supplied in \a paParms.
696 * @param paParms Array of HGCM parameters.
697 * @param hList Handle of list to close.
698 */
699int VBoxSvcClipboardURISetListClose(uint32_t cParms, VBOXHGCMSVCPARM paParms[],
700 SHAREDCLIPBOARDLISTHANDLE hList)
701{
702 int rc;
703
704 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_CLOSE)
705 {
706 HGCMSvcSetU32(&paParms[0], 0 /* uContextID */);
707 HGCMSvcSetU64(&paParms[1], hList);
708
709 rc = VINF_SUCCESS;
710 }
711 else
712 rc = VERR_INVALID_PARAMETER;
713
714 LogFlowFuncLeaveRC(rc);
715 return rc;
716}
717
718/**
719 * Gets an URI list header from HGCM service parameters.
720 *
721 * @returns VBox status code.
722 * @param cParms Number of HGCM parameters supplied in \a paParms.
723 * @param paParms Array of HGCM parameters.
724 * @param phList Where to store the list handle.
725 * @param pListHdr Where to store the list header.
726 */
727int VBoxSvcClipboardURIGetListHdr(uint32_t cParms, VBOXHGCMSVCPARM paParms[],
728 PSHAREDCLIPBOARDLISTHANDLE phList, PVBOXCLIPBOARDLISTHDR pListHdr)
729{
730 int rc;
731
732 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR)
733 {
734 /* Note: Context ID (paParms[0]) not used yet. */
735 rc = HGCMSvcGetU64(&paParms[1], phList);
736 /* Note: Flags (paParms[2]) not used here. */
737 if (RT_SUCCESS(rc))
738 rc = HGCMSvcGetU32(&paParms[3], &pListHdr->fFeatures);
739 if (RT_SUCCESS(rc))
740 rc = HGCMSvcGetU64(&paParms[4], &pListHdr->cTotalObjects);
741 if (RT_SUCCESS(rc))
742 rc = HGCMSvcGetU64(&paParms[5], &pListHdr->cbTotalSize);
743 if (RT_SUCCESS(rc))
744 rc = HGCMSvcGetU32(&paParms[6], &pListHdr->enmCompression);
745 if (RT_SUCCESS(rc))
746 rc = HGCMSvcGetU32(&paParms[7], (uint32_t *)&pListHdr->enmChecksumType);
747
748 if (RT_SUCCESS(rc))
749 {
750 /** @todo Validate pvMetaFmt + cbMetaFmt. */
751 /** @todo Validate header checksum. */
752 }
753 }
754 else
755 rc = VERR_INVALID_PARAMETER;
756
757 LogFlowFuncLeaveRC(rc);
758 return rc;
759}
760
761/**
762 * Sets an URI list header to HGCM service parameters.
763 *
764 * @returns VBox status code.
765 * @param cParms Number of HGCM parameters supplied in \a paParms.
766 * @param paParms Array of HGCM parameters.
767 * @param pListHdr Pointer to data to set to the HGCM parameters.
768 */
769int VBoxSvcClipboardURISetListHdr(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDLISTHDR pListHdr)
770{
771 int rc;
772
773 if ( cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR
774 || cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR)
775 {
776 /** @todo Set pvMetaFmt + cbMetaFmt. */
777 /** @todo Calculate header checksum. */
778
779 HGCMSvcSetU32(&paParms[0], 0 /* uContextID */);
780 HGCMSvcSetU32(&paParms[1], pListHdr->fFeatures);
781 HGCMSvcSetU32(&paParms[2], 0 /* Features, will be returned on success */);
782 HGCMSvcSetU64(&paParms[3], pListHdr->cTotalObjects);
783 HGCMSvcSetU64(&paParms[4], pListHdr->cbTotalSize);
784 HGCMSvcSetU32(&paParms[5], pListHdr->enmCompression);
785 HGCMSvcSetU32(&paParms[6], pListHdr->enmChecksumType);
786
787 rc = VINF_SUCCESS;
788 }
789 else
790 rc = VERR_INVALID_PARAMETER;
791
792 LogFlowFuncLeaveRC(rc);
793 return rc;
794}
795
796/**
797 * Gets an URI list entry from HGCM service parameters.
798 *
799 * @returns VBox status code.
800 * @param cParms Number of HGCM parameters supplied in \a paParms.
801 * @param paParms Array of HGCM parameters.
802 * @param phList Where to store the list handle.
803 * @param pListEntry Where to store the list entry.
804 */
805int VBoxSvcClipboardURIGetListEntry(uint32_t cParms, VBOXHGCMSVCPARM paParms[],
806 PSHAREDCLIPBOARDLISTHANDLE phList, PVBOXCLIPBOARDLISTENTRY pListEntry)
807{
808 int rc;
809
810 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY)
811 {
812 /* Note: Context ID (paParms[0]) not used yet. */
813 rc = HGCMSvcGetU64(&paParms[1], phList);
814 if (RT_SUCCESS(rc))
815 rc = HGCMSvcGetU32(&paParms[2], &pListEntry->fInfo);
816 if (RT_SUCCESS(rc))
817 rc = HGCMSvcGetPv(&paParms[3], (void **)&pListEntry->pszName, &pListEntry->cbName);
818 if (RT_SUCCESS(rc))
819 {
820 uint32_t cbInfo;
821 rc = HGCMSvcGetU32(&paParms[4], &cbInfo);
822 if (RT_SUCCESS(rc))
823 {
824 rc = HGCMSvcGetPv(&paParms[5], &pListEntry->pvInfo, &pListEntry->cbInfo);
825 AssertReturn(cbInfo == pListEntry->cbInfo, VERR_INVALID_PARAMETER);
826 }
827 }
828
829 if (RT_SUCCESS(rc))
830 {
831 if (!SharedClipboardURIListEntryIsValid(pListEntry))
832 rc = VERR_INVALID_PARAMETER;
833 }
834 }
835 else
836 rc = VERR_INVALID_PARAMETER;
837
838 LogFlowFuncLeaveRC(rc);
839 return rc;
840}
841
842/**
843 * Sets an URI data chunk to HGCM service parameters.
844 *
845 * @returns VBox status code.
846 * @param cParms Number of HGCM parameters supplied in \a paParms.
847 * @param paParms Array of HGCM parameters.
848 * @param pListEntry Pointer to data to set to the HGCM parameters.
849 */
850int VBoxSvcClipboardURISetListEntry(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDLISTENTRY pListEntry)
851{
852 int rc;
853
854 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY)
855 {
856 /** @todo Calculate chunk checksum. */
857
858 HGCMSvcSetU32(&paParms[0], 0 /* uContextID */);
859 HGCMSvcSetU32(&paParms[1], pListEntry->fInfo);
860 HGCMSvcSetU32(&paParms[2], pListEntry->cbInfo);
861 HGCMSvcSetPv (&paParms[3], pListEntry->pvInfo, pListEntry->cbInfo);
862
863 rc = VINF_SUCCESS;
864 }
865 else
866 rc = VERR_INVALID_PARAMETER;
867
868 LogFlowFuncLeaveRC(rc);
869 return rc;
870}
871
872/**
873 * Gets an URI error from HGCM service parameters.
874 *
875 * @returns VBox status code.
876 * @param cParms Number of HGCM parameters supplied in \a paParms.
877 * @param paParms Array of HGCM parameters.
878 * @param pRc Where to store the received error code.
879 */
880int VBoxSvcClipboardURIGetError(uint32_t cParms, VBOXHGCMSVCPARM paParms[], int *pRc)
881{
882 AssertPtrReturn(paParms, VERR_INVALID_PARAMETER);
883 AssertPtrReturn(pRc, VERR_INVALID_PARAMETER);
884
885 int rc;
886
887 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_ERROR)
888 {
889 /* Note: Context ID (paParms[0]) not used yet. */
890 rc = HGCMSvcGetU32(&paParms[1], (uint32_t *)pRc); /** @todo int vs. uint32_t !!! */
891 }
892 else
893 rc = VERR_INVALID_PARAMETER;
894
895 LogFlowFuncLeaveRC(rc);
896 return rc;
897}
898
899/**
900 * Handles a guest reply (VBOX_SHARED_CLIPBOARD_GUEST_FN_REPLY) message.
901 *
902 * @returns VBox status code.
903 * @param pClient Pointer to associated client.
904 * @param pTransfer Pointer to transfer to handle guest reply for.
905 * @param cParms Number of function parameters supplied.
906 * @param paParms Array function parameters supplied.
907 */
908int VBoxSvcClipboardURITransferHandleReply(PVBOXCLIPBOARDCLIENT pClient, PSHAREDCLIPBOARDURITRANSFER pTransfer,
909 uint32_t cParms, VBOXHGCMSVCPARM paParms[])
910{
911 RT_NOREF(pClient);
912
913 int rc;
914
915 uint32_t cbReply = sizeof(VBOXCLIPBOARDREPLY);
916 PVBOXCLIPBOARDREPLY pReply = (PVBOXCLIPBOARDREPLY)RTMemAlloc(cbReply);
917 if (pReply)
918 {
919 rc = VBoxSvcClipboardURIGetReply(cParms, paParms, pReply);
920 if (RT_SUCCESS(rc))
921 {
922 PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload
923 = (PSHAREDCLIPBOARDURITRANSFERPAYLOAD)RTMemAlloc(sizeof(SHAREDCLIPBOARDURITRANSFERPAYLOAD));
924 if (pPayload)
925 {
926 pPayload->pvData = pReply;
927 pPayload->cbData = cbReply;
928
929 switch (pReply->uType)
930 {
931 case VBOX_SHAREDCLIPBOARD_REPLYMSGTYPE_LIST_OPEN:
932 {
933 rc = SharedClipboardURITransferEventSignal(pTransfer,
934 SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_OPEN, pPayload);
935 break;
936 }
937
938 case VBOX_SHAREDCLIPBOARD_REPLYMSGTYPE_LIST_CLOSE:
939 {
940 rc = SharedClipboardURITransferEventSignal(pTransfer,
941 SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_CLOSE, pPayload);
942 break;
943 }
944
945 case VBOX_SHAREDCLIPBOARD_REPLYMSGTYPE_OBJ_OPEN:
946 {
947 rc = SharedClipboardURITransferEventSignal(pTransfer,
948 SHAREDCLIPBOARDURITRANSFEREVENTTYPE_OBJ_OPEN, pPayload);
949 break;
950 }
951
952 case VBOX_SHAREDCLIPBOARD_REPLYMSGTYPE_OBJ_CLOSE:
953 {
954 rc = SharedClipboardURITransferEventSignal(pTransfer,
955 SHAREDCLIPBOARDURITRANSFEREVENTTYPE_OBJ_CLOSE, pPayload);
956 break;
957 }
958
959 default:
960 rc = VERR_NOT_FOUND;
961 break;
962 }
963
964 if (RT_FAILURE(rc))
965 {
966 if (pPayload)
967 RTMemFree(pPayload);
968 }
969 }
970 else
971 rc = VERR_NO_MEMORY;
972 }
973 }
974 else
975 rc = VERR_NO_MEMORY;
976
977 if (RT_FAILURE(rc))
978 {
979 if (pReply)
980 RTMemFree(pReply);
981 }
982
983 LogFlowFuncLeaveRC(rc);
984 return rc;
985}
986
987/**
988 * URI client (guest) handler for the Shared Clipboard host service.
989 *
990 * @returns VBox status code.
991 * @param pClient Pointer to associated client.
992 * @param callHandle The client's call handle of this call.
993 * @param u32Function Function number being called.
994 * @param cParms Number of function parameters supplied.
995 * @param paParms Array function parameters supplied.
996 * @param tsArrival Timestamp of arrival.
997 */
998int vboxSvcClipboardURIHandler(PVBOXCLIPBOARDCLIENT pClient,
999 VBOXHGCMCALLHANDLE callHandle,
1000 uint32_t u32Function,
1001 uint32_t cParms,
1002 VBOXHGCMSVCPARM paParms[],
1003 uint64_t tsArrival)
1004{
1005 RT_NOREF(paParms, tsArrival);
1006
1007 LogFlowFunc(("uClient=%RU32, u32Function=%RU32 (%s), cParms=%RU32, g_pfnExtension=%p\n",
1008 pClient->uClientID, u32Function, VBoxSvcClipboardGuestMsgToStr(u32Function), cParms, g_pfnExtension));
1009
1010 const PVBOXCLIPBOARDCLIENTDATA pClientData = pClient->pData;
1011 AssertPtrReturn(pClientData, VERR_INVALID_POINTER);
1012
1013 /* Check if we've the right mode set. */
1014 if (!vboxSvcClipboardURIMsgIsAllowed(vboxSvcClipboardGetMode(), u32Function))
1015 {
1016 LogFunc(("Wrong clipboard mode, denying access\n"));
1017 return VERR_ACCESS_DENIED;
1018 }
1019
1020 /* A (valid) service extension is needed because VBoxSVC needs to keep track of the
1021 * clipboard areas cached on the host. */
1022 if (!g_pfnExtension)
1023 {
1024#ifdef DEBUG_andy
1025 AssertPtr(g_pfnExtension);
1026#endif
1027 LogFunc(("Invalid / no service extension set, skipping URI handling\n"));
1028 return VERR_NOT_SUPPORTED;
1029 }
1030
1031 int rc = VINF_SUCCESS;
1032
1033 /*
1034 * Pre-check: For certain messages we need to make sure that a (right) transfer is present.
1035 */
1036 PSHAREDCLIPBOARDURITRANSFER pTransfer = NULL;
1037 switch (u32Function)
1038 {
1039 case VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_NOWAIT:
1040 RT_FALL_THROUGH();
1041 case VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_WAIT:
1042 RT_FALL_THROUGH();
1043 case VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_GET:
1044 RT_FALL_THROUGH();
1045 case VBOX_SHARED_CLIPBOARD_GUEST_FN_STATUS:
1046 break;
1047 default:
1048 {
1049 if (!SharedClipboardURICtxGetTotalTransfers(&pClientData->URI))
1050 {
1051 LogFunc(("No transfers found\n"));
1052 rc = VERR_WRONG_ORDER;
1053 break;
1054 }
1055
1056 const uint32_t uTransferID = 0; /* Only one transfer per client is supported at the moment. */
1057
1058 pTransfer = SharedClipboardURICtxGetTransfer(&pClientData->URI, uTransferID);
1059 if (!pTransfer)
1060 {
1061 LogFunc(("Transfer with ID %RU32 not found\n", uTransferID));
1062 rc = VERR_WRONG_ORDER;
1063 }
1064 break;
1065 }
1066 }
1067
1068 if (RT_FAILURE(rc))
1069 return rc;
1070
1071 rc = VERR_INVALID_PARAMETER; /* Play safe. */
1072
1073 switch (u32Function)
1074 {
1075 case VBOX_SHARED_CLIPBOARD_GUEST_FN_STATUS:
1076 {
1077 LogFlowFunc(("[Client %RU32] VBOX_SHARED_CLIPBOARD_GUEST_FN_STATUS\n", pClient->uClientID));
1078
1079 if (cParms != VBOX_SHARED_CLIPBOARD_CPARMS_STATUS)
1080 break;
1081
1082 SHAREDCLIPBOARDURITRANSFERSTATUS uStatus = SHAREDCLIPBOARDURITRANSFERSTATUS_NONE;
1083 rc = HGCMSvcGetU32(&paParms[1], &uStatus);
1084 if (RT_FAILURE(rc))
1085 break;
1086
1087 LogFlowFunc(("uStatus: %RU32\n", uStatus));
1088
1089 if ( uStatus == SHAREDCLIPBOARDURITRANSFERSTATUS_RUNNING
1090 && !SharedClipboardURICtxTransfersMaximumReached(&pClientData->URI))
1091 {
1092 SharedClipboardURICtxTransfersCleanup(&pClientData->URI);
1093
1094 SHAREDCLIPBOARDURITRANSFERDIR enmDir = SHAREDCLIPBOARDURITRANSFERDIR_READ;
1095
1096 PSHAREDCLIPBOARDURITRANSFER pTransfer;
1097 rc = SharedClipboardURITransferCreate(enmDir,
1098 SHAREDCLIPBOARDSOURCE_REMOTE, &pTransfer);
1099 if (RT_SUCCESS(rc))
1100 {
1101 rc = vboxSvcClipboardURIAreaRegister(&pClientData->State, pTransfer);
1102 if (RT_SUCCESS(rc))
1103 {
1104 SHAREDCLIPBOARDPROVIDERCREATIONCTX creationCtx;
1105 RT_ZERO(creationCtx);
1106
1107 creationCtx.enmSource = pClientData->State.enmSource;
1108
1109 RT_ZERO(creationCtx.Interface);
1110 creationCtx.Interface.pfnTransferOpen = vboxSvcClipboardURITransferOpen;
1111 creationCtx.Interface.pfnTransferClose = vboxSvcClipboardURITransferClose;
1112 creationCtx.Interface.pfnListOpen = vboxSvcClipboardURIListOpen;
1113 creationCtx.Interface.pfnListClose = vboxSvcClipboardURIListClose;
1114 creationCtx.Interface.pfnObjOpen = vboxSvcClipboardURIObjOpen;
1115 creationCtx.Interface.pfnObjClose = vboxSvcClipboardURIObjClose;
1116
1117 if (enmDir == SHAREDCLIPBOARDURITRANSFERDIR_READ)
1118 {
1119 creationCtx.Interface.pfnGetRoots = vboxSvcClipboardURIGetRoots;
1120 creationCtx.Interface.pfnListHdrRead = vboxSvcClipboardURIListHdrRead;
1121 creationCtx.Interface.pfnListEntryRead = vboxSvcClipboardURIListEntryRead;
1122 creationCtx.Interface.pfnObjRead = vboxSvcClipboardURIObjRead;
1123 }
1124 else
1125 {
1126 AssertFailed();
1127 }
1128
1129 creationCtx.pvUser = pClient;
1130
1131 /* Register needed callbacks so that we can wait for the meta data to arrive here. */
1132 SHAREDCLIPBOARDURITRANSFERCALLBACKS Callbacks;
1133 RT_ZERO(Callbacks);
1134
1135 Callbacks.pvUser = pClientData;
1136
1137 Callbacks.pfnTransferPrepare = VBoxSvcClipboardURITransferPrepareCallback;
1138 Callbacks.pfnTransferComplete = VBoxSvcClipboardURITransferCompleteCallback;
1139 Callbacks.pfnTransferCanceled = VBoxSvcClipboardURITransferCanceledCallback;
1140 Callbacks.pfnTransferError = VBoxSvcClipboardURITransferErrorCallback;
1141
1142 SharedClipboardURITransferSetCallbacks(pTransfer, &Callbacks);
1143
1144 rc = SharedClipboardURITransferSetInterface(pTransfer, &creationCtx);
1145 if (RT_SUCCESS(rc))
1146 rc = SharedClipboardURICtxTransferAdd(&pClientData->URI, pTransfer);
1147 }
1148
1149 if (RT_SUCCESS(rc))
1150 {
1151 rc = VBoxClipboardSvcImplURITransferCreate(pClientData, pTransfer);
1152 if (RT_SUCCESS(rc))
1153 rc = VBoxClipboardSvcImplFormatAnnounce(pClientData, VBOX_SHARED_CLIPBOARD_FMT_URI_LIST);
1154 }
1155
1156 if (RT_FAILURE(rc))
1157 {
1158 VBoxClipboardSvcImplURITransferDestroy(pClientData, pTransfer);
1159 SharedClipboardURITransferDestroy(pTransfer);
1160 }
1161 }
1162 }
1163 else
1164 rc = VERR_SHCLPB_MAX_TRANSFERS_REACHED;
1165
1166 LogFlowFunc(("[Client %RU32] VBOX_SHARED_CLIPBOARD_GUEST_FN_STATUS: %Rrc\n", pClient->uClientID, rc));
1167
1168 if (RT_FAILURE(rc))
1169 LogRel(("Shared Clipboard: Initializing transfer failed with %Rrc\n", rc));
1170
1171 break;
1172 }
1173
1174 case VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_NOWAIT:
1175 {
1176 rc = vboxSvcClipboardMsgPeek(pClient, callHandle, cParms, paParms, false /*fWait*/);
1177 break;
1178 }
1179
1180 case VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_WAIT:
1181 {
1182 rc = vboxSvcClipboardMsgPeek(pClient, callHandle, cParms, paParms, true /*fWait*/);
1183 break;
1184 }
1185
1186 case VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_GET:
1187 {
1188 rc = vboxSvcClipboardMsgGet(pClient, callHandle, cParms, paParms);
1189 break;
1190 }
1191
1192 case VBOX_SHARED_CLIPBOARD_GUEST_FN_REPLY:
1193 {
1194 rc = VBoxSvcClipboardURITransferHandleReply(pClient, pTransfer, cParms, paParms);
1195 break;
1196 }
1197
1198 case VBOX_SHARED_CLIPBOARD_GUEST_FN_ROOTS:
1199 {
1200 VBOXCLIPBOARDROOTS Roots;
1201 rc = VBoxSvcClipboardURIGetRoots(cParms, paParms, &Roots);
1202 if (RT_SUCCESS(rc))
1203 {
1204 void *pvData = SharedClipboardURIRootsDup(&Roots);
1205 uint32_t cbData = sizeof(VBOXCLIPBOARDROOTS);
1206
1207 PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
1208 rc = SharedClipboardURITransferPayloadAlloc(SHAREDCLIPBOARDURITRANSFEREVENTTYPE_GET_ROOTS,
1209 pvData, cbData, &pPayload);
1210 if (RT_SUCCESS(rc))
1211 rc = SharedClipboardURITransferEventSignal(pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_GET_ROOTS,
1212 pPayload);
1213 }
1214 break;
1215 }
1216
1217 case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_OPEN:
1218 {
1219 VBOXCLIPBOARDLISTOPENPARMS listOpenParms;
1220 rc = VBoxSvcClipboardURIGetListOpen(cParms, paParms, &listOpenParms);
1221 if (RT_SUCCESS(rc))
1222 {
1223 SHAREDCLIPBOARDLISTHANDLE hList;
1224 rc = SharedClipboardURITransferListOpen(pTransfer, &listOpenParms, &hList);
1225 if (RT_SUCCESS(rc))
1226 {
1227 /* Return list handle. */
1228 HGCMSvcSetU32(&paParms[1], hList);
1229 }
1230 }
1231 break;
1232 }
1233
1234 case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_CLOSE:
1235 {
1236 if (cParms != VBOX_SHARED_CLIPBOARD_CPARMS_LIST_CLOSE)
1237 break;
1238
1239 SHAREDCLIPBOARDLISTHANDLE hList;
1240 /* Note: Context ID (paParms[0]) not used yet. */
1241 rc = HGCMSvcGetU64(&paParms[1], &hList);
1242 if (RT_SUCCESS(rc))
1243 {
1244 rc = SharedClipboardURITransferListClose(pTransfer, hList);
1245 }
1246 break;
1247 }
1248
1249 case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_READ:
1250 {
1251 if (cParms != VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR)
1252 break;
1253
1254 SHAREDCLIPBOARDLISTHANDLE hList;
1255 /* Note: Context ID (paParms[0]) not used yet. */
1256 rc = HGCMSvcGetU64(&paParms[1], &hList); /* Get list handle. */
1257 if (RT_SUCCESS(rc))
1258 {
1259 VBOXCLIPBOARDLISTHDR hdrList;
1260 rc = SharedClipboardURITransferListGetHeader(pTransfer, hList, &hdrList);
1261 if (RT_SUCCESS(rc))
1262 rc = VBoxSvcClipboardURISetListHdr(cParms, paParms, &hdrList);
1263 }
1264 break;
1265 }
1266
1267 case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_WRITE:
1268 {
1269 VBOXCLIPBOARDLISTHDR hdrList;
1270 rc = SharedClipboardURIListHdrInit(&hdrList);
1271 if (RT_SUCCESS(rc))
1272 {
1273 SHAREDCLIPBOARDLISTHANDLE hList;
1274 rc = VBoxSvcClipboardURIGetListHdr(cParms, paParms, &hList, &hdrList);
1275 if (RT_SUCCESS(rc))
1276 {
1277 void *pvData = SharedClipboardURIListHdrDup(&hdrList);
1278 uint32_t cbData = sizeof(VBOXCLIPBOARDLISTHDR);
1279
1280 PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
1281 rc = SharedClipboardURITransferPayloadAlloc(SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_HDR_WRITE,
1282 pvData, cbData, &pPayload);
1283 if (RT_SUCCESS(rc))
1284 {
1285 rc = SharedClipboardURITransferEventSignal(pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_HDR_WRITE,
1286 pPayload);
1287 }
1288 }
1289 }
1290 break;
1291 }
1292
1293 case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_ENTRY_READ:
1294 {
1295 if (cParms != VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY)
1296 break;
1297
1298 SHAREDCLIPBOARDLISTHANDLE hList;
1299 /* Note: Context ID (paParms[0]) not used yet. */
1300 rc = HGCMSvcGetU64(&paParms[1], &hList); /* Get list handle. */
1301 if (RT_SUCCESS(rc))
1302 {
1303 VBOXCLIPBOARDLISTENTRY entryList;
1304 rc = SharedClipboardURITransferListRead(pTransfer, hList, &entryList);
1305 }
1306 break;
1307 }
1308
1309 case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_ENTRY_WRITE:
1310 {
1311 VBOXCLIPBOARDLISTENTRY entryList;
1312 rc = SharedClipboardURIListEntryInit(&entryList);
1313 if (RT_SUCCESS(rc))
1314 {
1315 SHAREDCLIPBOARDLISTHANDLE hList;
1316 rc = VBoxSvcClipboardURIGetListEntry(cParms, paParms, &hList, &entryList);
1317 if (RT_SUCCESS(rc))
1318 {
1319 void *pvData = SharedClipboardURIListEntryDup(&entryList);
1320 uint32_t cbData = sizeof(VBOXCLIPBOARDLISTENTRY);
1321
1322 PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
1323 rc = SharedClipboardURITransferPayloadAlloc(SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_ENTRY_WRITE,
1324 pvData, cbData, &pPayload);
1325 if (RT_SUCCESS(rc))
1326 {
1327 rc = SharedClipboardURITransferEventSignal(pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_ENTRY_WRITE,
1328 pPayload);
1329 }
1330
1331 }
1332 }
1333 break;
1334 }
1335
1336 #if 0
1337 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DIR:
1338 {
1339 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DIR\n"));
1340
1341 VBOXCLIPBOARDDIRDATA dirData;
1342 rc = VBoxSvcClipboardURIGetDir(cParms, paParms, &dirData);
1343 if (RT_SUCCESS(rc))
1344 {
1345 SharedClipboardArea *pArea = SharedClipboardURITransferGetArea(pTransfer);
1346 AssertPtrBreakStmt(pArea, rc = VERR_INVALID_POINTER);
1347
1348 const char *pszCacheDir = pArea->GetDirAbs();
1349 char *pszDir = RTPathJoinA(pszCacheDir, dirData.pszPath);
1350 if (pszDir)
1351 {
1352 LogFlowFunc(("pszDir=%s\n", pszDir));
1353
1354 rc = RTDirCreateFullPath(pszDir, dirData.fMode);
1355 if (RT_SUCCESS(rc))
1356 {
1357 SHAREDCLIPBOARDAREAOBJ Obj = { SHAREDCLIPBOARDAREAOBJTYPE_DIR, SHAREDCLIPBOARDAREAOBJSTATE_COMPLETE };
1358 int rc2 = pArea->AddObject(pszDir, Obj);
1359 AssertRC(rc2);
1360 }
1361
1362 RTStrFree(pszDir);
1363 }
1364 else
1365 rc = VERR_NO_MEMORY;
1366 }
1367 break;
1368 }
1369
1370 case VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_FILE_HDR:
1371 {
1372 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_FILE_HDR\n"));
1373
1374 VBOXCLIPBOARDFILEHDR fileHdr;
1375 rc = VBoxSvcClipboardURISetFileHdr(cParms, paParms, &fileHdr);
1376 break;
1377 }
1378
1379 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_FILE_HDR:
1380 {
1381 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_FILE_HDR\n"));
1382
1383 if (!SharedClipboardURIObjCtxIsValid(SharedClipboardURITransferGetCurrentObjCtx(pTransfer)))
1384 {
1385 pTransfer->State.ObjCtx.pObj = new SharedClipboardURIObject(SharedClipboardURIObject::Type_File);
1386 if (pTransfer->State.ObjCtx.pObj) /** @todo Can this throw? */
1387 {
1388 rc = VINF_SUCCESS;
1389 }
1390 else
1391 rc = VERR_NO_MEMORY;
1392 }
1393 else /* There still is another object being processed? */
1394 rc = VERR_WRONG_ORDER;
1395
1396 if (RT_FAILURE(rc))
1397 break;
1398
1399 VBOXCLIPBOARDFILEHDR fileHdr;
1400 rc = VBoxSvcClipboardURIGetFileHdr(cParms, paParms, &fileHdr);
1401 if (RT_SUCCESS(rc))
1402 {
1403 SharedClipboardArea *pArea = SharedClipboardURITransferGetArea(pTransfer);
1404 AssertPtrBreakStmt(pArea, rc = VERR_WRONG_ORDER);
1405
1406 const char *pszCacheDir = pArea->GetDirAbs();
1407
1408 char pszPathAbs[RTPATH_MAX];
1409 rc = RTPathJoin(pszPathAbs, sizeof(pszPathAbs), pszCacheDir, fileHdr.pszFilePath);
1410 if (RT_SUCCESS(rc))
1411 {
1412 rc = SharedClipboardPathSanitize(pszPathAbs, sizeof(pszPathAbs));
1413 if (RT_SUCCESS(rc))
1414 {
1415 PSHAREDCLIPBOARDCLIENTURIOBJCTX pObjCtx = SharedClipboardURITransferGetCurrentObjCtx(pTransfer);
1416 AssertPtrBreakStmt(pObjCtx, VERR_INVALID_POINTER);
1417
1418 SharedClipboardURIObject *pObj = pObjCtx->pObj;
1419 AssertPtrBreakStmt(pObj, VERR_INVALID_POINTER);
1420
1421 LogFlowFunc(("pszFile=%s\n", pszPathAbs));
1422
1423 /** @todo Add sparse file support based on fFlags? (Use Open(..., fFlags | SPARSE). */
1424 rc = pObj->OpenFileEx(pszPathAbs, SharedClipboardURIObject::View_Target,
1425 RTFILE_O_CREATE_REPLACE | RTFILE_O_WRITE | RTFILE_O_DENY_WRITE,
1426 (fileHdr.fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR);
1427 if (RT_SUCCESS(rc))
1428 {
1429 rc = pObj->SetSize(fileHdr.cbSize);
1430
1431 /** @todo Unescape path before printing. */
1432 LogRel2(("Clipboard: Transferring guest file '%s' to host (%RU64 bytes, mode 0x%x)\n",
1433 pObj->GetDestPathAbs().c_str(), pObj->GetSize(), pObj->GetMode()));
1434
1435 if (pObj->IsComplete()) /* 0-byte file? We're done already. */
1436 {
1437 /** @todo Sanitize path. */
1438 LogRel2(("Clipboard: Transferring guest file '%s' (0 bytes) to host complete\n",
1439 pObj->GetDestPathAbs().c_str()));
1440
1441 SharedClipboardURIObjCtxDestroy(&pTransfer->State.ObjCtx);
1442 }
1443
1444 SHAREDCLIPBOARDAREAOBJ Obj = { SHAREDCLIPBOARDAREAOBJTYPE_FILE, SHAREDCLIPBOARDAREAOBJSTATE_NONE };
1445 int rc2 = pArea->AddObject(pszPathAbs, Obj);
1446 AssertRC(rc2);
1447 }
1448 else
1449 LogRel(("Clipboard: Error opening/creating guest file '%s' on host, rc=%Rrc\n", pszPathAbs, rc));
1450 }
1451 }
1452 }
1453 break;
1454 }
1455
1456 case VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_FILE_DATA:
1457 {
1458 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_READ_FILE_DATA\n"));
1459
1460 VBOXCLIPBOARDFILEDATA fileData;
1461 rc = VBoxSvcClipboardURISetFileData(cParms, paParms, &fileData);
1462 break;
1463 }
1464
1465 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_FILE_DATA:
1466 {
1467 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_FILE_DATA\n"));
1468
1469 if (!SharedClipboardURIObjCtxIsValid(&pTransfer->State.ObjCtx))
1470 {
1471 rc = VERR_WRONG_ORDER;
1472 break;
1473 }
1474
1475 VBOXCLIPBOARDFILEDATA fileData;
1476 rc = VBoxSvcClipboardURIGetFileData(cParms, paParms, &fileData);
1477 if (RT_SUCCESS(rc))
1478 {
1479 PSHAREDCLIPBOARDCLIENTURIOBJCTX pObjCtx = SharedClipboardURITransferGetCurrentObjCtx(pTransfer);
1480 AssertPtrBreakStmt(pObjCtx, VERR_INVALID_POINTER);
1481
1482 SharedClipboardURIObject *pObj = pObjCtx->pObj;
1483 AssertPtrBreakStmt(pObj, VERR_INVALID_POINTER);
1484
1485 uint32_t cbWritten;
1486 rc = pObj->Write(fileData.pvData, fileData.cbData, &cbWritten);
1487 if (RT_SUCCESS(rc))
1488 {
1489 Assert(cbWritten <= fileData.cbData);
1490 if (cbWritten < fileData.cbData)
1491 {
1492 /** @todo What to do when the host's disk is full? */
1493 rc = VERR_DISK_FULL;
1494 }
1495
1496 if ( pObj->IsComplete()
1497 || RT_FAILURE(rc))
1498 SharedClipboardURIObjCtxDestroy(&pTransfer->State.ObjCtx);
1499 }
1500 else
1501 LogRel(("Clipboard: Error writing guest file data for '%s', rc=%Rrc\n", pObj->GetDestPathAbs().c_str(), rc));
1502 }
1503 break;
1504 }
1505#endif
1506 case VBOX_SHARED_CLIPBOARD_GUEST_FN_CANCEL:
1507 {
1508 LogRel2(("Shared Clipboard: Transfer canceled\n"));
1509 break;
1510 }
1511
1512 case VBOX_SHARED_CLIPBOARD_GUEST_FN_ERROR:
1513 {
1514 int rcGuest;
1515 rc = VBoxSvcClipboardURIGetError(cParms,paParms, &rcGuest);
1516 if (RT_SUCCESS(rc))
1517 LogRel(("Shared Clipboard: Transfer error: %Rrc\n", rcGuest));
1518 break;
1519 }
1520
1521 default:
1522 LogFunc(("Not implemented\n"));
1523 break;
1524 }
1525
1526 if (rc != VINF_HGCM_ASYNC_EXECUTE)
1527 {
1528 /* Tell the client that the call is complete (unblocks waiting). */
1529 LogFlowFunc(("[Client %RU32] Calling pfnCallComplete w/ rc=%Rrc\n", pClient->uClientID, rc));
1530 AssertPtr(g_pHelpers);
1531 g_pHelpers->pfnCallComplete(callHandle, rc);
1532 }
1533
1534 LogFlowFunc(("[Client %RU32] Returning rc=%Rrc\n", pClient->uClientID, rc));
1535 return rc;
1536}
1537
1538/**
1539 * URI host handler for the Shared Clipboard host service.
1540 *
1541 * @returns VBox status code.
1542 * @param u32Function Function number being called.
1543 * @param cParms Number of function parameters supplied.
1544 * @param paParms Array function parameters supplied.
1545 */
1546int vboxSvcClipboardURIHostHandler(uint32_t u32Function,
1547 uint32_t cParms,
1548 VBOXHGCMSVCPARM paParms[])
1549{
1550 RT_NOREF(cParms, paParms);
1551
1552 int rc = VERR_NOT_IMPLEMENTED; /* Play safe. */
1553
1554 switch (u32Function)
1555 {
1556 case VBOX_SHARED_CLIPBOARD_HOST_FN_CANCEL:
1557 /** @todo */
1558 break;
1559
1560 case VBOX_SHARED_CLIPBOARD_HOST_FN_ERROR:
1561 /** @todo */
1562 break;
1563
1564 default:
1565 break;
1566
1567 }
1568
1569 LogFlowFuncLeaveRC(rc);
1570 return rc;
1571}
1572
1573/**
1574 * Registers an URI clipboard area.
1575 *
1576 * @returns VBox status code.
1577 * @param pClientState Client state to use.
1578 * @param pTransfer URI transfer to register a clipboard area for.
1579 */
1580int vboxSvcClipboardURIAreaRegister(PVBOXCLIPBOARDCLIENTSTATE pClientState, PSHAREDCLIPBOARDURITRANSFER pTransfer)
1581{
1582 LogFlowFuncEnter();
1583
1584 AssertMsgReturn(pTransfer->pArea == NULL, ("An area already is registered for this transfer\n"),
1585 VERR_WRONG_ORDER);
1586
1587 pTransfer->pArea = new SharedClipboardArea();
1588 if (!pTransfer->pArea)
1589 return VERR_NO_MEMORY;
1590
1591 int rc;
1592
1593 if (g_pfnExtension)
1594 {
1595 VBOXCLIPBOARDEXTAREAPARMS parms;
1596 RT_ZERO(parms);
1597
1598 parms.uID = NIL_SHAREDCLIPBOARDAREAID;
1599
1600 /* As the meta data is now complete, register a new clipboard on the host side. */
1601 rc = g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_AREA_REGISTER, &parms, sizeof(parms));
1602 if (RT_SUCCESS(rc))
1603 {
1604 /* Note: Do *not* specify SHAREDCLIPBOARDAREA_OPEN_FLAGS_MUST_NOT_EXIST as flags here, as VBoxSVC took care of the
1605 * clipboard area creation already. */
1606 rc = pTransfer->pArea->OpenTemp(parms.uID /* Area ID */,
1607 SHAREDCLIPBOARDAREA_OPEN_FLAGS_NONE);
1608 }
1609
1610 LogFlowFunc(("Registered new clipboard area (%RU32) by client %RU32 with rc=%Rrc\n",
1611 parms.uID, pClientState->u32ClientID, rc));
1612 }
1613 else
1614 rc = VERR_NOT_SUPPORTED;
1615
1616 LogFlowFuncLeaveRC(rc);
1617 return rc;
1618}
1619
1620/**
1621 * Unregisters an URI clipboard area.
1622 *
1623 * @returns VBox status code.
1624 * @param pClientState Client state to use.
1625 * @param pTransfer URI transfer to unregister a clipboard area from.
1626 */
1627int vboxSvcClipboardURIAreaUnregister(PVBOXCLIPBOARDCLIENTSTATE pClientState, PSHAREDCLIPBOARDURITRANSFER pTransfer)
1628{
1629 LogFlowFuncEnter();
1630
1631 if (!pTransfer->pArea)
1632 return VINF_SUCCESS;
1633
1634 int rc = VINF_SUCCESS;
1635
1636 if (g_pfnExtension)
1637 {
1638 VBOXCLIPBOARDEXTAREAPARMS parms;
1639 RT_ZERO(parms);
1640
1641 parms.uID = pTransfer->pArea->GetID();
1642
1643 rc = g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_AREA_UNREGISTER, &parms, sizeof(parms));
1644 if (RT_SUCCESS(rc))
1645 {
1646 rc = pTransfer->pArea->Close();
1647 if (RT_SUCCESS(rc))
1648 {
1649 delete pTransfer->pArea;
1650 pTransfer->pArea = NULL;
1651 }
1652 }
1653
1654 LogFlowFunc(("Unregistered clipboard area (%RU32) by client %RU32 with rc=%Rrc\n",
1655 parms.uID, pClientState->u32ClientID, rc));
1656 }
1657
1658 delete pTransfer->pArea;
1659 pTransfer->pArea = NULL;
1660
1661 LogFlowFuncLeaveRC(rc);
1662 return rc;
1663}
1664
1665/**
1666 * Attaches to an existing (registered) URI clipboard area.
1667 *
1668 * @returns VBox status code.
1669 * @param pClientState Client state to use.
1670 * @param pTransfer URI transfer to attach a clipboard area to.
1671 * @param uID ID of clipboard area to to attach to. Specify 0 to attach to the most recent one.
1672 */
1673int vboxSvcClipboardURIAreaAttach(PVBOXCLIPBOARDCLIENTSTATE pClientState, PSHAREDCLIPBOARDURITRANSFER pTransfer,
1674 SHAREDCLIPBOARDAREAID uID)
1675{
1676 LogFlowFuncEnter();
1677
1678 AssertMsgReturn(pTransfer->pArea == NULL, ("An area already is attached to this transfer\n"),
1679 VERR_WRONG_ORDER);
1680
1681 pTransfer->pArea = new SharedClipboardArea();
1682 if (!pTransfer->pArea)
1683 return VERR_NO_MEMORY;
1684
1685 int rc = VINF_SUCCESS;
1686
1687 if (g_pfnExtension)
1688 {
1689 VBOXCLIPBOARDEXTAREAPARMS parms;
1690 RT_ZERO(parms);
1691
1692 parms.uID = uID; /* 0 means most recent clipboard area. */
1693
1694 /* The client now needs to attach to the most recent clipboard area
1695 * to keep a reference to it. The host does the actual book keeping / cleanup then.
1696 *
1697 * This might fail if the host does not have a most recent clipboard area (yet). */
1698 rc = g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_AREA_ATTACH, &parms, sizeof(parms));
1699 if (RT_SUCCESS(rc))
1700 rc = pTransfer->pArea->OpenTemp(parms.uID /* Area ID */);
1701
1702 LogFlowFunc(("Attached client %RU32 to clipboard area %RU32 with rc=%Rrc\n",
1703 pClientState->u32ClientID, parms.uID, rc));
1704 }
1705 else
1706 rc = VERR_NOT_SUPPORTED;
1707
1708 LogFlowFuncLeaveRC(rc);
1709 return rc;
1710}
1711
1712/**
1713 * Detaches from an URI clipboard area.
1714 *
1715 * @returns VBox status code.
1716 * @param pClientState Client state to use.
1717 * @param pTransfer URI transfer to detach a clipboard area from.
1718 */
1719int vboxSvcClipboardURIAreaDetach(PVBOXCLIPBOARDCLIENTSTATE pClientState, PSHAREDCLIPBOARDURITRANSFER pTransfer)
1720{
1721 LogFlowFuncEnter();
1722
1723 if (!pTransfer->pArea)
1724 return VINF_SUCCESS;
1725
1726 const uint32_t uAreaID = pTransfer->pArea->GetID();
1727
1728 int rc = VINF_SUCCESS;
1729
1730 if (g_pfnExtension)
1731 {
1732 VBOXCLIPBOARDEXTAREAPARMS parms;
1733 RT_ZERO(parms);
1734 parms.uID = uAreaID;
1735
1736 rc = g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_AREA_DETACH, &parms, sizeof(parms));
1737
1738 LogFlowFunc(("Detached client %RU32 from clipboard area %RU32 with rc=%Rrc\n",
1739 pClientState->u32ClientID, uAreaID, rc));
1740 }
1741
1742 delete pTransfer->pArea;
1743 pTransfer->pArea = NULL;
1744
1745 LogFlowFuncLeaveRC(rc);
1746 return rc;
1747}
1748
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