VirtualBox

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

Last change on this file since 79347 was 79347, 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.1 KB
Line 
1/* $Id: VBoxSharedClipboardSvc-uri.cpp 79347 2019-06-26 09:15:29Z 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
45static DECLCALLBACK(int) vboxSvcClipboardURIProviderImplReadDataHdr(PSHAREDCLIPBOARDPROVIDERCTX pCtx,
46 PVBOXCLIPBOARDDATAHDR *ppDataHdr)
47{
48 RT_NOREF(pCtx, ppDataHdr);
49 return VERR_NOT_IMPLEMENTED;
50}
51
52static DECLCALLBACK(int) vboxSvcClipboardURIProviderImplReadObjHdr(PSHAREDCLIPBOARDPROVIDERCTX pCtx,
53 PVBOXCLIPBOARDDATAHDR *ppDataHdr)
54{
55 RT_NOREF(pCtx, ppDataHdr);
56 return VERR_NOT_IMPLEMENTED;
57}
58
59static DECLCALLBACK(int) vboxSvcClipboardURIProviderImplReadDir(PSHAREDCLIPBOARDPROVIDERCTX pCtx,
60 PVBOXCLIPBOARDDIRDATA *ppDirData)
61{
62 RT_NOREF(pCtx, ppDirData);
63 return VERR_NOT_IMPLEMENTED;
64}
65
66static DECLCALLBACK(int) vboxSvcClipboardURIProviderImplReadFileHdr(PSHAREDCLIPBOARDPROVIDERCTX pCtx,
67 PVBOXCLIPBOARDFILEHDR *ppFileHdr)
68{
69 RT_NOREF(pCtx, ppFileHdr);
70 return VERR_NOT_IMPLEMENTED;
71}
72
73static DECLCALLBACK(int) vboxSvcClipboardURIProviderImplReadFileData(PSHAREDCLIPBOARDPROVIDERCTX pCtX,
74 void *pvData, uint32_t cbData, uint32_t fFlags,
75 uint32_t *pcbRead)
76{
77#if 0
78 const PVBOXCLIPBOARDCLIENTDATA pClientData = (PVBOXCLIPBOARDCLIENTDATA)pCtx->pvUser;
79
80 return pObjCtx->pObj->Read(pvBuf, cbBuf, pcbWritten);
81#endif
82
83 RT_NOREF(pCtX, pvData, cbData, fFlags, pcbRead);
84 return VERR_NOT_IMPLEMENTED;
85}
86
87#if 0
88int vboxSvcClipboardURIAnnounce(uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
89{
90 Provider.pfnReadDataHdr = vboxSvcClipboardURIProviderImplReadDataHdr;
91 Provider.pfnReadDataChunk = vboxSvcClipboardURIProviderImplReadDataChunk;
92 Provider.pfnReadDir = vboxSvcClipboardURIProviderImplReadDir;
93 Provider.pfnReadFileHdr = vboxSvcClipboardURIProviderImplReadFileHdr;
94 Provider.pfnReadFileData = vboxSvcClipboardURIProviderImplReadFileData;
95
96 Provider.pvUser =
97
98 SharedClipboardURITransferSetProvider(&Provider);
99
100 return rc;
101}
102#endif
103
104/**
105 * Gets an URI data header from HGCM service parameters.
106 *
107 * @returns VBox status code.
108 * @param cParms Number of HGCM parameters supplied in \a paParms.
109 * @param paParms Array of HGCM parameters.
110 * @param pDataHdr Where to store the result.
111 */
112int VBoxSvcClipboardURIGetDataHdr(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDDATAHDR pDataHdr)
113{
114 int rc;
115
116 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_DATA_HDR)
117 {
118 /* Note: Context ID (paParms[0]) not used yet. */
119 rc = HGCMSvcGetU32(&paParms[1], &pDataHdr->uFlags);
120 if (RT_SUCCESS(rc))
121 rc = HGCMSvcGetU32(&paParms[2], &pDataHdr->uScreenId);
122 if (RT_SUCCESS(rc))
123 rc = HGCMSvcGetU64(&paParms[3], &pDataHdr->cbTotal);
124 if (RT_SUCCESS(rc))
125 rc = HGCMSvcGetU32(&paParms[4], &pDataHdr->cbMeta);
126 if (RT_SUCCESS(rc))
127 rc = HGCMSvcGetU32(&paParms[5], &pDataHdr->cbMetaFmt);
128 if (RT_SUCCESS(rc))
129 rc = HGCMSvcGetPv(&paParms[6], &pDataHdr->pvMetaFmt, &pDataHdr->cbMetaFmt);
130 if (RT_SUCCESS(rc))
131 rc = HGCMSvcGetU64(&paParms[7], &pDataHdr->cObjects);
132 if (RT_SUCCESS(rc))
133 rc = HGCMSvcGetU32(&paParms[8], &pDataHdr->enmCompression);
134 if (RT_SUCCESS(rc))
135 rc = HGCMSvcGetU32(&paParms[9], (uint32_t *)&pDataHdr->enmChecksumType);
136 if (RT_SUCCESS(rc))
137 rc = HGCMSvcGetU32(&paParms[10], &pDataHdr->cbChecksum);
138 if (RT_SUCCESS(rc))
139 rc = HGCMSvcGetPv(&paParms[11], &pDataHdr->pvChecksum, &pDataHdr->cbChecksum);
140
141 LogFlowFunc(("fFlags=0x%x, cbMeta=%RU32, cbTotalSize=%RU64, cObj=%RU64\n",
142 pDataHdr->uFlags, pDataHdr->cbMeta, pDataHdr->cbTotal, pDataHdr->cObjects));
143
144 if (RT_SUCCESS(rc))
145 {
146 /** @todo Validate pvMetaFmt + cbMetaFmt. */
147 /** @todo Validate header checksum. */
148 }
149 }
150 else
151 rc = VERR_INVALID_PARAMETER;
152
153 LogFlowFuncLeaveRC(rc);
154 return rc;
155}
156
157/**
158 * Sets an URI data header to HGCM service parameters.
159 *
160 * @returns VBox status code.
161 * @param cParms Number of HGCM parameters supplied in \a paParms.
162 * @param paParms Array of HGCM parameters.
163 * @param pDataHdr Pointer to data to set to the HGCM parameters.
164 */
165int VBoxSvcClipboardURISetDataHdr(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDDATAHDR pDataHdr)
166{
167 int rc;
168
169 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_READ_DATA_HDR)
170 {
171 /** @todo Set pvMetaFmt + cbMetaFmt. */
172 /** @todo Calculate header checksum. */
173
174 /* Note: Context ID (paParms[0]) not used yet. */
175 HGCMSvcSetU32(&paParms[1], pDataHdr->uFlags);
176 HGCMSvcSetU32(&paParms[2], pDataHdr->uScreenId);
177 HGCMSvcSetU64(&paParms[3], pDataHdr->cbTotal);
178 HGCMSvcSetU32(&paParms[4], pDataHdr->cbMeta);
179 HGCMSvcSetU32(&paParms[5], pDataHdr->cbMetaFmt);
180 HGCMSvcSetPv (&paParms[6], pDataHdr->pvMetaFmt, pDataHdr->cbMetaFmt);
181 HGCMSvcSetU64(&paParms[7], pDataHdr->cObjects);
182 HGCMSvcSetU32(&paParms[8], pDataHdr->enmCompression);
183 HGCMSvcSetU32(&paParms[9], (uint32_t)pDataHdr->enmChecksumType);
184 HGCMSvcSetU32(&paParms[10], pDataHdr->cbChecksum);
185 HGCMSvcSetPv (&paParms[11], pDataHdr->pvChecksum, pDataHdr->cbChecksum);
186
187 LogFlowFunc(("fFlags=0x%x, cbMeta=%RU32, cbTotalSize=%RU64, cObj=%RU64\n",
188 pDataHdr->uFlags, pDataHdr->cbMeta, pDataHdr->cbTotal, pDataHdr->cObjects));
189
190 rc = VINF_SUCCESS;
191 }
192 else
193 rc = VERR_INVALID_PARAMETER;
194
195 LogFlowFuncLeaveRC(rc);
196 return rc;
197}
198
199/**
200 * Gets an URI data chunk from HGCM service parameters.
201 *
202 * @returns VBox status code.
203 * @param cParms Number of HGCM parameters supplied in \a paParms.
204 * @param paParms Array of HGCM parameters.
205 * @param pDataChunk Where to store the result.
206 */
207int VBoxSvcClipboardURIGetDataChunk(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDDATACHUNK pDataChunk)
208{
209 int rc;
210
211 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_DATA_CHUNK)
212 {
213 /* Note: Context ID (paParms[0]) not used yet. */
214 rc = HGCMSvcGetU32(&paParms[1], &pDataChunk->cbData);
215 if (RT_SUCCESS(rc))
216 rc = HGCMSvcGetPv(&paParms[2], &pDataChunk->pvData, &pDataChunk->cbData);
217 if (RT_SUCCESS(rc))
218 rc = HGCMSvcGetU32(&paParms[3], &pDataChunk->cbChecksum);
219 if (RT_SUCCESS(rc))
220 rc = HGCMSvcGetPv(&paParms[4], &pDataChunk->pvChecksum, &pDataChunk->cbChecksum);
221
222 if (RT_SUCCESS(rc))
223 {
224 if (!SharedClipboardURIDataChunkIsValid(pDataChunk))
225 rc = VERR_INVALID_PARAMETER;
226 }
227 }
228 else
229 rc = VERR_INVALID_PARAMETER;
230
231 LogFlowFuncLeaveRC(rc);
232 return rc;
233}
234
235/**
236 * Sets an URI data chunk to HGCM service parameters.
237 *
238 * @returns VBox status code.
239 * @param cParms Number of HGCM parameters supplied in \a paParms.
240 * @param paParms Array of HGCM parameters.
241 * @param pDataChunk Pointer to data to set to the HGCM parameters.
242 */
243int VBoxSvcClipboardURISetDataChunk(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDDATACHUNK pDataChunk)
244{
245 int rc;
246
247 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_READ_DATA_CHUNK)
248 {
249 /** @todo Calculate chunk checksum. */
250
251 /* Note: Context ID (paParms[0]) not used yet. */
252 HGCMSvcSetU32(&paParms[1], pDataChunk->cbData);
253 HGCMSvcSetPv (&paParms[2], pDataChunk->pvData, pDataChunk->cbData);
254 HGCMSvcSetU32(&paParms[3], pDataChunk->cbChecksum);
255 HGCMSvcSetPv (&paParms[4], pDataChunk->pvChecksum, pDataChunk->cbChecksum);
256
257 rc = VINF_SUCCESS;
258 }
259 else
260 rc = VERR_INVALID_PARAMETER;
261
262 LogFlowFuncLeaveRC(rc);
263 return rc;
264}
265
266/**
267 * Gets an URI directory entry from HGCM service parameters.
268 *
269 * @returns VBox status code.
270 * @param cParms Number of HGCM parameters supplied in \a paParms.
271 * @param paParms Array of HGCM parameters.
272 * @param pDirData Where to store the result.
273 */
274int VBoxSvcClipboardURIGetDir(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDDIRDATA pDirData)
275{
276 int rc;
277
278 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_DIR)
279 {
280 /* Note: Context ID (paParms[0]) not used yet. */
281 rc = HGCMSvcGetU32(&paParms[1], &pDirData->cbPath);
282 if (RT_SUCCESS(rc))
283 rc = HGCMSvcGetPv(&paParms[2], (void **)&pDirData->pszPath, &pDirData->cbPath);
284 if (RT_SUCCESS(rc))
285 rc = HGCMSvcGetU32(&paParms[3], &pDirData->fMode);
286
287 LogFlowFunc(("pszPath=%s, cbPath=%RU32, fMode=0x%x\n", pDirData->pszPath, pDirData->cbPath, pDirData->fMode));
288
289 if (RT_SUCCESS(rc))
290 {
291 if (!SharedClipboardURIDirDataIsValid(pDirData))
292 rc = VERR_INVALID_PARAMETER;
293 }
294 }
295 else
296 rc = VERR_INVALID_PARAMETER;
297
298 LogFlowFuncLeaveRC(rc);
299 return rc;
300}
301
302/**
303 * Sets an URI directory entry to HGCM service parameters.
304 *
305 * @returns VBox status code.
306 * @param cParms Number of HGCM parameters supplied in \a paParms.
307 * @param paParms Array of HGCM parameters.
308 * @param pDirData Pointer to data to set to the HGCM parameters.
309 */
310int VBoxSvcClipboardURISetDir(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDDIRDATA pDirData)
311{
312 int rc;
313
314 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_READ_DIR)
315 {
316 /* Note: Context ID (paParms[0]) not used yet. */
317 HGCMSvcSetU32(&paParms[1], pDirData->cbPath);
318 HGCMSvcSetPv (&paParms[2], pDirData->pszPath, pDirData->cbPath);
319 HGCMSvcSetU32(&paParms[3], pDirData->fMode);
320
321 rc = VINF_SUCCESS;
322 }
323 else
324 rc = VERR_INVALID_PARAMETER;
325
326 LogFlowFuncLeaveRC(rc);
327 return rc;
328}
329
330/**
331 * Reads an URI file header from HGCM service parameters.
332 *
333 * @returns VBox status code.
334 * @param cParms Number of HGCM parameters supplied in \a paParms.
335 * @param paParms Array of HGCM parameters.
336 * @param pFileHdr Where to store the result.
337 */
338int VBoxSvcClipboardURIGetFileHdr(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDFILEHDR pFileHdr)
339{
340 int rc;
341
342 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_FILE_HDR)
343 {
344 /* Note: Context ID (paParms[0]) not used yet. */
345 rc = HGCMSvcGetU32(&paParms[1], &pFileHdr->cbFilePath);
346 if (RT_SUCCESS(rc))
347 rc = HGCMSvcGetPv(&paParms[2], (void **)&pFileHdr->pszFilePath, &pFileHdr->cbFilePath);
348 if (RT_SUCCESS(rc))
349 rc = HGCMSvcGetU32(&paParms[3], &pFileHdr->fFlags);
350 if (RT_SUCCESS(rc))
351 rc = HGCMSvcGetU32(&paParms[4], &pFileHdr->fMode);
352 if (RT_SUCCESS(rc))
353 rc = HGCMSvcGetU64(&paParms[5], &pFileHdr->cbSize);
354
355 LogFlowFunc(("pszPath=%s, cbPath=%RU32, fMode=0x%x, cbSize=%RU64\n",
356 pFileHdr->pszFilePath, pFileHdr->cbFilePath, pFileHdr->fMode, pFileHdr->cbSize));
357 }
358 else
359 rc = VERR_INVALID_PARAMETER;
360
361 LogFlowFuncLeaveRC(rc);
362 return rc;
363}
364
365/**
366 * Sets an URI file header to HGCM service parameters.
367 *
368 * @returns VBox status code.
369 * @param cParms Number of HGCM parameters supplied in \a paParms.
370 * @param paParms Array of HGCM parameters.
371 * @param pFileHdr Pointer to data to set to the HGCM parameters.
372 */
373int VBoxSvcClipboardURISetFileHdr(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDFILEHDR pFileHdr)
374{
375 int rc;
376
377 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_READ_FILE_HDR)
378 {
379 /* Note: Context ID (paParms[0]) not used yet. */
380 HGCMSvcSetU32(&paParms[1], pFileHdr->cbFilePath);
381 HGCMSvcSetPv (&paParms[2], pFileHdr->pszFilePath, pFileHdr->cbFilePath);
382 HGCMSvcSetU32(&paParms[3], pFileHdr->fFlags);
383 HGCMSvcSetU32(&paParms[4], pFileHdr->fMode);
384 HGCMSvcSetU64(&paParms[5], pFileHdr->cbSize);
385
386 rc = VINF_SUCCESS;
387 }
388 else
389 rc = VERR_INVALID_PARAMETER;
390
391 LogFlowFuncLeaveRC(rc);
392 return rc;
393}
394
395/**
396 * Gets an URI file data chunk from HGCM service parameters.
397 *
398 * @returns VBox status code.
399 * @param cParms Number of HGCM parameters supplied in \a paParms.
400 * @param paParms Array of HGCM parameters.
401 * @param pFileData Where to store the result.
402 */
403int VBoxSvcClipboardURIGetFileData(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDFILEDATA pFileData)
404{
405 int rc;
406
407 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_FILE_DATA)
408 {
409 /* Note: Context ID (paParms[0]) not used yet. */
410 rc = HGCMSvcGetU32(&paParms[1], &pFileData->cbData);
411 if (RT_SUCCESS(rc))
412 rc = HGCMSvcGetPv(&paParms[2], &pFileData->pvData, &pFileData->cbData);
413 if (RT_SUCCESS(rc))
414 rc = HGCMSvcGetU32(&paParms[3], &pFileData->cbChecksum);
415 if (RT_SUCCESS(rc))
416 rc = HGCMSvcGetPv(&paParms[4], &pFileData->pvChecksum, &pFileData->cbChecksum);
417
418 LogFlowFunc(("pvData=0x%p, cbData=%RU32\n", pFileData->pvData, pFileData->cbData));
419 }
420 else
421 rc = VERR_INVALID_PARAMETER;
422
423 LogFlowFuncLeaveRC(rc);
424 return rc;
425}
426
427/**
428 * Sets an URI file data chunk to HGCM service parameters.
429 *
430 * @returns VBox status code.
431 * @param cParms Number of HGCM parameters supplied in \a paParms.
432 * @param paParms Array of HGCM parameters.
433 * @param pFileData Pointer to data to set to the HGCM parameters.
434 */
435int VBoxSvcClipboardURISetFileData(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDFILEDATA pFileData)
436{
437 int rc;
438
439 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_READ_FILE_DATA)
440 {
441 /* Note: Context ID (paParms[0]) not used yet. */
442 HGCMSvcSetU32(&paParms[1], pFileData->cbData);
443 HGCMSvcSetPv (&paParms[2], pFileData->pvData, pFileData->cbData);
444 HGCMSvcSetU32(&paParms[3], pFileData->cbChecksum);
445 HGCMSvcSetPv (&paParms[4], pFileData->pvChecksum, pFileData->cbChecksum);
446
447 rc = VINF_SUCCESS;
448 }
449 else
450 rc = VERR_INVALID_PARAMETER;
451
452 LogFlowFuncLeaveRC(rc);
453 return rc;
454}
455
456/**
457 * URI client (guest) handler for the Shared Clipboard host service.
458 *
459 * @returns VBox status code.
460 * @param u32ClientID Client ID of the client which called this handler.
461 * @param pvClient Pointer to client-specific data block.
462 * @param u32Function Function number being called.
463 * @param cParms Number of function parameters supplied.
464 * @param paParms Array function parameters supplied.
465 * @param tsArrival Timestamp of arrival.
466 * @param pfAsync Returns \c true if the response needs to be being asynchronous or \c false if not,
467 */
468int vboxSvcClipboardURIHandler(uint32_t u32ClientID,
469 void *pvClient,
470 uint32_t u32Function,
471 uint32_t cParms,
472 VBOXHGCMSVCPARM paParms[],
473 uint64_t tsArrival,
474 bool *pfAsync)
475{
476 RT_NOREF(u32ClientID, paParms, tsArrival, pfAsync);
477
478 LogFlowFunc(("u32ClientID=%RU32, u32Function=%RU32, cParms=%RU32, g_pfnExtension=%p\n",
479 u32ClientID, u32Function, cParms, g_pfnExtension));
480
481 const PVBOXCLIPBOARDCLIENTDATA pClientData = (PVBOXCLIPBOARDCLIENTDATA)pvClient;
482 AssertPtrReturn(pClientData, VERR_INVALID_POINTER);
483
484 /* Check if we've the right mode set. */
485 if (!vboxSvcClipboardURIMsgIsAllowed(vboxSvcClipboardGetMode(), u32Function))
486 return VERR_ACCESS_DENIED;
487
488 /* A (valid) service extension is needed because VBoxSVC needs to keep track of the
489 * clipboard areas cached on the host. */
490 if (!g_pfnExtension)
491 {
492#ifdef DEBUG_andy
493 AssertPtr(g_pfnExtension);
494#endif
495 LogFunc(("Invalid / no service extension set, skipping URI handling\n"));
496 return VERR_NOT_SUPPORTED;
497 }
498
499 if (!SharedClipboardURICtxGetRunningTransfers(&pClientData->URI))
500 {
501 LogFunc(("No running transfers found\n"));
502 return VERR_WRONG_ORDER;
503 }
504
505 const uint32_t uTransferID = 0; /* Only one transfer is supported at the moment. */
506
507 const PSHAREDCLIPBOARDURITRANSFER pTransfer = SharedClipboardURICtxGetTransfer(&pClientData->URI, uTransferID);
508 if (!pTransfer)
509 {
510 LogFunc(("Transfer with ID %RU32 not found\n", uTransferID));
511 return VERR_WRONG_ORDER;
512 }
513
514 bool fWriteToProvider = false; /* Whether to (also) dispatch the HGCM data to the transfer provider. */
515
516 int rc = VERR_INVALID_PARAMETER; /* Play safe. */
517
518 switch (u32Function)
519 {
520 case VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_DATA_HDR:
521 {
522 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_DATA_HDR\n"));
523
524 VBOXCLIPBOARDDATAHDR dataHdr;
525 rc = VBoxSvcClipboardURISetDataHdr(cParms, paParms, &dataHdr);
526 break;
527 }
528
529 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DATA_HDR:
530 {
531 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DATA_HDR\n"));
532
533 VBOXCLIPBOARDDATAHDR dataHdr;
534 rc = SharedClipboardURIDataHdrInit(&dataHdr);
535 if (RT_SUCCESS(rc))
536 rc = VBoxSvcClipboardURIGetDataHdr(cParms, paParms, &dataHdr);
537 /*if (RT_SUCCESS(rc))
538 rc = SharedClipboardURITransferSetDataHeader(&dataHdr);*/
539 break;
540 }
541
542 case VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_DATA_CHUNK:
543 {
544 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_DATA_CHUNK\n"));
545 break;
546 }
547
548 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DATA_CHUNK:
549 {
550 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DATA_CHUNK\n"));
551
552 VBOXCLIPBOARDDATACHUNK dataChunk;
553 rc = SharedClipboardURIDataChunkInit(&dataChunk);
554 if (RT_SUCCESS(rc))
555 rc = VBoxSvcClipboardURIGetDataChunk(cParms, paParms, &dataChunk);
556 #if 0
557 if (RT_SUCCESS(rc))
558 {
559 VBOXCLIPBOARDTRANSFEREVENT Event = { &dataChunk, sizeof(dataChunk) };
560 rc = SharedClipboardURITransferSendEvent(WRITE_DATA_CHUNK, &Event);
561 }
562 #endif
563 break;
564 }
565
566 case VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_DIR:
567 {
568 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_DIR\n"));
569
570 VBOXCLIPBOARDDIRDATA data;
571 rc = VBoxSvcClipboardURISetDir(cParms, paParms, &data);
572 break;
573 }
574
575 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DIR:
576 {
577 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DIR\n"));
578
579 VBOXCLIPBOARDDIRDATA dirData;
580 rc = VBoxSvcClipboardURIGetDir(cParms, paParms, &dirData);
581 if (RT_SUCCESS(rc))
582 {
583 SharedClipboardArea *pArea = SharedClipboardURITransferGetArea(pTransfer);
584 AssertPtrBreakStmt(pArea, rc = VERR_INVALID_POINTER);
585
586 const char *pszCacheDir = pArea->GetDirAbs();
587 char *pszDir = RTPathJoinA(pszCacheDir, dirData.pszPath);
588 if (pszDir)
589 {
590 LogFlowFunc(("pszDir=%s\n", pszDir));
591
592 rc = RTDirCreateFullPath(pszDir, dirData.fMode);
593 if (RT_SUCCESS(rc))
594 {
595 SHAREDCLIPBOARDAREAOBJ Obj = { SHAREDCLIPBOARDAREAOBJTYPE_DIR, SHAREDCLIPBOARDAREAOBJSTATE_COMPLETE };
596 int rc2 = pArea->AddObject(pszDir, Obj);
597 AssertRC(rc2);
598 }
599
600 RTStrFree(pszDir);
601 }
602 else
603 rc = VERR_NO_MEMORY;
604 }
605 break;
606 }
607
608 case VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_FILE_HDR:
609 {
610 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_FILE_HDR\n"));
611
612 VBOXCLIPBOARDFILEHDR fileHdr;
613 rc = VBoxSvcClipboardURISetFileHdr(cParms, paParms, &fileHdr);
614 break;
615 }
616
617 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_FILE_HDR:
618 {
619 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_FILE_HDR\n"));
620
621 if (!SharedClipboardURIObjCtxIsValid(SharedClipboardURITransferGetCurrentObjCtx(pTransfer)))
622 {
623 pTransfer->State.ObjCtx.pObj = new SharedClipboardURIObject(SharedClipboardURIObject::Type_File);
624 if (pTransfer->State.ObjCtx.pObj) /** @todo Can this throw? */
625 {
626 rc = VINF_SUCCESS;
627 }
628 else
629 rc = VERR_NO_MEMORY;
630 }
631 else /* There still is another object being processed? */
632 rc = VERR_WRONG_ORDER;
633
634 if (RT_FAILURE(rc))
635 break;
636
637 VBOXCLIPBOARDFILEHDR fileHdr;
638 rc = VBoxSvcClipboardURIGetFileHdr(cParms, paParms, &fileHdr);
639 if (RT_SUCCESS(rc))
640 {
641 SharedClipboardArea *pArea = SharedClipboardURITransferGetArea(pTransfer);
642 AssertPtrBreakStmt(pArea, rc = VERR_WRONG_ORDER);
643
644 const char *pszCacheDir = pArea->GetDirAbs();
645
646 char pszPathAbs[RTPATH_MAX];
647 rc = RTPathJoin(pszPathAbs, sizeof(pszPathAbs), pszCacheDir, fileHdr.pszFilePath);
648 if (RT_SUCCESS(rc))
649 {
650 rc = SharedClipboardPathSanitize(pszPathAbs, sizeof(pszPathAbs));
651 if (RT_SUCCESS(rc))
652 {
653 PSHAREDCLIPBOARDCLIENTURIOBJCTX pObjCtx = SharedClipboardURITransferGetCurrentObjCtx(pTransfer);
654 AssertPtrBreakStmt(pObjCtx, VERR_INVALID_POINTER);
655
656 SharedClipboardURIObject *pObj = pObjCtx->pObj;
657 AssertPtrBreakStmt(pObj, VERR_INVALID_POINTER);
658
659 LogFlowFunc(("pszFile=%s\n", pszPathAbs));
660
661 /** @todo Add sparse file support based on fFlags? (Use Open(..., fFlags | SPARSE). */
662 rc = pObj->OpenFileEx(pszPathAbs, SharedClipboardURIObject::View_Target,
663 RTFILE_O_CREATE_REPLACE | RTFILE_O_WRITE | RTFILE_O_DENY_WRITE,
664 (fileHdr.fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR);
665 if (RT_SUCCESS(rc))
666 {
667 rc = pObj->SetSize(fileHdr.cbSize);
668
669 /** @todo Unescape path before printing. */
670 LogRel2(("Clipboard: Transferring guest file '%s' to host (%RU64 bytes, mode 0x%x)\n",
671 pObj->GetDestPathAbs().c_str(), pObj->GetSize(), pObj->GetMode()));
672
673 if (pObj->IsComplete()) /* 0-byte file? We're done already. */
674 {
675 /** @todo Sanitize path. */
676 LogRel2(("Clipboard: Transferring guest file '%s' (0 bytes) to host complete\n",
677 pObj->GetDestPathAbs().c_str()));
678
679 SharedClipboardURIObjCtxDestroy(&pTransfer->State.ObjCtx);
680 }
681
682 SHAREDCLIPBOARDAREAOBJ Obj = { SHAREDCLIPBOARDAREAOBJTYPE_FILE, SHAREDCLIPBOARDAREAOBJSTATE_NONE };
683 int rc2 = pArea->AddObject(pszPathAbs, Obj);
684 AssertRC(rc2);
685 }
686 else
687 LogRel(("Clipboard: Error opening/creating guest file '%s' on host, rc=%Rrc\n", pszPathAbs, rc));
688 }
689 }
690 }
691 break;
692 }
693
694 case VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_FILE_DATA:
695 {
696 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_READ_FILE_DATA\n"));
697
698 VBOXCLIPBOARDFILEDATA fileData;
699 rc = VBoxSvcClipboardURISetFileData(cParms, paParms, &fileData);
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->State.ObjCtx))
708 {
709 rc = VERR_WRONG_ORDER;
710 break;
711 }
712
713 VBOXCLIPBOARDFILEDATA fileData;
714 rc = VBoxSvcClipboardURIGetFileData(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->State.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 * @param uID ID of clipboard area to to attach to. Specify 0 to attach to the most recent one.
922 */
923int vboxSvcClipboardURIAreaAttach(PVBOXCLIPBOARDCLIENTSTATE pClientState, PSHAREDCLIPBOARDURITRANSFER pTransfer,
924 SHAREDCLIPBOARDAREAID uID)
925{
926 LogFlowFuncEnter();
927
928 AssertMsgReturn(pTransfer->pArea == NULL, ("An area already is attached to this transfer\n"),
929 VERR_WRONG_ORDER);
930
931 pTransfer->pArea = new SharedClipboardArea();
932 if (!pTransfer->pArea)
933 return VERR_NO_MEMORY;
934
935 int rc = VINF_SUCCESS;
936
937 if (g_pfnExtension)
938 {
939 VBOXCLIPBOARDEXTAREAPARMS parms;
940 RT_ZERO(parms);
941
942 parms.uID = uID; /* 0 means most recent clipboard area. */
943
944 /* The client now needs to attach to the most recent clipboard area
945 * to keep a reference to it. The host does the actual book keeping / cleanup then.
946 *
947 * This might fail if the host does not have a most recent clipboard area (yet). */
948 rc = g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_AREA_ATTACH, &parms, sizeof(parms));
949 if (RT_SUCCESS(rc))
950 rc = pTransfer->pArea->OpenTemp(parms.uID /* Area ID */);
951
952 LogFlowFunc(("Attached client %RU32 to clipboard area %RU32 with rc=%Rrc\n",
953 pClientState->u32ClientID, parms.uID, rc));
954 }
955 else
956 rc = VERR_NOT_SUPPORTED;
957
958 LogFlowFuncLeaveRC(rc);
959 return rc;
960}
961
962/**
963 * Detaches from an URI clipboard area.
964 *
965 * @returns VBox status code.
966 * @param pClientState Client state to use.
967 * @param pTransfer URI transfer to detach a clipboard area from.
968 */
969int vboxSvcClipboardURIAreaDetach(PVBOXCLIPBOARDCLIENTSTATE pClientState, PSHAREDCLIPBOARDURITRANSFER pTransfer)
970{
971 LogFlowFuncEnter();
972
973 if (!pTransfer->pArea)
974 return VINF_SUCCESS;
975
976 const uint32_t uAreaID = pTransfer->pArea->GetID();
977
978 int rc = VINF_SUCCESS;
979
980 if (g_pfnExtension)
981 {
982 VBOXCLIPBOARDEXTAREAPARMS parms;
983 RT_ZERO(parms);
984 parms.uID = uAreaID;
985
986 rc = g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_AREA_DETACH, &parms, sizeof(parms));
987
988 LogFlowFunc(("Detached client %RU32 from clipboard area %RU32 with rc=%Rrc\n",
989 pClientState->u32ClientID, uAreaID, rc));
990 }
991
992 delete pTransfer->pArea;
993 pTransfer->pArea = NULL;
994
995 LogFlowFuncLeaveRC(rc);
996 return rc;
997}
998
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