VirtualBox

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

Last change on this file since 80283 was 80283, checked in by vboxsync, 5 years ago

Shared Clipboard/URI: Update; more work on root list handling.

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

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