VirtualBox

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

Last change on this file since 79267 was 79267, 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.8 KB
Line 
1/* $Id: VBoxSharedClipboardSvc-uri.cpp 79267 2019-06-21 10:11:59Z 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 HCGCM 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 RT_BREAKPOINT();
469
470 char pszPathAbs[RTPATH_MAX];
471 rc = RTPathJoin(pszPathAbs, sizeof(pszPathAbs), pszCacheDir, fileHdr.pszFilePath);
472 if (RT_SUCCESS(rc))
473 {
474 rc = SharedClipboardPathSanitize(pszPathAbs, sizeof(pszPathAbs));
475 if (RT_SUCCESS(rc))
476 {
477 PSHAREDCLIPBOARDCLIENTURIOBJCTX pObjCtx = SharedClipboardURITransferGetCurrentObjCtx(pTransfer);
478 AssertPtrBreakStmt(pObjCtx, VERR_INVALID_POINTER);
479
480 SharedClipboardURIObject *pObj = pObjCtx->pObj;
481 AssertPtrBreakStmt(pObj, VERR_INVALID_POINTER);
482
483 LogFlowFunc(("pszFile=%s\n", pszPathAbs));
484
485 /** @todo Add sparse file support based on fFlags? (Use Open(..., fFlags | SPARSE). */
486 rc = pObj->OpenFileEx(pszPathAbs, SharedClipboardURIObject::View_Target,
487 RTFILE_O_CREATE_REPLACE | RTFILE_O_WRITE | RTFILE_O_DENY_WRITE,
488 (fileHdr.fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR);
489 if (RT_SUCCESS(rc))
490 {
491 rc = pObj->SetSize(fileHdr.cbSize);
492
493 /** @todo Unescape path before printing. */
494 LogRel2(("Clipboard: Transferring guest file '%s' to host (%RU64 bytes, mode 0x%x)\n",
495 pObj->GetDestPathAbs().c_str(), pObj->GetSize(), pObj->GetMode()));
496
497 if (pObj->IsComplete()) /* 0-byte file? We're done already. */
498 {
499 /** @todo Sanitize path. */
500 LogRel2(("Clipboard: Transferring guest file '%s' (0 bytes) to host complete\n",
501 pObj->GetDestPathAbs().c_str()));
502
503 SharedClipboardURIObjCtxDestroy(&pTransfer->ObjCtx);
504 }
505
506 /* Add for having a proper rollback. */
507 int rc2 = pArea->AddFile(pszPathAbs);
508 AssertRC(rc2);
509 }
510 else
511 LogRel(("Clipboard: Error opening/creating guest file '%s' on host, rc=%Rrc\n", pszPathAbs, rc));
512 }
513 }
514 }
515 break;
516 }
517
518 case VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_FILE_DATA:
519 {
520 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_READ_FILE_DATA\n"));
521 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_READ_FILE_DATA)
522 {
523 if (!SharedClipboardURICtxGetActiveTransfers(&pClientData->URI))
524 {
525 rc = VERR_WRONG_ORDER;
526 break;
527 }
528
529 VBOXCLIPBOARDFILEDATA data;
530 rc = VBoxClipboardSvcImplURIReadFileData(pClientData, &data);
531 if (RT_SUCCESS(rc))
532 {
533 /* Note: Context ID (paParms[0]) not used yet. */
534 HGCMSvcSetPv (&paParms[1], data.pvData, data.cbData);
535 HGCMSvcSetU32(&paParms[2], data.cbData);
536 HGCMSvcSetPv (&paParms[3], data.pvChecksum, data.cbChecksum);
537 HGCMSvcSetU32(&paParms[4], data.cbChecksum);
538
539 SharedClipboardURIFileDataDestroy(&data);
540 }
541 }
542 break;
543 }
544
545 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_FILE_DATA:
546 {
547 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_FILE_DATA\n"));
548
549 if (!SharedClipboardURIObjCtxIsValid(&pTransfer->ObjCtx))
550 {
551 rc = VERR_WRONG_ORDER;
552 break;
553 }
554
555 VBOXCLIPBOARDFILEDATA fileData;
556 rc = VBoxSvcClipboardURIReadFileData(cParms, paParms, &fileData);
557 if (RT_SUCCESS(rc))
558 {
559 PSHAREDCLIPBOARDCLIENTURIOBJCTX pObjCtx = SharedClipboardURITransferGetCurrentObjCtx(pTransfer);
560 AssertPtrBreakStmt(pObjCtx, VERR_INVALID_POINTER);
561
562 SharedClipboardURIObject *pObj = pObjCtx->pObj;
563 AssertPtrBreakStmt(pObj, VERR_INVALID_POINTER);
564
565 uint32_t cbWritten;
566 rc = pObj->Write(fileData.pvData, fileData.cbData, &cbWritten);
567 if (RT_SUCCESS(rc))
568 {
569 Assert(cbWritten <= fileData.cbData);
570 if (cbWritten < fileData.cbData)
571 {
572 /** @todo What to do when the host's disk is full? */
573 rc = VERR_DISK_FULL;
574 }
575
576 if ( pObj->IsComplete()
577 || RT_FAILURE(rc))
578 SharedClipboardURIObjCtxDestroy(&pTransfer->ObjCtx);
579 }
580 else
581 LogRel(("Clipboard: Error writing guest file data for '%s', rc=%Rrc\n", pObj->GetDestPathAbs().c_str(), rc));
582 }
583 break;
584 }
585
586 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_CANCEL:
587 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_CANCEL\n"));
588 AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED);
589 break;
590
591 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_ERROR:
592 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_ERROR\n"));
593 AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED);
594 break;
595
596 default:
597 AssertMsgFailed(("Not implemented\n"));
598 break;
599 }
600
601 if (fDispatchToProvider)
602 rc = VINF_SUCCESS;
603
604 if (RT_SUCCESS(rc))
605 {
606 if (fDispatchToProvider)
607 {
608 SHAREDCLIPBOARDPROVIDERWRITEPARMS writeParms;
609 RT_ZERO(writeParms);
610
611 writeParms.u.HostService.uMsg = u32Function;
612 writeParms.u.HostService.cParms = cParms;
613 writeParms.u.HostService.paParms = paParms;
614
615 rc = pTransfer->pProvider->OnWrite(&writeParms);
616 }
617 }
618
619 LogFlowFuncLeaveRC(rc);
620 return rc;
621}
622
623/**
624 * URI host handler for the Shared Clipboard host service.
625 *
626 * @returns VBox status code.
627 * @param u32Function Function number being called.
628 * @param cParms Number of function parameters supplied.
629 * @param paParms Array function parameters supplied.
630 */
631int vboxSvcClipboardURIHostHandler(uint32_t u32Function,
632 uint32_t cParms,
633 VBOXHGCMSVCPARM paParms[])
634{
635 RT_NOREF(cParms, paParms);
636
637 int rc = VERR_INVALID_PARAMETER; /* Play safe. */
638
639 switch (u32Function)
640 {
641 case VBOX_SHARED_CLIPBOARD_HOST_FN_CANCEL:
642 AssertFailed(); /** @todo Implement this. */
643 break;
644
645 case VBOX_SHARED_CLIPBOARD_HOST_FN_ERROR:
646 AssertFailed(); /** @todo Implement this. */
647 break;
648
649 default:
650 AssertMsgFailed(("Not implemented\n"));
651 break;
652
653 }
654
655 LogFlowFuncLeaveRC(rc);
656 return rc;
657}
658
659/**
660 * Registers an URI clipboard area.
661 *
662 * @returns VBox status code.
663 * @param pClientState Client state to use.
664 * @param pTransfer URI transfer to register a clipboard area for.
665 */
666int vboxSvcClipboardURIAreaRegister(PVBOXCLIPBOARDCLIENTSTATE pClientState, PSHAREDCLIPBOARDURITRANSFER pTransfer)
667{
668 LogFlowFuncEnter();
669
670 AssertMsgReturn(pTransfer->pArea == NULL, ("An area already is registered for this transfer\n"),
671 VERR_WRONG_ORDER);
672
673 pTransfer->pArea = new SharedClipboardArea();
674 if (!pTransfer->pArea)
675 return VERR_NO_MEMORY;
676
677 int rc;
678
679 if (g_pfnExtension)
680 {
681 VBOXCLIPBOARDEXTAREAPARMS parms;
682 RT_ZERO(parms);
683
684 parms.uID = NIL_SHAREDCLIPBOARDAREAID;
685
686 if (pTransfer->State.pMeta)
687 {
688 parms.u.fn_register.pvData = SharedClipboardMetaDataMutableRaw(pTransfer->State.pMeta);
689 parms.u.fn_register.cbData = (uint32_t)SharedClipboardMetaDataGetUsed(pTransfer->State.pMeta);
690 }
691
692 /* As the meta data is now complete, register a new clipboard on the host side. */
693 rc = g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_AREA_REGISTER, &parms, sizeof(parms));
694 if (RT_SUCCESS(rc))
695 {
696 /* Note: Do *not* specify SHAREDCLIPBOARDAREA_OPEN_FLAGS_MUST_NOT_EXIST as flags here, as VBoxSVC took care of the
697 * clipboard area creation already. */
698 rc = pTransfer->pArea->OpenTemp(parms.uID /* Area ID */,
699 SHAREDCLIPBOARDAREA_OPEN_FLAGS_NONE);
700 }
701
702 LogFlowFunc(("Registered new clipboard area (%RU32) by client %RU32 with rc=%Rrc\n",
703 parms.uID, pClientState->u32ClientID, rc));
704 }
705 else
706 rc = VERR_NOT_SUPPORTED;
707
708 LogFlowFuncLeaveRC(rc);
709 return rc;
710}
711
712/**
713 * Unregisters an URI clipboard area.
714 *
715 * @returns VBox status code.
716 * @param pClientState Client state to use.
717 * @param pTransfer URI transfer to unregister a clipboard area from.
718 */
719int vboxSvcClipboardURIAreaUnregister(PVBOXCLIPBOARDCLIENTSTATE pClientState, PSHAREDCLIPBOARDURITRANSFER pTransfer)
720{
721 LogFlowFuncEnter();
722
723 if (!pTransfer->pArea)
724 return VINF_SUCCESS;
725
726 int rc = VINF_SUCCESS;
727
728 if (g_pfnExtension)
729 {
730 VBOXCLIPBOARDEXTAREAPARMS parms;
731 RT_ZERO(parms);
732
733 parms.uID = pTransfer->pArea->GetID();
734
735 rc = g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_AREA_UNREGISTER, &parms, sizeof(parms));
736 if (RT_SUCCESS(rc))
737 {
738 rc = pTransfer->pArea->Close();
739 if (RT_SUCCESS(rc))
740 {
741 delete pTransfer->pArea;
742 pTransfer->pArea = NULL;
743 }
744 }
745
746 LogFlowFunc(("Unregistered clipboard area (%RU32) by client %RU32 with rc=%Rrc\n",
747 parms.uID, pClientState->u32ClientID, rc));
748 }
749
750 delete pTransfer->pArea;
751 pTransfer->pArea = NULL;
752
753 LogFlowFuncLeaveRC(rc);
754 return rc;
755}
756
757/**
758 * Attaches to an existing (registered) URI clipboard area.
759 *
760 * @returns VBox status code.
761 * @param pClientState Client state to use.
762 * @param pTransfer URI transfer to attach a clipboard area to.
763 */
764int vboxSvcClipboardURIAreaAttach(PVBOXCLIPBOARDCLIENTSTATE pClientState, PSHAREDCLIPBOARDURITRANSFER pTransfer)
765{
766 LogFlowFuncEnter();
767
768 AssertMsgReturn(pTransfer->pArea == NULL, ("An area already is attached to this transfer\n"),
769 VERR_WRONG_ORDER);
770
771 pTransfer->pArea = new SharedClipboardArea();
772 if (!pTransfer->pArea)
773 return VERR_NO_MEMORY;
774
775 int rc = VINF_SUCCESS;
776
777 if (g_pfnExtension)
778 {
779 VBOXCLIPBOARDEXTAREAPARMS parms;
780 RT_ZERO(parms);
781
782 parms.uID = 0; /* 0 means most recent clipboard area. */
783
784 /* The client now needs to attach to the most recent clipboard area
785 * to keep a reference to it. The host does the actual book keeping / cleanup then.
786 *
787 * This might fail if the host does not have a most recent clipboard area (yet). */
788 rc = g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_AREA_ATTACH, &parms, sizeof(parms));
789 if (RT_SUCCESS(rc))
790 rc = pTransfer->pArea->OpenTemp(parms.uID /* Area ID */);
791
792 LogFlowFunc(("Attached client %RU32 to clipboard area %RU32 with rc=%Rrc\n",
793 pClientState->u32ClientID, parms.uID, rc));
794 }
795 else
796 rc = VERR_NOT_SUPPORTED;
797
798 LogFlowFuncLeaveRC(rc);
799 return rc;
800}
801
802/**
803 * Detaches from an URI clipboard area.
804 *
805 * @returns VBox status code.
806 * @param pClientState Client state to use.
807 * @param pTransfer URI transfer to detach a clipboard area from.
808 */
809int vboxSvcClipboardURIAreaDetach(PVBOXCLIPBOARDCLIENTSTATE pClientState, PSHAREDCLIPBOARDURITRANSFER pTransfer)
810{
811 LogFlowFuncEnter();
812
813 if (!pTransfer->pArea)
814 return VINF_SUCCESS;
815
816 const uint32_t uAreaID = pTransfer->pArea->GetID();
817
818 int rc = VINF_SUCCESS;
819
820 if (g_pfnExtension)
821 {
822 VBOXCLIPBOARDEXTAREAPARMS parms;
823 RT_ZERO(parms);
824 parms.uID = uAreaID;
825
826 rc = g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_AREA_DETACH, &parms, sizeof(parms));
827
828 LogFlowFunc(("Detached client %RU32 from clipboard area %RU32 with rc=%Rrc\n",
829 pClientState->u32ClientID, uAreaID, rc));
830 }
831
832 delete pTransfer->pArea;
833 pTransfer->pArea = NULL;
834
835 LogFlowFuncLeaveRC(rc);
836 return rc;
837}
838
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette