VirtualBox

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

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