VirtualBox

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

Last change on this file since 79036 was 79036, checked in by vboxsync, 6 years ago

Shared Clipboard/URI: Update.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 30.2 KB
Line 
1/* $Id: VBoxSharedClipboardSvc-uri.cpp 79036 2019-06-07 14:56: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 * Initializes an URI object context.
47 *
48 * @returns VBox status code.
49 * @param pObjCtx URI object context to initialize.
50 */
51int vboxClipboardSvcURIObjCtxInit(PVBOXCLIPBOARDCLIENTURIOBJCTX pObjCtx)
52{
53 AssertPtrReturn(pObjCtx, VERR_INVALID_POINTER);
54
55 LogFlowFuncEnter();
56
57 pObjCtx->pObj = NULL;
58
59 return VINF_SUCCESS;
60}
61
62/**
63 * Uninitializes an URI object context.
64 *
65 * @param pObjCtx URI object context to uninitialize.
66 */
67void vboxClipboardSvcURIObjCtxUninit(PVBOXCLIPBOARDCLIENTURIOBJCTX pObjCtx)
68{
69 AssertPtrReturnVoid(pObjCtx);
70
71 LogFlowFuncEnter();
72
73 if (pObjCtx->pObj)
74 {
75 pObjCtx->pObj->Close();
76 delete pObjCtx->pObj;
77 }
78
79 pObjCtx->pObj = NULL;
80}
81
82/**
83 * Returns the URI object context's URI object.
84 *
85 * @returns Pointer to the URI object context's URI object.
86 * @param pObjCtx URI object context to return the URI object for.
87 */
88SharedClipboardURIObject *vboxClipboardSvcURIObjCtxGetObj(PVBOXCLIPBOARDCLIENTURIOBJCTX pObjCtx)
89{
90 AssertPtrReturn(pObjCtx, NULL);
91 return pObjCtx->pObj;
92}
93
94/**
95 * Returns if an URI object context is valid or not.
96 *
97 * @returns \c true if valid, \c false if not.
98 * @param pObjCtx URI object context to check.
99 */
100bool vboxClipboardSvcURIObjCtxIsValid(PVBOXCLIPBOARDCLIENTURIOBJCTX pObjCtx)
101{
102 return ( pObjCtx
103 && pObjCtx->pObj
104 && pObjCtx->pObj->IsComplete() == false
105 && pObjCtx->pObj->IsOpen());
106}
107
108/**
109 * Creates a URI transfer object.
110 *
111 * @returns VBox status code.
112 * @param pTransfer Transfer object to destroy.
113 * @param pState Client state to assign to the transfer object.
114 */
115int vboxClipboardSvcURITransferCreate(PVBOXCLIPBOARDCLIENTURITRANSFER pTransfer, PVBOXCLIPBOARDCLIENTSTATE pState)
116{
117 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
118 AssertPtrReturn(pState, VERR_INVALID_POINTER);
119
120 int rc = SharedClipboardMetaDataInit(&pTransfer->Meta);
121 if (RT_SUCCESS(rc))
122 {
123 vboxClipboardSvcURIObjCtxInit(&pTransfer->ObjCtx);
124 if (RT_SUCCESS(rc))
125 {
126 pTransfer->pState = pState;
127 }
128 }
129
130 LogFlowFuncLeaveRC(rc);
131 return rc;
132}
133
134/**
135 * Destroys a URI transfer object.
136 *
137 * @param pTransfer Transfer object to destroy.
138 */
139void vboxClipboardSvcURITransferDestroy(PVBOXCLIPBOARDCLIENTURITRANSFER pTransfer)
140{
141 AssertPtrReturnVoid(pTransfer);
142
143 LogFlowFuncEnter();
144
145 vboxClipboardSvcURITransferReset(pTransfer);
146}
147
148/**
149 * Resets a URI transfer object.
150 *
151 * @param pTransfer Transfer object to reset.
152 */
153void vboxClipboardSvcURITransferReset(PVBOXCLIPBOARDCLIENTURITRANSFER pTransfer)
154{
155 AssertPtrReturnVoid(pTransfer);
156
157 LogFlowFuncEnter();
158
159 vboxClipboardSvcURIObjCtxUninit(&pTransfer->ObjCtx);
160
161 /* Do we need to detach from a previously attached clipboard area? */
162 const SHAREDCLIPBOARDAREAID uAreaID = pTransfer->Area.GetID();
163 if ( g_pfnExtension
164 && uAreaID != NIL_SHAREDCLIPBOARDAREAID)
165 {
166 VBOXCLIPBOARDEXTAREAPARMS parms;
167 RT_ZERO(parms);
168 parms.uID = uAreaID;
169
170 int rc2 = g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_AREA_DETACH, &parms, sizeof(parms));
171#ifdef LOG_ENABLED
172 AssertPtr(pTransfer->pState);
173 LogFlowFunc(("Detached client %RU32 from clipboard area %RU32 with rc=%Rrc\n",
174 pTransfer->pState->u32ClientID, uAreaID, rc2));
175#endif
176 }
177
178 /* ignore rc */ pTransfer->Area.Rollback();
179 /* ignore rc */ pTransfer->Area.Close();
180
181 SharedClipboardMetaDataDestroy(&pTransfer->Meta);
182}
183
184/**
185 * Destroys a VBOXCLIPBOARDDIRDATA structure.
186 *
187 * @param pDirData VBOXCLIPBOARDDIRDATA structure to destroy.
188 */
189void vboxClipboardSvcURIDirDataDestroy(PVBOXCLIPBOARDDIRDATA pDirData)
190{
191 if (!pDirData)
192 return;
193
194 if (pDirData->pszPath)
195 {
196 Assert(pDirData->cbPath);
197 RTStrFree(pDirData->pszPath);
198 pDirData->pszPath = NULL;
199 }
200}
201
202/**
203 * Destroys a VBOXCLIPBOARDFILEHDR structure.
204 *
205 * @param pFileHdr VBOXCLIPBOARDFILEHDR structure to destroy.
206 */
207void vboxClipboardSvcURIFileHdrDestroy(PVBOXCLIPBOARDFILEHDR pFileHdr)
208{
209 if (!pFileHdr)
210 return;
211
212 if (pFileHdr->pszFilePath)
213 {
214 Assert(pFileHdr->pszFilePath);
215 RTStrFree(pFileHdr->pszFilePath);
216 pFileHdr->pszFilePath = NULL;
217 }
218}
219
220/**
221 * Destroys a VBOXCLIPBOARDFILEDATA structure.
222 *
223 * @param pFileData VBOXCLIPBOARDFILEDATA structure to destroy.
224 */
225void vboxClipboardSvcURIFileDataDestroy(PVBOXCLIPBOARDFILEDATA pFileData)
226{
227 if (!pFileData)
228 return;
229
230 if (pFileData->pvData)
231 {
232 Assert(pFileData->cbData);
233 RTMemFree(pFileData->pvData);
234 pFileData->pvData = NULL;
235 }
236}
237
238/**
239 * URI client (guest) handler for the Shared Clipboard host service.
240 *
241 * @returns VBox status code.
242 * @param u32ClientID Client ID of the client which called this handler.
243 * @param pvClient Pointer to client-specific data block.
244 * @param u32Function Function number being called.
245 * @param cParms Number of function parameters supplied.
246 * @param paParms Array function parameters supplied.
247 * @param tsArrival Timestamp of arrival.
248 * @param pfAsync Returns \c true if the response needs to be being asynchronous or \c false if not,
249 */
250int vboxClipboardSvcURIHandler(uint32_t u32ClientID,
251 void *pvClient,
252 uint32_t u32Function,
253 uint32_t cParms,
254 VBOXHGCMSVCPARM paParms[],
255 uint64_t tsArrival,
256 bool *pfAsync)
257{
258 RT_NOREF(u32ClientID, paParms, tsArrival, pfAsync);
259
260 LogFlowFunc(("u32ClientID=%RU32, u32Function=%RU32, cParms=%RU32, g_pfnExtension=%p\n",
261 u32ClientID, u32Function, cParms, g_pfnExtension));
262
263 const PVBOXCLIPBOARDCLIENTDATA pClientData = (PVBOXCLIPBOARDCLIENTDATA)pvClient;
264 AssertPtrReturn(pClientData, VERR_INVALID_POINTER);
265
266 /* Check if we've the right mode set. */
267 int rc = VERR_ACCESS_DENIED; /* Play safe. */
268
269 switch (u32Function)
270 {
271 case VBOX_SHARED_CLIPBOARD_FN_READ_DATA_HDR:
272 RT_FALL_THROUGH();
273 case VBOX_SHARED_CLIPBOARD_FN_READ_DIR:
274 RT_FALL_THROUGH();
275 case VBOX_SHARED_CLIPBOARD_FN_READ_FILE_HDR:
276 RT_FALL_THROUGH();
277 case VBOX_SHARED_CLIPBOARD_FN_READ_FILE_DATA:
278 {
279 if ( vboxSvcClipboardGetMode() == VBOX_SHARED_CLIPBOARD_MODE_GUEST_TO_HOST
280 || vboxSvcClipboardGetMode() == VBOX_SHARED_CLIPBOARD_MODE_BIDIRECTIONAL)
281 {
282 rc = VINF_SUCCESS;
283 }
284
285 if (RT_FAILURE(rc))
286 LogFunc(("Guest -> Host Shared Clipboard mode disabled, ignoring request\n"));
287 break;
288 }
289
290 case VBOX_SHARED_CLIPBOARD_FN_WRITE_DATA_HDR:
291 RT_FALL_THROUGH();
292 case VBOX_SHARED_CLIPBOARD_FN_WRITE_FILE_HDR:
293 RT_FALL_THROUGH();
294 case VBOX_SHARED_CLIPBOARD_FN_WRITE_FILE_DATA:
295 RT_FALL_THROUGH();
296 case VBOX_SHARED_CLIPBOARD_FN_WRITE_CANCEL:
297 RT_FALL_THROUGH();
298 case VBOX_SHARED_CLIPBOARD_FN_WRITE_ERROR:
299 {
300 if ( vboxSvcClipboardGetMode() == VBOX_SHARED_CLIPBOARD_MODE_HOST_TO_GUEST
301 || vboxSvcClipboardGetMode() == VBOX_SHARED_CLIPBOARD_MODE_BIDIRECTIONAL)
302 {
303 rc = VINF_SUCCESS;
304 }
305
306 if (RT_FAILURE(rc))
307 LogFunc(("Clipboard: Host -> Guest Shared Clipboard mode disabled, ignoring request\n"));
308 break;
309 }
310
311 default:
312 break;
313 }
314
315 if (!g_pfnExtension)
316 {
317#ifdef DEBUG_andy
318 AssertPtr(g_pfnExtension);
319#endif
320 LogFunc(("Invalid / no service extension set, skipping URI handling\n"));
321 rc = VERR_ACCESS_DENIED;
322 }
323
324 if (RT_FAILURE(rc))
325 return rc;
326
327 const PVBOXCLIPBOARDCLIENTURITRANSFER pTransfer = &pClientData->Transfer;
328
329 rc = VERR_INVALID_PARAMETER; /* Play safe. */
330
331 switch (u32Function)
332 {
333 case VBOX_SHARED_CLIPBOARD_FN_READ_DATA_HDR:
334 {
335 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_READ_DATA_HDR\n"));
336 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_READ_DATA_HDR)
337 {
338 VBOXCLIPBOARDEXTAREAPARMS parms;
339 RT_ZERO(parms);
340
341 parms.uID = 0; /* 0 means most recent clipboard area. */
342
343 /* The client now needs to attach to the most recent clipboard area
344 * to keep a reference to it. The host does the actual book keeping / cleanup then.
345 *
346 * This might fail if the host does not have a most recent clipboard area (yet). */
347 rc = g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_AREA_ATTACH, &parms, sizeof(parms));
348#ifdef LOG_ENABLED
349 AssertPtr(pTransfer->pState);
350 LogFlowFunc(("Attached client %RU32 to clipboard area %RU32 with rc=%Rrc\n",
351 pTransfer->pState->u32ClientID, parms.uID, rc));
352#endif
353 bool fDetach = false;
354
355 if (RT_SUCCESS(rc))
356 {
357 // pTransfer->Area. parms.uID
358
359 /** @todo Detach if header / meta size is 0. */
360 }
361
362 /* Do we need to detach again because we're done? */
363 if (fDetach)
364 {
365 RT_ZERO(parms);
366 parms.uID = pTransfer->Area.GetID();
367
368 rc = g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_AREA_DETACH, &parms, sizeof(parms));
369#ifdef LOG_ENABLED
370 AssertPtr(pTransfer->pState);
371 LogFlowFunc(("Detached client %RU32 from clipboard area %RU32 with rc=%Rrc\n",
372 pTransfer->pState->u32ClientID, parms.uID, rc));
373#endif
374 }
375 }
376 break;
377 }
378
379 case VBOX_SHARED_CLIPBOARD_FN_WRITE_DATA_HDR:
380 {
381 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_DATA_HDR\n"));
382 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_DATA_HDR)
383 {
384 if (pClientData->cTransfers == 0) /* At the moment we only support on transfer per client at a time. */
385 {
386 RT_ZERO(pTransfer->Hdr);
387 /* Note: Context ID (paParms[0]) not used yet. */
388 rc = HGCMSvcGetU32(&paParms[1], &pTransfer->Hdr.uFlags);
389 if (RT_SUCCESS(rc))
390 rc = HGCMSvcGetU32(&paParms[2], &pTransfer->Hdr.uScreenId);
391 if (RT_SUCCESS(rc))
392 rc = HGCMSvcGetU64(&paParms[3], &pTransfer->Hdr.cbTotal);
393 if (RT_SUCCESS(rc))
394 rc = HGCMSvcGetU32(&paParms[4], &pTransfer->Hdr.cbMeta);
395 if (RT_SUCCESS(rc))
396 rc = HGCMSvcGetPv(&paParms[5], &pTransfer->Hdr.pvMetaFmt, &pTransfer->Hdr.cbMetaFmt);
397 if (RT_SUCCESS(rc))
398 rc = HGCMSvcGetU32(&paParms[6], &pTransfer->Hdr.cbMetaFmt);
399 if (RT_SUCCESS(rc))
400 rc = HGCMSvcGetU64(&paParms[7], &pTransfer->Hdr.cObjects);
401 if (RT_SUCCESS(rc))
402 rc = HGCMSvcGetU32(&paParms[8], &pTransfer->Hdr.enmCompression);
403 if (RT_SUCCESS(rc))
404 rc = HGCMSvcGetU32(&paParms[9], (uint32_t *)&pTransfer->Hdr.enmChecksumType);
405 if (RT_SUCCESS(rc))
406 rc = HGCMSvcGetPv(&paParms[10], &pTransfer->Hdr.pvChecksum, &pTransfer->Hdr.cbChecksum);
407 if (RT_SUCCESS(rc))
408 rc = HGCMSvcGetU32(&paParms[11], &pTransfer->Hdr.cbChecksum);
409
410 LogFlowFunc(("fFlags=0x%x, cbMeta=%RU32, cbTotalSize=%RU64, cObj=%RU64\n",
411 pTransfer->Hdr.uFlags, pTransfer->Hdr.cbMeta, pTransfer->Hdr.cbTotal, pTransfer->Hdr.cObjects));
412
413 if (RT_SUCCESS(rc))
414 {
415 /** @todo Validate pvMetaFmt + cbMetaFmt. */
416 /** @todo Validate checksum. */
417 rc = SharedClipboardMetaDataResize(&pTransfer->Meta, pTransfer->Hdr.cbMeta);
418 if (RT_SUCCESS(rc))
419 {
420 pClientData->cTransfers++;
421 }
422 }
423 }
424 else
425 {
426 LogFunc(("Another transfer in progress, cTransfers=%RU32\n", pClientData->cTransfers));
427 rc = VERR_SHCLPB_MAX_TRANSFERS_REACHED;
428 }
429 }
430
431 break;
432 }
433
434 case VBOX_SHARED_CLIPBOARD_FN_WRITE_DATA_CHUNK:
435 {
436 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_DATA_CHUNK\n"));
437 if ( cParms == VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_DATA_CHUNK
438 && pClientData->cTransfers) /* Some transfer in-flight? */
439 {
440 VBOXCLIPBOARDDATACHUNK data;
441 RT_ZERO(data);
442 /* Note: Context ID (paParms[0]) not used yet. */
443 rc = HGCMSvcGetPv(&paParms[1], (void**)&data.pvData, &data.cbData);
444 if (RT_SUCCESS(rc))
445 rc = HGCMSvcGetU32(&paParms[2], &data.cbData);
446 if (RT_SUCCESS(rc))
447 rc = HGCMSvcGetPv(&paParms[3], (void**)&data.pvChecksum, &data.cbChecksum);
448 if (RT_SUCCESS(rc))
449 rc = HGCMSvcGetU32(&paParms[4], &data.cbChecksum);
450
451 if (RT_SUCCESS(rc))
452 {
453 if (!VBoxSvcClipboardDataChunkIsValid(&data))
454 rc = VERR_INVALID_PARAMETER;
455 }
456
457 if (RT_SUCCESS(rc))
458 {
459 /** @todo Validate checksum. */
460 rc = SharedClipboardMetaDataAdd(&pTransfer->Meta, data.pvData, data.cbData);
461 if ( RT_SUCCESS(rc)
462 && SharedClipboardMetaDataGetUsed(&pTransfer->Meta) == pTransfer->Hdr.cbMeta) /* Meta data transfer complete? */
463 {
464 void *pvMeta = SharedClipboardMetaDataMutableRaw(&pTransfer->Meta);
465 const size_t cbMeta = SharedClipboardMetaDataGetSize(&pTransfer->Meta);
466
467 rc = pTransfer->List.SetFromURIData(pvMeta, cbMeta, SHAREDCLIPBOARDURILIST_FLAGS_NONE);
468
469 if (RT_SUCCESS(rc))
470 {
471 VBOXCLIPBOARDEXTAREAPARMS parms;
472 RT_ZERO(parms);
473
474 parms.uID = NIL_SHAREDCLIPBOARDAREAID;
475 parms.u.fn_register.pvData = pvMeta;
476 parms.u.fn_register.cbData = (uint32_t)cbMeta;
477
478 /* As the meta data is now complete, register a new clipboard on the host side. */
479 rc = g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_AREA_REGISTER, &parms, sizeof(parms));
480 if (RT_SUCCESS(rc))
481 rc = pTransfer->Area.OpenTemp(parms.uID /* Area ID */);
482#ifdef LOG_ENABLED
483 AssertPtr(pTransfer->pState);
484 LogFlowFunc(("Registered new clipboard area (%RU32) by client %RU32 with rc=%Rrc\n",
485 parms.uID, pTransfer->pState->u32ClientID, rc));
486#endif
487 }
488
489 /* We're done processing the meta data, so just destroy it. */
490 SharedClipboardMetaDataDestroy(&pTransfer->Meta);
491 }
492 }
493 }
494 break;
495 }
496
497 case VBOX_SHARED_CLIPBOARD_FN_READ_DIR:
498 {
499 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_READ_DIR\n"));
500 if ( cParms == VBOX_SHARED_CLIPBOARD_CPARMS_READ_DIR
501 && pClientData->cTransfers) /* Some transfer in-flight? */
502 {
503 VBOXCLIPBOARDDIRDATA data;
504 rc = VBoxClipboardSvcImplURIReadDir(pClientData, &data);
505 if (RT_SUCCESS(rc))
506 {
507 /* Note: Context ID (paParms[0]) not used yet. */
508 HGCMSvcSetPv (&paParms[1], data.pszPath, data.cbPath);
509 HGCMSvcSetU32(&paParms[2], data.cbPath);
510 HGCMSvcSetU32(&paParms[3], data.fMode);
511
512 vboxClipboardSvcURIDirDataDestroy(&data);
513 }
514 }
515 break;
516 }
517
518 case VBOX_SHARED_CLIPBOARD_FN_WRITE_DIR:
519 {
520 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_DIR\n"));
521 if ( cParms == VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_DIR
522 && pClientData->cTransfers) /* Some transfer in-flight? */
523 {
524 VBOXCLIPBOARDDIRDATA data;
525 RT_ZERO(data);
526 /* Note: Context ID (paParms[0]) not used yet. */
527 rc = HGCMSvcGetPv(&paParms[1], (void**)&data.pszPath, &data.cbPath);
528 if (RT_SUCCESS(rc))
529 rc = HGCMSvcGetU32(&paParms[2], &data.cbPath);
530 if (RT_SUCCESS(rc))
531 rc = HGCMSvcGetU32(&paParms[3], &data.fMode);
532
533 LogFlowFunc(("pszPath=%s, cbPath=%RU32, fMode=0x%x\n", data.pszPath, data.cbPath, data.fMode));
534
535 if (RT_SUCCESS(rc))
536 {
537 if (!VBoxSvcClipboardDirDataIsValid(&data))
538 rc = VERR_INVALID_PARAMETER;
539 }
540
541 if (RT_SUCCESS(rc))
542 {
543 const char *pszCacheDir = pTransfer->Area.GetDirAbs();
544 char *pszDir = RTPathJoinA(pszCacheDir, data.pszPath);
545 if (pszDir)
546 {
547 LogFlowFunc(("pszDir=%s\n", pszDir));
548
549 rc = RTDirCreateFullPath(pszDir, data.fMode);
550 if (RT_SUCCESS(rc))
551 {
552 /* Add for having a proper rollback. */
553 int rc2 = pTransfer->Area.AddDir(pszDir);
554 AssertRC(rc2);
555 }
556
557 RTStrFree(pszDir);
558 }
559 else
560 rc = VERR_NO_MEMORY;
561 }
562 }
563 break;
564 }
565
566 case VBOX_SHARED_CLIPBOARD_FN_READ_FILE_HDR:
567 {
568 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_READ_FILE_HDR\n"));
569 if ( cParms == VBOX_SHARED_CLIPBOARD_CPARMS_READ_FILE_HDR
570 && pClientData->cTransfers) /* Some transfer in-flight? */
571 {
572 VBOXCLIPBOARDFILEHDR hdr;
573 rc = VBoxClipboardSvcImplURIReadFileHdr(pClientData, &hdr);
574 if (RT_SUCCESS(rc))
575 {
576 /* Note: Context ID (paParms[0]) not used yet. */
577 HGCMSvcSetPv (&paParms[1], hdr.pszFilePath, hdr.cbFilePath);
578 HGCMSvcSetU32(&paParms[2], hdr.cbFilePath);
579 HGCMSvcSetU32(&paParms[3], hdr.fFlags);
580 HGCMSvcSetU32(&paParms[4], hdr.fMode);
581 HGCMSvcSetU64(&paParms[5], hdr.cbSize);
582
583 vboxClipboardSvcURIFileHdrDestroy(&hdr);
584 }
585 }
586 break;
587 }
588
589 case VBOX_SHARED_CLIPBOARD_FN_WRITE_FILE_HDR:
590 {
591 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_FILE_HDR\n"));
592 if ( cParms == VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_FILE_HDR
593 && pClientData->cTransfers) /* Some transfer in-flight? */
594 {
595 VBOXCLIPBOARDFILEHDR data;
596 RT_ZERO(data);
597 /* Note: Context ID (paParms[0]) not used yet. */
598 rc = HGCMSvcGetPv(&paParms[1], (void**)&data.pszFilePath, &data.cbFilePath);
599 if (RT_SUCCESS(rc))
600 rc = HGCMSvcGetU32(&paParms[2], &data.cbFilePath);
601 if (RT_SUCCESS(rc))
602 rc = HGCMSvcGetU32(&paParms[3], &data.fFlags);
603 if (RT_SUCCESS(rc))
604 rc = HGCMSvcGetU32(&paParms[4], &data.fMode);
605 if (RT_SUCCESS(rc))
606 rc = HGCMSvcGetU64(&paParms[5], &data.cbSize);
607
608 LogFlowFunc(("pszPath=%s, cbPath=%RU32, fMode=0x%x, cbSize=%RU64\n",
609 data.pszFilePath, data.cbFilePath, data.fMode, data.cbSize));
610
611 if (RT_SUCCESS(rc))
612 {
613 if (!VBoxSvcClipboardFileHdrIsValid(&data, &pTransfer->Hdr))
614 {
615 rc = VERR_INVALID_PARAMETER;
616 }
617 else
618 {
619 if (pTransfer->ObjCtx.pObj == NULL)
620 {
621 pTransfer->ObjCtx.pObj = new SharedClipboardURIObject(SharedClipboardURIObject::Type_File);
622 if (!pTransfer->ObjCtx.pObj) /** @todo Can this throw? */
623 rc = VERR_NO_MEMORY;
624 }
625 else /* There still is another object being processed? */
626 rc = VERR_WRONG_ORDER;
627 }
628 }
629
630 if (RT_SUCCESS(rc))
631 {
632 const char *pszCacheDir = pTransfer->Area.GetDirAbs();
633
634 char pszPathAbs[RTPATH_MAX];
635 rc = RTPathJoin(pszPathAbs, sizeof(pszPathAbs), pszCacheDir, data.pszFilePath);
636 if (RT_SUCCESS(rc))
637 {
638 rc = SharedClipboardPathSanitize(pszPathAbs, sizeof(pszPathAbs));
639 if (RT_SUCCESS(rc))
640 {
641 SharedClipboardURIObject *pObj = vboxClipboardSvcURIObjCtxGetObj(&pTransfer->ObjCtx);
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 (data.fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR);
647 if (RT_SUCCESS(rc))
648 {
649 rc = pObj->SetSize(data.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 vboxClipboardSvcURIObjCtxUninit(&pTransfer->ObjCtx);
662 }
663
664 /* Add for having a proper rollback. */
665 int rc2 = pTransfer->Area.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 }
674 break;
675 }
676
677 case VBOX_SHARED_CLIPBOARD_FN_READ_FILE_DATA:
678 {
679 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_READ_FILE_DATA\n"));
680 if ( cParms == VBOX_SHARED_CLIPBOARD_CPARMS_READ_FILE_DATA
681 && pClientData->cTransfers) /* Some transfer in-flight? */
682 {
683 VBOXCLIPBOARDFILEDATA data;
684 rc = VBoxClipboardSvcImplURIReadFileData(pClientData, &data);
685 if (RT_SUCCESS(rc))
686 {
687 /* Note: Context ID (paParms[0]) not used yet. */
688 HGCMSvcSetPv (&paParms[1], data.pvData, data.cbData);
689 HGCMSvcSetU32(&paParms[2], data.cbData);
690 HGCMSvcSetPv (&paParms[3], data.pvChecksum, data.cbChecksum);
691 HGCMSvcSetU32(&paParms[4], data.cbChecksum);
692
693 vboxClipboardSvcURIFileDataDestroy(&data);
694 }
695 }
696 break;
697 }
698
699 case VBOX_SHARED_CLIPBOARD_FN_WRITE_FILE_DATA:
700 {
701 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_FILE_DATA\n"));
702 if ( cParms == VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_FILE_DATA
703 && pClientData->cTransfers) /* Some transfer in-flight? */
704 {
705 VBOXCLIPBOARDFILEDATA data;
706 RT_ZERO(data);
707 /* Note: Context ID (paParms[0]) not used yet. */
708 rc = HGCMSvcGetPv(&paParms[1], (void**)&data.pvData, &data.cbData);
709 if (RT_SUCCESS(rc))
710 rc = HGCMSvcGetU32(&paParms[2], &data.cbData);
711 if (RT_SUCCESS(rc))
712 rc = HGCMSvcGetPv(&paParms[3], (void**)&data.pvChecksum, &data.cbChecksum);
713 if (RT_SUCCESS(rc))
714 rc = HGCMSvcGetU32(&paParms[4], &data.cbChecksum);
715
716 LogFlowFunc(("pvData=0x%p, cbData=%RU32\n", data.pvData, data.cbData));
717
718 if (RT_SUCCESS(rc))
719 {
720 if (!VBoxSvcClipboardFileDataIsValid(&data, &pTransfer->Hdr))
721 rc = VERR_INVALID_PARAMETER;
722
723 if (!vboxClipboardSvcURIObjCtxIsValid(&pTransfer->ObjCtx))
724 rc = VERR_WRONG_ORDER;
725 }
726
727 if (RT_SUCCESS(rc))
728 {
729 SharedClipboardURIObject *pObj = vboxClipboardSvcURIObjCtxGetObj(&pTransfer->ObjCtx);
730
731 uint32_t cbWritten;
732 rc = pObj->Write(data.pvData, data.cbData, &cbWritten);
733 if (RT_SUCCESS(rc))
734 {
735 Assert(cbWritten <= data.cbData);
736 if (cbWritten < data.cbData)
737 {
738 /** @todo What to do when the host's disk is full? */
739 rc = VERR_DISK_FULL;
740 }
741
742 if ( pObj->IsComplete()
743 || RT_FAILURE(rc))
744 vboxClipboardSvcURIObjCtxUninit(&pTransfer->ObjCtx);
745 }
746 else
747 LogRel(("Clipboard: Error writing guest file data for '%s', rc=%Rrc\n", pObj->GetDestPathAbs().c_str(), rc));
748 }
749 }
750 break;
751 }
752
753 case VBOX_SHARED_CLIPBOARD_FN_WRITE_CANCEL:
754 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_CANCEL\n"));
755 AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED);
756 break;
757
758 case VBOX_SHARED_CLIPBOARD_FN_WRITE_ERROR:
759 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_ERROR\n"));
760 AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED);
761 break;
762
763 default:
764 AssertMsgFailed(("Not implemented\n"));
765 break;
766 }
767
768 LogFlowFuncLeaveRC(rc);
769 return rc;
770}
771
772/**
773 * URI host handler for the Shared Clipboard host service.
774 *
775 * @returns VBox status code.
776 * @param u32Function Function number being called.
777 * @param cParms Number of function parameters supplied.
778 * @param paParms Array function parameters supplied.
779 */
780int vboxClipboardSvcURIHostHandler(uint32_t u32Function,
781 uint32_t cParms,
782 VBOXHGCMSVCPARM paParms[])
783{
784 RT_NOREF(cParms, paParms);
785
786 int rc = VERR_INVALID_PARAMETER; /* Play safe. */
787
788 switch (u32Function)
789 {
790 case VBOX_SHARED_CLIPBOARD_HOST_FN_CANCEL:
791 break;
792
793 case VBOX_SHARED_CLIPBOARD_HOST_FN_ERROR:
794 break;
795
796 default:
797 AssertMsgFailed(("Not implemented\n"));
798 break;
799
800 }
801
802 LogFlowFuncLeaveRC(rc);
803 return rc;
804}
805
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