VirtualBox

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

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

Shared Clipboard/URI: More work on context IDs and entry list handling.

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