VirtualBox

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

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

Shared Clipboard/URI: Update.

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