VirtualBox

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

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

Shared Clipboard: Renaming (SHAREDCLIPBOARD -> SHCL and VBOXCLIPBOARD -> SHCL).

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