VirtualBox

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

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

Shared Clipboard/URI: Update.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 26.7 KB
Line 
1/* $Id: VBoxSharedClipboardSvc-uri.cpp 79107 2019-06-12 13:57:04Z vboxsync $ */
2/** @file
3 * Shared Clipboard Service - Internal code for URI (list) handling.
4 */
5
6/*
7 * Copyright (C) 2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_SHARED_CLIPBOARD
23#include <VBox/log.h>
24
25#include <VBox/err.h>
26
27#include <VBox/HostServices/VBoxClipboardSvc.h>
28#include <VBox/HostServices/VBoxClipboardExt.h>
29
30#include <iprt/dir.h>
31#include <iprt/file.h>
32#include <iprt/path.h>
33
34#include "VBoxSharedClipboardSvc-internal.h"
35#include "VBoxSharedClipboardSvc-uri.h"
36
37
38/*********************************************************************************************************************************
39* Externals *
40*********************************************************************************************************************************/
41extern PFNHGCMSVCEXT g_pfnExtension;
42extern void *g_pvExtension;
43
44
45/**
46 * Destroys a VBOXCLIPBOARDDIRDATA structure.
47 *
48 * @param pDirData VBOXCLIPBOARDDIRDATA structure to destroy.
49 */
50void vboxSvcClipboardURIDirDataDestroy(PVBOXCLIPBOARDDIRDATA pDirData)
51{
52 if (!pDirData)
53 return;
54
55 if (pDirData->pszPath)
56 {
57 Assert(pDirData->cbPath);
58 RTStrFree(pDirData->pszPath);
59 pDirData->pszPath = NULL;
60 }
61}
62
63/**
64 * Destroys a VBOXCLIPBOARDFILEHDR structure.
65 *
66 * @param pFileHdr VBOXCLIPBOARDFILEHDR structure to destroy.
67 */
68void vboxSvcClipboardURIFileHdrDestroy(PVBOXCLIPBOARDFILEHDR pFileHdr)
69{
70 if (!pFileHdr)
71 return;
72
73 if (pFileHdr->pszFilePath)
74 {
75 Assert(pFileHdr->pszFilePath);
76 RTStrFree(pFileHdr->pszFilePath);
77 pFileHdr->pszFilePath = NULL;
78 }
79}
80
81/**
82 * Destroys a VBOXCLIPBOARDFILEDATA structure.
83 *
84 * @param pFileData VBOXCLIPBOARDFILEDATA structure to destroy.
85 */
86void vboxSvcClipboardURIFileDataDestroy(PVBOXCLIPBOARDFILEDATA pFileData)
87{
88 if (!pFileData)
89 return;
90
91 if (pFileData->pvData)
92 {
93 Assert(pFileData->cbData);
94 RTMemFree(pFileData->pvData);
95 pFileData->pvData = NULL;
96 }
97}
98
99/**
100 * URI client (guest) handler for the Shared Clipboard host service.
101 *
102 * @returns VBox status code.
103 * @param u32ClientID Client ID of the client which called this handler.
104 * @param pvClient Pointer to client-specific data block.
105 * @param u32Function Function number being called.
106 * @param cParms Number of function parameters supplied.
107 * @param paParms Array function parameters supplied.
108 * @param tsArrival Timestamp of arrival.
109 * @param pfAsync Returns \c true if the response needs to be being asynchronous or \c false if not,
110 */
111int vboxSvcClipboardURIHandler(uint32_t u32ClientID,
112 void *pvClient,
113 uint32_t u32Function,
114 uint32_t cParms,
115 VBOXHGCMSVCPARM paParms[],
116 uint64_t tsArrival,
117 bool *pfAsync)
118{
119 RT_NOREF(u32ClientID, paParms, tsArrival, pfAsync);
120
121 LogFlowFunc(("u32ClientID=%RU32, u32Function=%RU32, cParms=%RU32, g_pfnExtension=%p\n",
122 u32ClientID, u32Function, cParms, g_pfnExtension));
123
124 const PVBOXCLIPBOARDCLIENTDATA pClientData = (PVBOXCLIPBOARDCLIENTDATA)pvClient;
125 AssertPtrReturn(pClientData, VERR_INVALID_POINTER);
126
127 /* Check if we've the right mode set. */
128 int rc = VERR_ACCESS_DENIED; /* Play safe. */
129
130 if (!vboxSvcClipboardURIMsgIsAllowed(vboxSvcClipboardGetMode(), u32Function))
131 return rc;
132
133 /* A (valid) service extension is needed because VBoxSVC needs to keep track of the
134 * clipboard areas cached on the host. */
135 if (!g_pfnExtension)
136 {
137#ifdef DEBUG_andy
138 AssertPtr(g_pfnExtension);
139#endif
140 LogFunc(("Invalid / no service extension set, skipping URI handling\n"));
141 rc = VERR_NOT_SUPPORTED;
142 }
143
144 if (RT_FAILURE(rc))
145 return rc;
146
147 const PSHAREDCLIPBOARDURITRANSFER pTransfer = SharedClipboardURICtxGetTransfer(&pClientData->URI, 0 /* Index */);
148
149 rc = VERR_INVALID_PARAMETER; /* Play safe. */
150
151 switch (u32Function)
152 {
153 case VBOX_SHARED_CLIPBOARD_FN_READ_DATA_HDR:
154 {
155 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_READ_DATA_HDR\n"));
156 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_READ_DATA_HDR)
157 {
158 bool fDetach = false;
159
160 if (RT_SUCCESS(rc))
161 {
162 // pTransfer->Area. parms.uID
163
164 /** @todo Detach if header / meta size is 0. */
165 }
166
167 /* Do we need to detach again because we're done? */
168 if (fDetach)
169 vboxSvcClipboardURIAreaDetach(&pClientData->State, pTransfer);
170 }
171 break;
172 }
173
174 case VBOX_SHARED_CLIPBOARD_FN_WRITE_DATA_HDR:
175 {
176 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_DATA_HDR\n"));
177 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_DATA_HDR)
178 {
179 if (SharedClipboardURICtxMaximumTransfersReached(&pClientData->URI))
180 {
181 rc = VERR_SHCLPB_MAX_TRANSFERS_REACHED;
182 break;
183 }
184
185 RT_ZERO(pTransfer->Header);
186 /* Note: Context ID (paParms[0]) not used yet. */
187 rc = HGCMSvcGetU32(&paParms[1], &pTransfer->Header.uFlags);
188 if (RT_SUCCESS(rc))
189 rc = HGCMSvcGetU32(&paParms[2], &pTransfer->Header.uScreenId);
190 if (RT_SUCCESS(rc))
191 rc = HGCMSvcGetU64(&paParms[3], &pTransfer->Header.cbTotal);
192 if (RT_SUCCESS(rc))
193 rc = HGCMSvcGetU32(&paParms[4], &pTransfer->Header.cbMeta);
194 if (RT_SUCCESS(rc))
195 rc = HGCMSvcGetPv(&paParms[5], &pTransfer->Header.pvMetaFmt, &pTransfer->Header.cbMetaFmt);
196 if (RT_SUCCESS(rc))
197 rc = HGCMSvcGetU32(&paParms[6], &pTransfer->Header.cbMetaFmt);
198 if (RT_SUCCESS(rc))
199 rc = HGCMSvcGetU64(&paParms[7], &pTransfer->Header.cObjects);
200 if (RT_SUCCESS(rc))
201 rc = HGCMSvcGetU32(&paParms[8], &pTransfer->Header.enmCompression);
202 if (RT_SUCCESS(rc))
203 rc = HGCMSvcGetU32(&paParms[9], (uint32_t *)&pTransfer->Header.enmChecksumType);
204 if (RT_SUCCESS(rc))
205 rc = HGCMSvcGetPv(&paParms[10], &pTransfer->Header.pvChecksum, &pTransfer->Header.cbChecksum);
206 if (RT_SUCCESS(rc))
207 rc = HGCMSvcGetU32(&paParms[11], &pTransfer->Header.cbChecksum);
208
209 LogFlowFunc(("fFlags=0x%x, cbMeta=%RU32, cbTotalSize=%RU64, cObj=%RU64\n",
210 pTransfer->Header.uFlags, pTransfer->Header.cbMeta, pTransfer->Header.cbTotal, pTransfer->Header.cObjects));
211
212 if (RT_SUCCESS(rc))
213 {
214 /** @todo Validate pvMetaFmt + cbMetaFmt. */
215 /** @todo Validate checksum. */
216 rc = SharedClipboardMetaDataResize(&pTransfer->Meta, pTransfer->Header.cbMeta);
217 }
218 }
219
220 break;
221 }
222
223 case VBOX_SHARED_CLIPBOARD_FN_WRITE_DATA_CHUNK:
224 {
225 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_DATA_CHUNK\n"));
226 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_DATA_CHUNK)
227 {
228 if (!SharedClipboardURICtxGetActiveTransfers(&pClientData->URI))
229 {
230 rc = VERR_WRONG_ORDER;
231 break;
232 }
233
234 VBOXCLIPBOARDDATACHUNK data;
235 RT_ZERO(data);
236 /* Note: Context ID (paParms[0]) not used yet. */
237 rc = HGCMSvcGetPv(&paParms[1], (void**)&data.pvData, &data.cbData);
238 if (RT_SUCCESS(rc))
239 rc = HGCMSvcGetU32(&paParms[2], &data.cbData);
240 if (RT_SUCCESS(rc))
241 rc = HGCMSvcGetPv(&paParms[3], (void**)&data.pvChecksum, &data.cbChecksum);
242 if (RT_SUCCESS(rc))
243 rc = HGCMSvcGetU32(&paParms[4], &data.cbChecksum);
244
245 if (RT_SUCCESS(rc))
246 {
247 if (!vboxSvcClipboardURIDataChunkIsValid(&data))
248 rc = VERR_INVALID_PARAMETER;
249 }
250
251 if (RT_SUCCESS(rc))
252 {
253 /** @todo Validate checksum. */
254 rc = SharedClipboardMetaDataAdd(&pTransfer->Meta, data.pvData, data.cbData);
255 if ( RT_SUCCESS(rc)
256 && SharedClipboardMetaDataGetUsed(&pTransfer->Meta) == pTransfer->Header.cbMeta) /* Meta data transfer complete? */
257 {
258 if (RT_SUCCESS(rc))
259 {
260
261 }
262
263 /* We're done processing the meta data, so just destroy it. */
264 SharedClipboardMetaDataDestroy(&pTransfer->Meta);
265 }
266 }
267 }
268 break;
269 }
270
271 case VBOX_SHARED_CLIPBOARD_FN_READ_DIR:
272 {
273 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_READ_DIR\n"));
274 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_READ_DIR)
275 {
276 if (!SharedClipboardURICtxGetActiveTransfers(&pClientData->URI))
277 {
278 rc = VERR_WRONG_ORDER;
279 break;
280 }
281
282 VBOXCLIPBOARDDIRDATA data;
283 rc = VBoxClipboardSvcImplURIReadDir(pClientData, &data);
284 if (RT_SUCCESS(rc))
285 {
286 /* Note: Context ID (paParms[0]) not used yet. */
287 HGCMSvcSetPv (&paParms[1], data.pszPath, data.cbPath);
288 HGCMSvcSetU32(&paParms[2], data.cbPath);
289 HGCMSvcSetU32(&paParms[3], data.fMode);
290
291 vboxSvcClipboardURIDirDataDestroy(&data);
292 }
293 }
294 break;
295 }
296
297 case VBOX_SHARED_CLIPBOARD_FN_WRITE_DIR:
298 {
299 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_DIR\n"));
300 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_DIR)
301 {
302 if (!SharedClipboardURICtxGetActiveTransfers(&pClientData->URI))
303 {
304 rc = VERR_WRONG_ORDER;
305 break;
306 }
307
308 VBOXCLIPBOARDDIRDATA data;
309 RT_ZERO(data);
310 /* Note: Context ID (paParms[0]) not used yet. */
311 rc = HGCMSvcGetPv(&paParms[1], (void**)&data.pszPath, &data.cbPath);
312 if (RT_SUCCESS(rc))
313 rc = HGCMSvcGetU32(&paParms[2], &data.cbPath);
314 if (RT_SUCCESS(rc))
315 rc = HGCMSvcGetU32(&paParms[3], &data.fMode);
316
317 LogFlowFunc(("pszPath=%s, cbPath=%RU32, fMode=0x%x\n", data.pszPath, data.cbPath, data.fMode));
318
319 if (RT_SUCCESS(rc))
320 {
321 if (!vboxSvcClipboardURIDirDataIsValid(&data))
322 rc = VERR_INVALID_PARAMETER;
323 }
324
325 if (RT_SUCCESS(rc))
326 {
327 SharedClipboardArea *pArea = SharedClipboardURITransferGetArea(pTransfer);
328 AssertPtrBreakStmt(pArea, rc = VERR_INVALID_POINTER);
329
330 const char *pszCacheDir = pArea->GetDirAbs();
331 char *pszDir = RTPathJoinA(pszCacheDir, data.pszPath);
332 if (pszDir)
333 {
334 LogFlowFunc(("pszDir=%s\n", pszDir));
335
336 rc = RTDirCreateFullPath(pszDir, data.fMode);
337 if (RT_SUCCESS(rc))
338 {
339 /* Add for having a proper rollback. */
340 int rc2 = pArea->AddDir(pszDir);
341 AssertRC(rc2);
342 }
343
344 RTStrFree(pszDir);
345 }
346 else
347 rc = VERR_NO_MEMORY;
348 }
349 }
350 break;
351 }
352
353 case VBOX_SHARED_CLIPBOARD_FN_READ_FILE_HDR:
354 {
355 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_READ_FILE_HDR\n"));
356 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_READ_FILE_HDR)
357 {
358 if (!SharedClipboardURICtxGetActiveTransfers(&pClientData->URI))
359 {
360 rc = VERR_WRONG_ORDER;
361 break;
362 }
363
364 VBOXCLIPBOARDFILEHDR hdr;
365 rc = VBoxClipboardSvcImplURIReadFileHdr(pClientData, &hdr);
366 if (RT_SUCCESS(rc))
367 {
368 /* Note: Context ID (paParms[0]) not used yet. */
369 HGCMSvcSetPv (&paParms[1], hdr.pszFilePath, hdr.cbFilePath);
370 HGCMSvcSetU32(&paParms[2], hdr.cbFilePath);
371 HGCMSvcSetU32(&paParms[3], hdr.fFlags);
372 HGCMSvcSetU32(&paParms[4], hdr.fMode);
373 HGCMSvcSetU64(&paParms[5], hdr.cbSize);
374
375 vboxSvcClipboardURIFileHdrDestroy(&hdr);
376 }
377 }
378 break;
379 }
380
381 case VBOX_SHARED_CLIPBOARD_FN_WRITE_FILE_HDR:
382 {
383 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_FILE_HDR\n"));
384 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_FILE_HDR)
385 {
386 if (!SharedClipboardURICtxGetActiveTransfers(&pClientData->URI))
387 {
388 rc = VERR_WRONG_ORDER;
389 break;
390 }
391
392 VBOXCLIPBOARDFILEHDR data;
393 RT_ZERO(data);
394 /* Note: Context ID (paParms[0]) not used yet. */
395 rc = HGCMSvcGetPv(&paParms[1], (void**)&data.pszFilePath, &data.cbFilePath);
396 if (RT_SUCCESS(rc))
397 rc = HGCMSvcGetU32(&paParms[2], &data.cbFilePath);
398 if (RT_SUCCESS(rc))
399 rc = HGCMSvcGetU32(&paParms[3], &data.fFlags);
400 if (RT_SUCCESS(rc))
401 rc = HGCMSvcGetU32(&paParms[4], &data.fMode);
402 if (RT_SUCCESS(rc))
403 rc = HGCMSvcGetU64(&paParms[5], &data.cbSize);
404
405 LogFlowFunc(("pszPath=%s, cbPath=%RU32, fMode=0x%x, cbSize=%RU64\n",
406 data.pszFilePath, data.cbFilePath, data.fMode, data.cbSize));
407
408 if (RT_SUCCESS(rc))
409 {
410 if (!vboxSvcClipboardURIFileHdrIsValid(&data, &pTransfer->Header))
411 {
412 rc = VERR_INVALID_PARAMETER;
413 }
414 else
415 {
416 if (pTransfer->ObjCtx.pObj == NULL)
417 {
418 pTransfer->ObjCtx.pObj = new SharedClipboardURIObject(SharedClipboardURIObject::Type_File);
419 if (!pTransfer->ObjCtx.pObj) /** @todo Can this throw? */
420 rc = VERR_NO_MEMORY;
421 }
422 else /* There still is another object being processed? */
423 rc = VERR_WRONG_ORDER;
424 }
425 }
426
427 if (RT_SUCCESS(rc))
428 {
429 SharedClipboardArea *pArea = SharedClipboardURITransferGetArea(pTransfer);
430 AssertPtrBreakStmt(pArea, rc = VERR_INVALID_POINTER);
431
432 const char *pszCacheDir = pArea->GetDirAbs();
433
434 char pszPathAbs[RTPATH_MAX];
435 rc = RTPathJoin(pszPathAbs, sizeof(pszPathAbs), pszCacheDir, data.pszFilePath);
436 if (RT_SUCCESS(rc))
437 {
438 rc = SharedClipboardPathSanitize(pszPathAbs, sizeof(pszPathAbs));
439 if (RT_SUCCESS(rc))
440 {
441 SharedClipboardURIObject *pObj = SharedClipboardURITransferGetObject(pTransfer, 0 /* Index */);
442 AssertPtrBreakStmt(pObj, VERR_INVALID_POINTER);
443
444 /** @todo Add sparse file support based on fFlags? (Use Open(..., fFlags | SPARSE). */
445 rc = pObj->OpenFileEx(pszPathAbs, SharedClipboardURIObject::View_Target,
446 RTFILE_O_CREATE_REPLACE | RTFILE_O_WRITE | RTFILE_O_DENY_WRITE,
447 (data.fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR);
448 if (RT_SUCCESS(rc))
449 {
450 rc = pObj->SetSize(data.cbSize);
451
452 /** @todo Unescape path before printing. */
453 LogRel2(("Clipboard: Transferring guest file '%s' to host (%RU64 bytes, mode 0x%x)\n",
454 pObj->GetDestPathAbs().c_str(), pObj->GetSize(), pObj->GetMode()));
455
456 if (pObj->IsComplete()) /* 0-byte file? We're done already. */
457 {
458 /** @todo Sanitize path. */
459 LogRel2(("Clipboard: Transferring guest file '%s' (0 bytes) to host complete\n",
460 pObj->GetDestPathAbs().c_str()));
461
462 SharedClipboardURIObjCtxUninit(&pTransfer->ObjCtx);
463 }
464
465 /* Add for having a proper rollback. */
466 int rc2 = pArea->AddFile(pszPathAbs);
467 AssertRC(rc2);
468 }
469 else
470 LogRel(("Clipboard: Error opening/creating guest file '%s' on host, rc=%Rrc\n", pszPathAbs, rc));
471 }
472 }
473 }
474 }
475 break;
476 }
477
478 case VBOX_SHARED_CLIPBOARD_FN_READ_FILE_DATA:
479 {
480 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_READ_FILE_DATA\n"));
481 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_READ_FILE_DATA)
482 {
483 if (!SharedClipboardURICtxGetActiveTransfers(&pClientData->URI))
484 {
485 rc = VERR_WRONG_ORDER;
486 break;
487 }
488
489 VBOXCLIPBOARDFILEDATA data;
490 rc = VBoxClipboardSvcImplURIReadFileData(pClientData, &data);
491 if (RT_SUCCESS(rc))
492 {
493 /* Note: Context ID (paParms[0]) not used yet. */
494 HGCMSvcSetPv (&paParms[1], data.pvData, data.cbData);
495 HGCMSvcSetU32(&paParms[2], data.cbData);
496 HGCMSvcSetPv (&paParms[3], data.pvChecksum, data.cbChecksum);
497 HGCMSvcSetU32(&paParms[4], data.cbChecksum);
498
499 vboxSvcClipboardURIFileDataDestroy(&data);
500 }
501 }
502 break;
503 }
504
505 case VBOX_SHARED_CLIPBOARD_FN_WRITE_FILE_DATA:
506 {
507 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_FILE_DATA\n"));
508 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_FILE_DATA)
509 {
510 if (!SharedClipboardURICtxGetActiveTransfers(&pClientData->URI))
511 {
512 rc = VERR_WRONG_ORDER;
513 break;
514 }
515
516 VBOXCLIPBOARDFILEDATA data;
517 RT_ZERO(data);
518 /* Note: Context ID (paParms[0]) not used yet. */
519 rc = HGCMSvcGetPv(&paParms[1], (void**)&data.pvData, &data.cbData);
520 if (RT_SUCCESS(rc))
521 rc = HGCMSvcGetU32(&paParms[2], &data.cbData);
522 if (RT_SUCCESS(rc))
523 rc = HGCMSvcGetPv(&paParms[3], (void**)&data.pvChecksum, &data.cbChecksum);
524 if (RT_SUCCESS(rc))
525 rc = HGCMSvcGetU32(&paParms[4], &data.cbChecksum);
526
527 LogFlowFunc(("pvData=0x%p, cbData=%RU32\n", data.pvData, data.cbData));
528
529 if (RT_SUCCESS(rc))
530 {
531 if (!vboxSvcClipboardURIFileDataIsValid(&data, &pTransfer->Header))
532 rc = VERR_INVALID_PARAMETER;
533
534 if (!SharedClipboardURIObjCtxIsValid(&pTransfer->ObjCtx))
535 rc = VERR_WRONG_ORDER;
536 }
537
538 if (RT_SUCCESS(rc))
539 {
540 SharedClipboardURIObject *pObj = SharedClipboardURIObjCtxGetObj(&pTransfer->ObjCtx);
541 AssertPtrBreakStmt(pObj, VERR_INVALID_POINTER);
542
543 uint32_t cbWritten;
544 rc = pObj->Write(data.pvData, data.cbData, &cbWritten);
545 if (RT_SUCCESS(rc))
546 {
547 Assert(cbWritten <= data.cbData);
548 if (cbWritten < data.cbData)
549 {
550 /** @todo What to do when the host's disk is full? */
551 rc = VERR_DISK_FULL;
552 }
553
554 if ( pObj->IsComplete()
555 || RT_FAILURE(rc))
556 SharedClipboardURIObjCtxUninit(&pTransfer->ObjCtx);
557 }
558 else
559 LogRel(("Clipboard: Error writing guest file data for '%s', rc=%Rrc\n", pObj->GetDestPathAbs().c_str(), rc));
560 }
561 }
562 break;
563 }
564
565 case VBOX_SHARED_CLIPBOARD_FN_WRITE_CANCEL:
566 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_CANCEL\n"));
567 AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED);
568 break;
569
570 case VBOX_SHARED_CLIPBOARD_FN_WRITE_ERROR:
571 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_ERROR\n"));
572 AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED);
573 break;
574
575 default:
576 AssertMsgFailed(("Not implemented\n"));
577 break;
578 }
579
580 LogFlowFuncLeaveRC(rc);
581 return rc;
582}
583
584/**
585 * URI host handler for the Shared Clipboard host service.
586 *
587 * @returns VBox status code.
588 * @param u32Function Function number being called.
589 * @param cParms Number of function parameters supplied.
590 * @param paParms Array function parameters supplied.
591 */
592int vboxSvcClipboardURIHostHandler(uint32_t u32Function,
593 uint32_t cParms,
594 VBOXHGCMSVCPARM paParms[])
595{
596 RT_NOREF(cParms, paParms);
597
598 int rc = VERR_INVALID_PARAMETER; /* Play safe. */
599
600 switch (u32Function)
601 {
602 case VBOX_SHARED_CLIPBOARD_HOST_FN_CANCEL:
603 AssertFailed(); /** @todo Implement this. */
604 break;
605
606 case VBOX_SHARED_CLIPBOARD_HOST_FN_ERROR:
607 AssertFailed(); /** @todo Implement this. */
608 break;
609
610 default:
611 AssertMsgFailed(("Not implemented\n"));
612 break;
613
614 }
615
616 LogFlowFuncLeaveRC(rc);
617 return rc;
618}
619
620int vboxSvcClipboardURIAreaRegister(PVBOXCLIPBOARDCLIENTSTATE pClientState, PSHAREDCLIPBOARDURITRANSFER pTransfer)
621{
622 LogFlowFuncEnter();
623
624 AssertMsgReturn(pTransfer->pArea == NULL, ("An area already is registered for this transfer\n"),
625 VERR_WRONG_ORDER);
626
627 pTransfer->pArea = new SharedClipboardArea();
628 if (!pTransfer->pArea)
629 return VERR_NO_MEMORY;
630
631 VBOXCLIPBOARDEXTAREAPARMS parms;
632 RT_ZERO(parms);
633
634 parms.uID = NIL_SHAREDCLIPBOARDAREAID;
635 parms.u.fn_register.pvData = SharedClipboardMetaDataMutableRaw(&pTransfer->Meta);
636 parms.u.fn_register.cbData = (uint32_t)SharedClipboardMetaDataGetUsed(&pTransfer->Meta);
637
638 /* As the meta data is now complete, register a new clipboard on the host side. */
639 int rc = g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_AREA_REGISTER, &parms, sizeof(parms));
640 if (RT_SUCCESS(rc))
641 rc = pTransfer->pArea->OpenTemp(parms.uID /* Area ID */);
642
643 LogFlowFunc(("Registered new clipboard area (%RU32) by client %RU32 with rc=%Rrc\n",
644 parms.uID, pClientState->u32ClientID, rc));
645
646 LogFlowFuncLeaveRC(rc);
647 return rc;
648}
649
650int vboxSvcClipboardURIAreaAttach(PVBOXCLIPBOARDCLIENTSTATE pClientState, PSHAREDCLIPBOARDURITRANSFER pTransfer)
651{
652 LogFlowFuncEnter();
653
654 AssertMsgReturn(pTransfer->pArea == NULL, ("An area already is attached to this transfer\n"),
655 VERR_WRONG_ORDER);
656
657 pTransfer->pArea = new SharedClipboardArea();
658 if (!pTransfer->pArea)
659 return VERR_NO_MEMORY;
660
661 VBOXCLIPBOARDEXTAREAPARMS parms;
662 RT_ZERO(parms);
663
664 parms.uID = 0; /* 0 means most recent clipboard area. */
665
666 /* The client now needs to attach to the most recent clipboard area
667 * to keep a reference to it. The host does the actual book keeping / cleanup then.
668 *
669 * This might fail if the host does not have a most recent clipboard area (yet). */
670 int rc = g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_AREA_ATTACH, &parms, sizeof(parms));
671 if (RT_SUCCESS(rc))
672 rc = pTransfer->pArea->OpenTemp(parms.uID /* Area ID */);
673
674 LogFlowFunc(("Attached client %RU32 to clipboard area %RU32 with rc=%Rrc\n",
675 pClientState->u32ClientID, parms.uID, rc));
676
677 LogFlowFuncLeaveRC(rc);
678 return rc;
679}
680
681int vboxSvcClipboardURIAreaDetach(PVBOXCLIPBOARDCLIENTSTATE pClientState, PSHAREDCLIPBOARDURITRANSFER pTransfer)
682{
683 LogFlowFuncEnter();
684
685 if (!pTransfer->pArea)
686 return VINF_SUCCESS;
687
688 const uint32_t uAreaID = pTransfer->pArea->GetID();
689
690 VBOXCLIPBOARDEXTAREAPARMS parms;
691 RT_ZERO(parms);
692 parms.uID = uAreaID;
693
694 int rc = g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_AREA_DETACH, &parms, sizeof(parms));
695
696 LogFlowFunc(("Detached client %RU32 from clipboard area %RU32 with rc=%Rrc\n",
697 pClientState->u32ClientID, uAreaID, rc));
698
699 LogFlowFuncLeaveRC(rc);
700 return rc;
701}
702
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