VirtualBox

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

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

Shared Clipboard/URI: More code for root entries handling.

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