VirtualBox

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

Last change on this file since 79142 was 79120, 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: 28.9 KB
Line 
1/* $Id: VBoxSharedClipboardSvc-uri.cpp 79120 2019-06-13 10:08:33Z 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 SharedClipboardURIDirDataDestroy(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 SharedClipboardURIFileHdrDestroy(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 SharedClipboardURIFileDataDestroy(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
99int VBoxSvcClipboardURIReadDataHdr(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDDATAHDR pDataHdr)
100{
101 if (cParms != VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_DATA_HDR)
102 return VERR_INVALID_PARAMETER;
103
104 RT_BZERO(pDataHdr, sizeof(VBOXCLIPBOARDDATAHDR));
105
106 /* Note: Context ID (paParms[0]) not used yet. */
107 int rc = HGCMSvcGetU32(&paParms[1], &pDataHdr->uFlags);
108 if (RT_SUCCESS(rc))
109 rc = HGCMSvcGetU32(&paParms[2], &pDataHdr->uScreenId);
110 if (RT_SUCCESS(rc))
111 rc = HGCMSvcGetU64(&paParms[3], &pDataHdr->cbTotal);
112 if (RT_SUCCESS(rc))
113 rc = HGCMSvcGetU32(&paParms[4], &pDataHdr->cbMeta);
114 if (RT_SUCCESS(rc))
115 rc = HGCMSvcGetPv(&paParms[5], &pDataHdr->pvMetaFmt, &pDataHdr->cbMetaFmt);
116 if (RT_SUCCESS(rc))
117 rc = HGCMSvcGetU32(&paParms[6], &pDataHdr->cbMetaFmt);
118 if (RT_SUCCESS(rc))
119 rc = HGCMSvcGetU64(&paParms[7], &pDataHdr->cObjects);
120 if (RT_SUCCESS(rc))
121 rc = HGCMSvcGetU32(&paParms[8], &pDataHdr->enmCompression);
122 if (RT_SUCCESS(rc))
123 rc = HGCMSvcGetU32(&paParms[9], (uint32_t *)&pDataHdr->enmChecksumType);
124 if (RT_SUCCESS(rc))
125 rc = HGCMSvcGetPv(&paParms[10], &pDataHdr->pvChecksum, &pDataHdr->cbChecksum);
126 if (RT_SUCCESS(rc))
127 rc = HGCMSvcGetU32(&paParms[11], &pDataHdr->cbChecksum);
128
129 LogFlowFunc(("fFlags=0x%x, cbMeta=%RU32, cbTotalSize=%RU64, cObj=%RU64\n",
130 pDataHdr->uFlags, pDataHdr->cbMeta, pDataHdr->cbTotal, pDataHdr->cObjects));
131
132 if (RT_SUCCESS(rc))
133 {
134 /** @todo Validate pvMetaFmt + cbMetaFmt. */
135 /** @todo Validate header checksum. */
136 }
137
138 LogFlowFuncLeaveRC(rc);
139 return rc;
140}
141
142int VBoxSvcClipboardURIReadDataChunk(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDDATACHUNK pDataChunk)
143{
144 if (cParms != VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_DATA_CHUNK)
145 return VERR_INVALID_PARAMETER;
146
147 RT_BZERO(pDataChunk, sizeof(VBOXCLIPBOARDDATACHUNK));
148
149 /* Note: Context ID (paParms[0]) not used yet. */
150 int rc = HGCMSvcGetPv(&paParms[1], (void**)&pDataChunk->pvData, &pDataChunk->cbData);
151 if (RT_SUCCESS(rc))
152 rc = HGCMSvcGetU32(&paParms[2], &pDataChunk->cbData);
153 if (RT_SUCCESS(rc))
154 rc = HGCMSvcGetPv(&paParms[3], (void**)&pDataChunk->pvChecksum, &pDataChunk->cbChecksum);
155 if (RT_SUCCESS(rc))
156 rc = HGCMSvcGetU32(&paParms[4], &pDataChunk->cbChecksum);
157
158 if (RT_SUCCESS(rc))
159 {
160 if (!SharedClipboardURIDataChunkIsValid(pDataChunk))
161 rc = VERR_INVALID_PARAMETER;
162 }
163
164 LogFlowFuncLeaveRC(rc);
165 return rc;
166}
167
168int VBoxSvcClipboardURIReadDir(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDDIRDATA pDirData)
169{
170 if (cParms != VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_DIR)
171 return VERR_INVALID_PARAMETER;
172
173 RT_BZERO(pDirData, sizeof(VBOXCLIPBOARDDIRDATA));
174
175 /* Note: Context ID (paParms[0]) not used yet. */
176 int rc = HGCMSvcGetPv(&paParms[1], (void**)&pDirData->pszPath, &pDirData->cbPath);
177 if (RT_SUCCESS(rc))
178 rc = HGCMSvcGetU32(&paParms[2], &pDirData->cbPath);
179 if (RT_SUCCESS(rc))
180 rc = HGCMSvcGetU32(&paParms[3], &pDirData->fMode);
181
182 LogFlowFunc(("pszPath=%s, cbPath=%RU32, fMode=0x%x\n", pDirData->pszPath, pDirData->cbPath, pDirData->fMode));
183
184 if (RT_SUCCESS(rc))
185 {
186 if (!SharedClipboardURIDirDataIsValid(pDirData))
187 rc = VERR_INVALID_PARAMETER;
188 }
189
190 LogFlowFuncLeaveRC(rc);
191 return rc;
192}
193
194int VBoxSvcClipboardURIReadFileHdr(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDFILEHDR pFileHdr)
195{
196 if (cParms != VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_FILE_HDR)
197 return VERR_INVALID_PARAMETER;
198
199 RT_BZERO(pFileHdr, sizeof(VBOXCLIPBOARDFILEHDR));
200
201 /* Note: Context ID (paParms[0]) not used yet. */
202 int rc = HGCMSvcGetPv(&paParms[1], (void**)&pFileHdr->pszFilePath, &pFileHdr->cbFilePath);
203 if (RT_SUCCESS(rc))
204 rc = HGCMSvcGetU32(&paParms[2], &pFileHdr->cbFilePath);
205 if (RT_SUCCESS(rc))
206 rc = HGCMSvcGetU32(&paParms[3], &pFileHdr->fFlags);
207 if (RT_SUCCESS(rc))
208 rc = HGCMSvcGetU32(&paParms[4], &pFileHdr->fMode);
209 if (RT_SUCCESS(rc))
210 rc = HGCMSvcGetU64(&paParms[5], &pFileHdr->cbSize);
211
212 LogFlowFunc(("pszPath=%s, cbPath=%RU32, fMode=0x%x, cbSize=%RU64\n",
213 pFileHdr->pszFilePath, pFileHdr->cbFilePath, pFileHdr->fMode, pFileHdr->cbSize));
214
215 LogFlowFuncLeaveRC(rc);
216 return rc;
217}
218
219int VBoxSvcClipboardURIReadFileData(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDFILEDATA pFileData)
220{
221 if (cParms != VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_FILE_DATA)
222 return VERR_INVALID_PARAMETER;
223
224 RT_BZERO(pFileData, sizeof(VBOXCLIPBOARDFILEDATA));
225
226 /* Note: Context ID (paParms[0]) not used yet. */
227 int rc = HGCMSvcGetPv(&paParms[1], (void**)&pFileData->pvData, &pFileData->cbData);
228 if (RT_SUCCESS(rc))
229 rc = HGCMSvcGetU32(&paParms[2], &pFileData->cbData);
230 if (RT_SUCCESS(rc))
231 rc = HGCMSvcGetPv(&paParms[3], (void**)&pFileData->pvChecksum, &pFileData->cbChecksum);
232 if (RT_SUCCESS(rc))
233 rc = HGCMSvcGetU32(&paParms[4], &pFileData->cbChecksum);
234
235 LogFlowFunc(("pvData=0x%p, cbData=%RU32\n", pFileData->pvData, pFileData->cbData));
236
237 LogFlowFuncLeaveRC(rc);
238 return rc;
239}
240
241/**
242 * URI client (guest) handler for the Shared Clipboard host service.
243 *
244 * @returns VBox status code.
245 * @param u32ClientID Client ID of the client which called this handler.
246 * @param pvClient Pointer to client-specific data block.
247 * @param u32Function Function number being called.
248 * @param cParms Number of function parameters supplied.
249 * @param paParms Array function parameters supplied.
250 * @param tsArrival Timestamp of arrival.
251 * @param pfAsync Returns \c true if the response needs to be being asynchronous or \c false if not,
252 */
253int vboxSvcClipboardURIHandler(uint32_t u32ClientID,
254 void *pvClient,
255 uint32_t u32Function,
256 uint32_t cParms,
257 VBOXHGCMSVCPARM paParms[],
258 uint64_t tsArrival,
259 bool *pfAsync)
260{
261 RT_NOREF(u32ClientID, paParms, tsArrival, pfAsync);
262
263 LogFlowFunc(("u32ClientID=%RU32, u32Function=%RU32, cParms=%RU32, g_pfnExtension=%p\n",
264 u32ClientID, u32Function, cParms, g_pfnExtension));
265
266 const PVBOXCLIPBOARDCLIENTDATA pClientData = (PVBOXCLIPBOARDCLIENTDATA)pvClient;
267 AssertPtrReturn(pClientData, VERR_INVALID_POINTER);
268
269 /* Check if we've the right mode set. */
270 int rc = VERR_ACCESS_DENIED; /* Play safe. */
271
272 if (!vboxSvcClipboardURIMsgIsAllowed(vboxSvcClipboardGetMode(), u32Function))
273 return rc;
274
275 /* A (valid) service extension is needed because VBoxSVC needs to keep track of the
276 * clipboard areas cached on the host. */
277 if (!g_pfnExtension)
278 {
279#ifdef DEBUG_andy
280 AssertPtr(g_pfnExtension);
281#endif
282 LogFunc(("Invalid / no service extension set, skipping URI handling\n"));
283 rc = VERR_NOT_SUPPORTED;
284 }
285
286 if (RT_FAILURE(rc))
287 return rc;
288
289 const PSHAREDCLIPBOARDURITRANSFER pTransfer = SharedClipboardURICtxGetTransfer(&pClientData->URI, 0 /* Index */);
290
291 rc = VERR_INVALID_PARAMETER; /* Play safe. */
292
293 switch (u32Function)
294 {
295 case VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_DATA_HDR:
296 {
297 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_READ_DATA_HDR\n"));
298 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_READ_DATA_HDR)
299 {
300 bool fDetach = false;
301
302 if (RT_SUCCESS(rc))
303 {
304 // pTransfer->Area. parms.uID
305
306 /** @todo Detach if header / meta size is 0. */
307 }
308
309 /* Do we need to detach again because we're done? */
310 if (fDetach)
311 vboxSvcClipboardURIAreaDetach(&pClientData->State, pTransfer);
312 }
313 break;
314 }
315
316 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DATA_HDR:
317 RT_FALL_THROUGH();
318#if 0
319 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DATA_CHUNK:
320 RT_FALL_THROUGH();
321 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DIR:
322 RT_FALL_THROUGH();
323 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_FILE_HDR:
324 RT_FALL_THROUGH();
325 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_FILE_DATA:
326 RT_FALL_THROUGH();
327 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_CANCEL:
328 RT_FALL_THROUGH();
329 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_ERROR:
330 {
331 if ( u32Function == VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DATA_HDR
332 && SharedClipboardURICtxMaximumTransfersReached(&pClientData->URI))
333 {
334 rc = VERR_SHCLPB_MAX_TRANSFERS_REACHED;
335 break;
336 }
337
338 SHAREDCLIPBOARDPROVIDERWRITEPARMS writeParms;
339 RT_ZERO(writeParms);
340
341 writeParms.u.HostService.uMsg = u32Function;
342 writeParms.u.HostService.cParms = cParms;
343 writeParms.u.HostService.paParms = paParms;
344
345 rc = pTransfer->pProvider->Write(&writeParms);
346
347
348
349 break;
350 }
351#endif
352
353 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DATA_CHUNK:
354 {
355 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_DATA_CHUNK\n"));
356
357 if (!SharedClipboardURICtxGetActiveTransfers(&pClientData->URI))
358 {
359 rc = VERR_WRONG_ORDER;
360 break;
361 }
362
363#if 0
364 if (RT_SUCCESS(rc))
365 {
366 /** @todo Validate checksum. */
367 rc = SharedClipboardMetaDataAdd(&pTransfer->Meta, data.pvData, data.cbData);
368 if ( RT_SUCCESS(rc)
369 && SharedClipboardMetaDataGetUsed(&pTransfer->Meta) == pTransfer->Header.cbMeta) /* Meta data transfer complete? */
370 {
371 if (RT_SUCCESS(rc))
372 {
373
374 }
375
376 /* We're done processing the meta data, so just destroy it. */
377 SharedClipboardMetaDataDestroy(&pTransfer->Meta);
378 }
379 }
380#endif
381 break;
382 }
383
384 case VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_DIR:
385 {
386 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_READ_DIR\n"));
387 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_READ_DIR)
388 {
389 if (!SharedClipboardURICtxGetActiveTransfers(&pClientData->URI))
390 {
391 rc = VERR_WRONG_ORDER;
392 break;
393 }
394
395 VBOXCLIPBOARDDIRDATA data;
396 rc = VBoxClipboardSvcImplURIReadDir(pClientData, &data);
397 if (RT_SUCCESS(rc))
398 {
399 /* Note: Context ID (paParms[0]) not used yet. */
400 HGCMSvcSetPv (&paParms[1], data.pszPath, data.cbPath);
401 HGCMSvcSetU32(&paParms[2], data.cbPath);
402 HGCMSvcSetU32(&paParms[3], data.fMode);
403
404 SharedClipboardURIDirDataDestroy(&data);
405 }
406 }
407 break;
408 }
409
410 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DIR:
411 {
412 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_DIR\n"));
413
414 if (!SharedClipboardURICtxGetActiveTransfers(&pClientData->URI))
415 {
416 rc = VERR_WRONG_ORDER;
417 break;
418 }
419
420#if 0
421 if (RT_SUCCESS(rc))
422 {
423 SharedClipboardArea *pArea = SharedClipboardURITransferGetArea(pTransfer);
424 AssertPtrBreakStmt(pArea, rc = VERR_INVALID_POINTER);
425
426 const char *pszCacheDir = pArea->GetDirAbs();
427 char *pszDir = RTPathJoinA(pszCacheDir, data.pszPath);
428 if (pszDir)
429 {
430 LogFlowFunc(("pszDir=%s\n", pszDir));
431
432 rc = RTDirCreateFullPath(pszDir, data.fMode);
433 if (RT_SUCCESS(rc))
434 {
435 /* Add for having a proper rollback. */
436 int rc2 = pArea->AddDir(pszDir);
437 AssertRC(rc2);
438 }
439
440 RTStrFree(pszDir);
441 }
442 else
443 rc = VERR_NO_MEMORY;
444 }
445#endif
446 break;
447 }
448
449 case VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_FILE_HDR:
450 {
451 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_READ_FILE_HDR\n"));
452 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_READ_FILE_HDR)
453 {
454 if (!SharedClipboardURICtxGetActiveTransfers(&pClientData->URI))
455 {
456 rc = VERR_WRONG_ORDER;
457 break;
458 }
459
460 VBOXCLIPBOARDFILEHDR hdr;
461 rc = VBoxClipboardSvcImplURIReadFileHdr(pClientData, &hdr);
462 if (RT_SUCCESS(rc))
463 {
464 /* Note: Context ID (paParms[0]) not used yet. */
465 HGCMSvcSetPv (&paParms[1], hdr.pszFilePath, hdr.cbFilePath);
466 HGCMSvcSetU32(&paParms[2], hdr.cbFilePath);
467 HGCMSvcSetU32(&paParms[3], hdr.fFlags);
468 HGCMSvcSetU32(&paParms[4], hdr.fMode);
469 HGCMSvcSetU64(&paParms[5], hdr.cbSize);
470
471 SharedClipboardURIFileHdrDestroy(&hdr);
472 }
473 }
474 break;
475 }
476
477 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_FILE_HDR:
478 {
479 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_FILE_HDR\n"));
480
481 if (!SharedClipboardURICtxGetActiveTransfers(&pClientData->URI))
482 {
483 rc = VERR_WRONG_ORDER;
484 break;
485 }
486
487#if 0
488 if (RT_SUCCESS(rc))
489 {
490 if (!vboxSvcClipboardURIFileHdrIsValid(&data, &pTransfer->Header))
491 {
492 rc = VERR_INVALID_PARAMETER;
493 }
494 else
495 {
496 if (pTransfer->ObjCtx.pObj == NULL)
497 {
498 pTransfer->ObjCtx.pObj = new SharedClipboardURIObject(SharedClipboardURIObject::Type_File);
499 if (!pTransfer->ObjCtx.pObj) /** @todo Can this throw? */
500 rc = VERR_NO_MEMORY;
501 }
502 else /* There still is another object being processed? */
503 rc = VERR_WRONG_ORDER;
504 }
505 }
506
507 if (RT_SUCCESS(rc))
508 {
509 SharedClipboardArea *pArea = SharedClipboardURITransferGetArea(pTransfer);
510 AssertPtrBreakStmt(pArea, rc = VERR_INVALID_POINTER);
511
512 const char *pszCacheDir = pArea->GetDirAbs();
513
514 char pszPathAbs[RTPATH_MAX];
515 rc = RTPathJoin(pszPathAbs, sizeof(pszPathAbs), pszCacheDir, data.pszFilePath);
516 if (RT_SUCCESS(rc))
517 {
518 rc = SharedClipboardPathSanitize(pszPathAbs, sizeof(pszPathAbs));
519 if (RT_SUCCESS(rc))
520 {
521 SharedClipboardURIObject *pObj = SharedClipboardURITransferGetObject(pTransfer, 0 /* Index */);
522 AssertPtrBreakStmt(pObj, VERR_INVALID_POINTER);
523
524 /** @todo Add sparse file support based on fFlags? (Use Open(..., fFlags | SPARSE). */
525 rc = pObj->OpenFileEx(pszPathAbs, SharedClipboardURIObject::View_Target,
526 RTFILE_O_CREATE_REPLACE | RTFILE_O_WRITE | RTFILE_O_DENY_WRITE,
527 (data.fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR);
528 if (RT_SUCCESS(rc))
529 {
530 rc = pObj->SetSize(data.cbSize);
531
532 /** @todo Unescape path before printing. */
533 LogRel2(("Clipboard: Transferring guest file '%s' to host (%RU64 bytes, mode 0x%x)\n",
534 pObj->GetDestPathAbs().c_str(), pObj->GetSize(), pObj->GetMode()));
535
536 if (pObj->IsComplete()) /* 0-byte file? We're done already. */
537 {
538 /** @todo Sanitize path. */
539 LogRel2(("Clipboard: Transferring guest file '%s' (0 bytes) to host complete\n",
540 pObj->GetDestPathAbs().c_str()));
541
542 SharedClipboardURIObjCtxUninit(&pTransfer->ObjCtx);
543 }
544
545 /* Add for having a proper rollback. */
546 int rc2 = pArea->AddFile(pszPathAbs);
547 AssertRC(rc2);
548 }
549 else
550 LogRel(("Clipboard: Error opening/creating guest file '%s' on host, rc=%Rrc\n", pszPathAbs, rc));
551 }
552 }
553 }
554#endif
555 break;
556 }
557
558 case VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_FILE_DATA:
559 {
560 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_READ_FILE_DATA\n"));
561 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_READ_FILE_DATA)
562 {
563 if (!SharedClipboardURICtxGetActiveTransfers(&pClientData->URI))
564 {
565 rc = VERR_WRONG_ORDER;
566 break;
567 }
568
569 VBOXCLIPBOARDFILEDATA data;
570 rc = VBoxClipboardSvcImplURIReadFileData(pClientData, &data);
571 if (RT_SUCCESS(rc))
572 {
573 /* Note: Context ID (paParms[0]) not used yet. */
574 HGCMSvcSetPv (&paParms[1], data.pvData, data.cbData);
575 HGCMSvcSetU32(&paParms[2], data.cbData);
576 HGCMSvcSetPv (&paParms[3], data.pvChecksum, data.cbChecksum);
577 HGCMSvcSetU32(&paParms[4], data.cbChecksum);
578
579 SharedClipboardURIFileDataDestroy(&data);
580 }
581 }
582 break;
583 }
584
585 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_FILE_DATA:
586 {
587 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_FILE_DATA\n"));
588
589 if (!SharedClipboardURICtxGetActiveTransfers(&pClientData->URI))
590 {
591 rc = VERR_WRONG_ORDER;
592 break;
593 }
594
595#if 0
596 if (RT_SUCCESS(rc))
597 {
598 if (!vboxSvcClipboardURIFileDataIsValid(&data, &pTransfer->Header))
599 rc = VERR_INVALID_PARAMETER;
600
601 if (!SharedClipboardURIObjCtxIsValid(&pTransfer->ObjCtx))
602 rc = VERR_WRONG_ORDER;
603 }
604
605 if (RT_SUCCESS(rc))
606 {
607 SharedClipboardURIObject *pObj = SharedClipboardURIObjCtxGetObj(&pTransfer->ObjCtx);
608 AssertPtrBreakStmt(pObj, VERR_INVALID_POINTER);
609
610 uint32_t cbWritten;
611 rc = pObj->Write(data.pvData, data.cbData, &cbWritten);
612 if (RT_SUCCESS(rc))
613 {
614 Assert(cbWritten <= data.cbData);
615 if (cbWritten < data.cbData)
616 {
617 /** @todo What to do when the host's disk is full? */
618 rc = VERR_DISK_FULL;
619 }
620
621 if ( pObj->IsComplete()
622 || RT_FAILURE(rc))
623 SharedClipboardURIObjCtxUninit(&pTransfer->ObjCtx);
624 }
625 else
626 LogRel(("Clipboard: Error writing guest file data for '%s', rc=%Rrc\n", pObj->GetDestPathAbs().c_str(), rc));
627 }
628#endif
629 break;
630 }
631
632 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_CANCEL:
633 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_CANCEL\n"));
634 AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED);
635 break;
636
637 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_ERROR:
638 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_ERROR\n"));
639 AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED);
640 break;
641
642 default:
643 AssertMsgFailed(("Not implemented\n"));
644 break;
645 }
646
647 LogFlowFuncLeaveRC(rc);
648 return rc;
649}
650
651/**
652 * URI host handler for the Shared Clipboard host service.
653 *
654 * @returns VBox status code.
655 * @param u32Function Function number being called.
656 * @param cParms Number of function parameters supplied.
657 * @param paParms Array function parameters supplied.
658 */
659int vboxSvcClipboardURIHostHandler(uint32_t u32Function,
660 uint32_t cParms,
661 VBOXHGCMSVCPARM paParms[])
662{
663 RT_NOREF(cParms, paParms);
664
665 int rc = VERR_INVALID_PARAMETER; /* Play safe. */
666
667 switch (u32Function)
668 {
669 case VBOX_SHARED_CLIPBOARD_HOST_FN_CANCEL:
670 AssertFailed(); /** @todo Implement this. */
671 break;
672
673 case VBOX_SHARED_CLIPBOARD_HOST_FN_ERROR:
674 AssertFailed(); /** @todo Implement this. */
675 break;
676
677 default:
678 AssertMsgFailed(("Not implemented\n"));
679 break;
680
681 }
682
683 LogFlowFuncLeaveRC(rc);
684 return rc;
685}
686
687/**
688 * Registers an URI clipboard area.
689 *
690 * @returns VBox status code.
691 * @param pClientState Client state to use.
692 * @param pTransfer URI transfer to register a clipboard area for.
693 */
694int vboxSvcClipboardURIAreaRegister(PVBOXCLIPBOARDCLIENTSTATE pClientState, PSHAREDCLIPBOARDURITRANSFER pTransfer)
695{
696 LogFlowFuncEnter();
697
698 AssertMsgReturn(pTransfer->pArea == NULL, ("An area already is registered for this transfer\n"),
699 VERR_WRONG_ORDER);
700
701 pTransfer->pArea = new SharedClipboardArea();
702 if (!pTransfer->pArea)
703 return VERR_NO_MEMORY;
704
705 VBOXCLIPBOARDEXTAREAPARMS parms;
706 RT_ZERO(parms);
707
708 parms.uID = NIL_SHAREDCLIPBOARDAREAID;
709 parms.u.fn_register.pvData = SharedClipboardMetaDataMutableRaw(&pTransfer->Cache.Meta);
710 parms.u.fn_register.cbData = (uint32_t)SharedClipboardMetaDataGetUsed(&pTransfer->Cache.Meta);
711
712 /* As the meta data is now complete, register a new clipboard on the host side. */
713 int rc = g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_AREA_REGISTER, &parms, sizeof(parms));
714 if (RT_SUCCESS(rc))
715 rc = pTransfer->pArea->OpenTemp(parms.uID /* Area ID */,
716 SHAREDCLIPBOARDAREA_OPEN_FLAGS_MUST_NOT_EXIST);
717
718 LogFlowFunc(("Registered new clipboard area (%RU32) by client %RU32 with rc=%Rrc\n",
719 parms.uID, pClientState->u32ClientID, rc));
720
721 LogFlowFuncLeaveRC(rc);
722 return rc;
723}
724
725/**
726 * Unregisters an URI clipboard area.
727 *
728 * @returns VBox status code.
729 * @param pClientState Client state to use.
730 * @param pTransfer URI transfer to unregister a clipboard area from.
731 */
732int vboxSvcClipboardURIAreaUnregister(PVBOXCLIPBOARDCLIENTSTATE pClientState, PSHAREDCLIPBOARDURITRANSFER pTransfer)
733{
734 LogFlowFuncEnter();
735
736 if (!pTransfer->pArea)
737 return VINF_SUCCESS;
738
739 VBOXCLIPBOARDEXTAREAPARMS parms;
740 RT_ZERO(parms);
741
742 parms.uID = pTransfer->pArea->GetID();
743
744 int rc = g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_AREA_UNREGISTER, &parms, sizeof(parms));
745 if (RT_SUCCESS(rc))
746 {
747 rc = pTransfer->pArea->Close();
748 if (RT_SUCCESS(rc))
749 {
750 delete pTransfer->pArea;
751 pTransfer->pArea = NULL;
752 }
753 }
754
755 LogFlowFunc(("Unregistered clipboard area (%RU32) by client %RU32 with rc=%Rrc\n",
756 parms.uID, pClientState->u32ClientID, rc));
757
758 LogFlowFuncLeaveRC(rc);
759 return rc;
760}
761
762/**
763 * Attaches to an existing (registered) URI clipboard area.
764 *
765 * @returns VBox status code.
766 * @param pClientState Client state to use.
767 * @param pTransfer URI transfer to attach a clipboard area to.
768 */
769int vboxSvcClipboardURIAreaAttach(PVBOXCLIPBOARDCLIENTSTATE pClientState, PSHAREDCLIPBOARDURITRANSFER pTransfer)
770{
771 LogFlowFuncEnter();
772
773 AssertMsgReturn(pTransfer->pArea == NULL, ("An area already is attached to this transfer\n"),
774 VERR_WRONG_ORDER);
775
776 pTransfer->pArea = new SharedClipboardArea();
777 if (!pTransfer->pArea)
778 return VERR_NO_MEMORY;
779
780 VBOXCLIPBOARDEXTAREAPARMS parms;
781 RT_ZERO(parms);
782
783 parms.uID = 0; /* 0 means most recent clipboard area. */
784
785 /* The client now needs to attach to the most recent clipboard area
786 * to keep a reference to it. The host does the actual book keeping / cleanup then.
787 *
788 * This might fail if the host does not have a most recent clipboard area (yet). */
789 int rc = g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_AREA_ATTACH, &parms, sizeof(parms));
790 if (RT_SUCCESS(rc))
791 rc = pTransfer->pArea->OpenTemp(parms.uID /* Area ID */);
792
793 LogFlowFunc(("Attached client %RU32 to clipboard area %RU32 with rc=%Rrc\n",
794 pClientState->u32ClientID, parms.uID, rc));
795
796 LogFlowFuncLeaveRC(rc);
797 return rc;
798}
799
800/**
801 * Detaches from an URI clipboard area.
802 *
803 * @returns VBox status code.
804 * @param pClientState Client state to use.
805 * @param pTransfer URI transfer to detach a clipboard area from.
806 */
807int vboxSvcClipboardURIAreaDetach(PVBOXCLIPBOARDCLIENTSTATE pClientState, PSHAREDCLIPBOARDURITRANSFER pTransfer)
808{
809 LogFlowFuncEnter();
810
811 if (!pTransfer->pArea)
812 return VINF_SUCCESS;
813
814 const uint32_t uAreaID = pTransfer->pArea->GetID();
815
816 VBOXCLIPBOARDEXTAREAPARMS parms;
817 RT_ZERO(parms);
818 parms.uID = uAreaID;
819
820 int rc = g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_AREA_DETACH, &parms, sizeof(parms));
821
822 LogFlowFunc(("Detached client %RU32 from clipboard area %RU32 with rc=%Rrc\n",
823 pClientState->u32ClientID, uAreaID, rc));
824
825 LogFlowFuncLeaveRC(rc);
826 return rc;
827}
828
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