VirtualBox

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

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