VirtualBox

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

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