VirtualBox

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

Last change on this file since 78897 was 78897, 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: 26.1 KB
Line 
1/* $Id: VBoxSharedClipboardSvc-uri.cpp 78897 2019-05-31 15:23:14Z 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/HostServices/VBoxClipboardSvc.h>
24#include <VBox/HostServices/VBoxClipboardExt.h>
25
26#include <iprt/dir.h>
27#include <iprt/file.h>
28#include <iprt/path.h>
29
30#include "VBoxSharedClipboardSvc-internal.h"
31#include "VBoxSharedClipboardSvc-uri.h"
32
33
34/*********************************************************************************************************************************
35* Externals *
36*********************************************************************************************************************************/
37extern PFNHGCMSVCEXT g_pfnExtension;
38extern void *g_pvExtension;
39
40
41/**
42 * Initializes an URI object context.
43 *
44 * @returns VBox status code.
45 * @param pObjCtx URI object context to initialize.
46 */
47int vboxClipboardSvcURIObjCtxInit(PVBOXCLIPBOARDCLIENTURIOBJCTX pObjCtx)
48{
49 AssertPtrReturn(pObjCtx, VERR_INVALID_POINTER);
50
51 LogFlowFuncEnter();
52
53 pObjCtx->pObj = NULL;
54
55 return VINF_SUCCESS;
56}
57
58/**
59 * Uninitializes an URI object context.
60 *
61 * @param pObjCtx URI object context to uninitialize.
62 */
63void vboxClipboardSvcURIObjCtxUninit(PVBOXCLIPBOARDCLIENTURIOBJCTX pObjCtx)
64{
65 AssertPtrReturnVoid(pObjCtx);
66
67 LogFlowFuncEnter();
68
69 if (pObjCtx->pObj)
70 {
71 pObjCtx->pObj->Close();
72 delete pObjCtx->pObj;
73 }
74
75 pObjCtx->pObj = NULL;
76}
77
78/**
79 * Returns the URI object context's URI object.
80 *
81 * @returns Pointer to the URI object context's URI object.
82 * @param pObjCtx URI object context to return the URI object for.
83 */
84SharedClipboardURIObject *vboxClipboardSvcURIObjCtxGetObj(PVBOXCLIPBOARDCLIENTURIOBJCTX pObjCtx)
85{
86 AssertPtrReturn(pObjCtx, NULL);
87 return pObjCtx->pObj;
88}
89
90/**
91 * Returns if an URI object context is valid or not.
92 *
93 * @returns \c true if valid, \c false if not.
94 * @param pObjCtx URI object context to check.
95 */
96bool vboxClipboardSvcURIObjCtxIsValid(PVBOXCLIPBOARDCLIENTURIOBJCTX pObjCtx)
97{
98 return ( pObjCtx
99 && pObjCtx->pObj
100 && pObjCtx->pObj->IsComplete() == false
101 && pObjCtx->pObj->IsOpen());
102}
103
104/**
105 * Creates a URI transfer object.
106 *
107 * @returns VBox status code.
108 * @param pTransfer Transfer object to destroy.
109 * @param pState Client state to assign to the transfer object.
110 */
111int vboxClipboardSvcURITransferCreate(PVBOXCLIPBOARDCLIENTURITRANSFER pTransfer, PVBOXCLIPBOARDCLIENTSTATE pState)
112{
113 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
114 AssertPtrReturn(pState, VERR_INVALID_POINTER);
115
116 int rc = pTransfer->Cache.OpenTemp(SHAREDCLIPBOARDAREA_FLAGS_NONE);
117 if (RT_SUCCESS(rc))
118 {
119 rc = SharedClipboardMetaDataInit(&pTransfer->Meta);
120 if (RT_SUCCESS(rc))
121 {
122 vboxClipboardSvcURIObjCtxInit(&pTransfer->ObjCtx);
123 if (RT_SUCCESS(rc))
124 {
125 pTransfer->pState = pState;
126 }
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 int rc2;
162
163 /* Do we need to detach from a previously attached clipboard area? */
164 const SHAREDCLIPBOARDAREAID uAreaID = pTransfer->Cache.GetAreaID();
165 if ( g_pfnExtension
166 && uAreaID != NIL_SHAREDCLIPBOARDAREAID)
167 {
168 VBOXCLIPBOARDEXTAREAPARMS parms;
169 RT_ZERO(parms);
170 parms.uID = uAreaID;
171
172 rc2 = g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_AREA_DETACH, &parms, sizeof(parms));
173 AssertRC(rc2);
174#ifdef LOG_ENABLED
175 AssertPtr(pTransfer->pState);
176 LogFlowFunc(("Detached client %RU32 from clipboard area %RU32 with rc=%Rrc\n",
177 pTransfer->pState->u32ClientID, uAreaID, rc2));
178#endif
179 }
180
181 rc2 = pTransfer->Cache.Rollback();
182 AssertRC(rc2);
183
184 rc2 = pTransfer->Cache.Close();
185 AssertRC(rc2);
186
187 SharedClipboardMetaDataDestroy(&pTransfer->Meta);
188}
189
190/**
191 * URI client (guest) handler for the Shared Clipboard host service.
192 *
193 * @returns VBox status code.
194 * @param u32ClientID Client ID of the client which called this handler.
195 * @param pvClient Pointer to client-specific data block.
196 * @param u32Function Function number being called.
197 * @param cParms Number of function parameters supplied.
198 * @param paParms Array function parameters supplied.
199 * @param tsArrival Timestamp of arrival.
200 * @param pfAsync Returns \c true if the response needs to be being asynchronous or \c false if not,
201 */
202int vboxClipboardSvcURIHandler(uint32_t u32ClientID,
203 void *pvClient,
204 uint32_t u32Function,
205 uint32_t cParms,
206 VBOXHGCMSVCPARM paParms[],
207 uint64_t tsArrival,
208 bool *pfAsync)
209{
210 RT_NOREF(u32ClientID, paParms, tsArrival, pfAsync);
211
212 LogFlowFunc(("u32ClientID=%RU32, u32Function=%RU32, cParms=%RU32, g_pfnExtension=%p\n",
213 u32ClientID, u32Function, cParms, g_pfnExtension));
214
215 const PVBOXCLIPBOARDCLIENTDATA pClientData = (PVBOXCLIPBOARDCLIENTDATA)pvClient;
216 AssertPtrReturn(pClientData, VERR_INVALID_POINTER);
217
218 /* Check if we've the right mode set. */
219 int rc = VERR_ACCESS_DENIED; /* Play safe. */
220
221 switch (u32Function)
222 {
223 case VBOX_SHARED_CLIPBOARD_FN_READ_DATA_HDR:
224 RT_FALL_THROUGH();
225 case VBOX_SHARED_CLIPBOARD_FN_READ_DIR:
226 RT_FALL_THROUGH();
227 case VBOX_SHARED_CLIPBOARD_FN_READ_FILE_HDR:
228 RT_FALL_THROUGH();
229 case VBOX_SHARED_CLIPBOARD_FN_READ_FILE_DATA:
230 {
231 if ( vboxSvcClipboardGetMode() == VBOX_SHARED_CLIPBOARD_MODE_GUEST_TO_HOST
232 || vboxSvcClipboardGetMode() == VBOX_SHARED_CLIPBOARD_MODE_BIDIRECTIONAL)
233 {
234 rc = VINF_SUCCESS;
235 }
236
237 if (RT_FAILURE(rc))
238 LogFunc(("Guest -> Host Shared Clipboard mode disabled, ignoring request\n"));
239 break;
240 }
241
242 case VBOX_SHARED_CLIPBOARD_FN_WRITE_DATA_HDR:
243 RT_FALL_THROUGH();
244 case VBOX_SHARED_CLIPBOARD_FN_WRITE_FILE_HDR:
245 RT_FALL_THROUGH();
246 case VBOX_SHARED_CLIPBOARD_FN_WRITE_FILE_DATA:
247 RT_FALL_THROUGH();
248 case VBOX_SHARED_CLIPBOARD_FN_WRITE_CANCEL:
249 RT_FALL_THROUGH();
250 case VBOX_SHARED_CLIPBOARD_FN_WRITE_ERROR:
251 {
252 if ( vboxSvcClipboardGetMode() == VBOX_SHARED_CLIPBOARD_MODE_HOST_TO_GUEST
253 || vboxSvcClipboardGetMode() == VBOX_SHARED_CLIPBOARD_MODE_BIDIRECTIONAL)
254 {
255 rc = VINF_SUCCESS;
256 }
257
258 if (RT_FAILURE(rc))
259 LogFunc(("Clipboard: Host -> Guest Shared Clipboard mode disabled, ignoring request\n"));
260 break;
261 }
262
263 default:
264 break;
265 }
266
267 if (RT_FAILURE(rc))
268 return rc;
269
270 const PVBOXCLIPBOARDCLIENTURITRANSFER pTransfer = &pClientData->Transfer;
271
272 rc = VERR_INVALID_PARAMETER; /* Play safe. */
273
274 switch (u32Function)
275 {
276 case VBOX_SHARED_CLIPBOARD_FN_READ_DATA_HDR:
277 {
278 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_READ_DATA_HDR\n"));
279 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_READ_DATA_HDR)
280 {
281 if (g_pfnExtension)
282 {
283 VBOXCLIPBOARDEXTAREAPARMS parms;
284 RT_ZERO(parms);
285
286 parms.uID = 0; /* 0 means most recent clipboard area. */
287
288 /* The client now needs to attach to the most recent clipboard area
289 * to keep a reference to it. The host does the actual book keeping / cleanup then. */
290 rc = g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_AREA_ATTACH, &parms, sizeof(parms));
291#ifdef LOG_ENABLED
292 AssertPtr(pTransfer->pState);
293 LogFlowFunc(("Attached client %RU32 from clipboard area %RU32 with rc=%Rrc\n",
294 pTransfer->pState->u32ClientID, parms.uID, rc));
295#endif
296 if (RT_SUCCESS(rc))
297 {
298
299 }
300
301 /* Do we need to detach again because we're done? */
302 if ( RT_SUCCESS(rc))
303 {
304 RT_ZERO(parms);
305 parms.uID = pTransfer->Cache.GetAreaID();
306
307 rc = g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_AREA_DETACH, &parms, sizeof(parms));
308#ifdef LOG_ENABLED
309 AssertPtr(pTransfer->pState);
310 LogFlowFunc(("Detached client %RU32 from clipboard area %RU32 with rc=%Rrc\n",
311 pTransfer->pState->u32ClientID, parms.uID, rc));
312#endif
313 }
314 }
315 }
316 break;
317 }
318
319 case VBOX_SHARED_CLIPBOARD_FN_WRITE_DATA_HDR:
320 {
321 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_DATA_HDR\n"));
322 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_DATA_HDR)
323 {
324 if (pClientData->cTransfers == 0) /* At the moment we only support on transfer per client at a time. */
325 {
326 RT_ZERO(pTransfer->Hdr);
327 /* Note: Context ID (paParms[0]) not used yet. */
328 rc = HGCMSvcGetU32(&paParms[1], &pTransfer->Hdr.uFlags);
329 if (RT_SUCCESS(rc))
330 rc = HGCMSvcGetU32(&paParms[2], &pTransfer->Hdr.uScreenId);
331 if (RT_SUCCESS(rc))
332 rc = HGCMSvcGetU64(&paParms[3], &pTransfer->Hdr.cbTotal);
333 if (RT_SUCCESS(rc))
334 rc = HGCMSvcGetU32(&paParms[4], &pTransfer->Hdr.cbMeta);
335 if (RT_SUCCESS(rc))
336 rc = HGCMSvcGetPv(&paParms[5], &pTransfer->Hdr.pvMetaFmt, &pTransfer->Hdr.cbMetaFmt);
337 if (RT_SUCCESS(rc))
338 rc = HGCMSvcGetU32(&paParms[6], &pTransfer->Hdr.cbMetaFmt);
339 if (RT_SUCCESS(rc))
340 rc = HGCMSvcGetU64(&paParms[7], &pTransfer->Hdr.cObjects);
341 if (RT_SUCCESS(rc))
342 rc = HGCMSvcGetU32(&paParms[8], &pTransfer->Hdr.enmCompression);
343 if (RT_SUCCESS(rc))
344 rc = HGCMSvcGetU32(&paParms[9], (uint32_t *)&pTransfer->Hdr.enmChecksumType);
345 if (RT_SUCCESS(rc))
346 rc = HGCMSvcGetPv(&paParms[10], &pTransfer->Hdr.pvChecksum, &pTransfer->Hdr.cbChecksum);
347 if (RT_SUCCESS(rc))
348 rc = HGCMSvcGetU32(&paParms[11], &pTransfer->Hdr.cbChecksum);
349
350 LogFlowFunc(("fFlags=0x%x, cbTotalSize=%RU64, cObj=%RU64\n",
351 pTransfer->Hdr.uFlags, pTransfer->Hdr.cbTotal, pTransfer->Hdr.cObjects));
352
353 if (RT_SUCCESS(rc))
354 {
355 /** @todo Validate pvMetaFmt + cbMetaFmt. */
356 /** @todo Validate checksum. */
357 rc = SharedClipboardMetaDataResize(&pTransfer->Meta, pTransfer->Hdr.cbMeta);
358 if (RT_SUCCESS(rc))
359 pClientData->cTransfers++;
360 }
361 }
362 else
363 LogFunc(("Another transfer in progress, cTransfers=%RU32\n", pClientData->cTransfers));
364 }
365
366 break;
367 }
368
369 case VBOX_SHARED_CLIPBOARD_FN_WRITE_DATA_CHUNK:
370 {
371 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_DATA_CHUNK\n"));
372 if ( cParms == VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_DATA_CHUNK
373 && pClientData->cTransfers) /* Some transfer in-flight? */
374 {
375 VBOXCLIPBOARDDATACHUNK data;
376 RT_ZERO(data);
377 /* Note: Context ID (paParms[0]) not used yet. */
378 rc = HGCMSvcGetPv(&paParms[1], (void**)&data.pvData, &data.cbData);
379 if (RT_SUCCESS(rc))
380 rc = HGCMSvcGetU32(&paParms[2], &data.cbData);
381 if (RT_SUCCESS(rc))
382 rc = HGCMSvcGetPv(&paParms[3], (void**)&data.pvChecksum, &data.cbChecksum);
383 if (RT_SUCCESS(rc))
384 rc = HGCMSvcGetU32(&paParms[4], &data.cbChecksum);
385
386 if (RT_SUCCESS(rc))
387 {
388 if (!VBoxSvcClipboardDataChunkIsValid(&data))
389 rc = VERR_INVALID_PARAMETER;
390 }
391
392 if (RT_SUCCESS(rc))
393 {
394 /** @todo Validate checksum. */
395 rc = SharedClipboardMetaDataAdd(&pTransfer->Meta, data.pvData, data.cbData);
396 if ( RT_SUCCESS(rc)
397 && SharedClipboardMetaDataGetUsed(&pTransfer->Meta) == pTransfer->Hdr.cbMeta) /* Meta data transfer complete? */
398 {
399 void *pvMeta = SharedClipboardMetaDataMutableRaw(&pTransfer->Meta);
400 const size_t cbMeta = SharedClipboardMetaDataGetSize(&pTransfer->Meta);
401
402 rc = pTransfer->List.SetFromURIData(pvMeta, cbMeta, SHAREDCLIPBOARDURILIST_FLAGS_NONE);
403
404 if ( RT_SUCCESS(rc)
405 && g_pfnExtension)
406 {
407 VBOXCLIPBOARDEXTAREAPARMS parms;
408 RT_ZERO(parms);
409
410 parms.u.fn_register.pvData = pvMeta;
411 parms.u.fn_register.cbData = (uint32_t)cbMeta;
412
413 /* As the meta data is now complete, register a new clipboard on the host side. */
414 rc = g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_AREA_REGISTER, &parms, sizeof(parms));
415#ifdef LOG_ENABLED
416 AssertPtr(pTransfer->pState);
417 LogFlowFunc(("Registered new clipboard area by client %RU32 with rc=%Rrc\n",
418 pTransfer->pState->u32ClientID, rc));
419#endif
420 }
421
422 /* We're done processing the meta data, so just destroy it. */
423 SharedClipboardMetaDataDestroy(&pTransfer->Meta);
424 }
425 }
426 }
427 break;
428 }
429
430 case VBOX_SHARED_CLIPBOARD_FN_READ_DIR:
431 {
432 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_READ_DIR\n"));
433 AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED);
434 break;
435 }
436
437 case VBOX_SHARED_CLIPBOARD_FN_WRITE_DIR:
438 {
439 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_DIR\n"));
440 if ( cParms == VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_DIR
441 && pClientData->cTransfers) /* Some transfer in-flight? */
442 {
443 VBOXCLIPBOARDDIRDATA data;
444 RT_ZERO(data);
445 /* Note: Context ID (paParms[0]) not used yet. */
446 rc = HGCMSvcGetPv(&paParms[1], (void**)&data.pszPath, &data.cbPath);
447 if (RT_SUCCESS(rc))
448 rc = HGCMSvcGetU32(&paParms[2], &data.cbPath);
449 if (RT_SUCCESS(rc))
450 rc = HGCMSvcGetU32(&paParms[3], &data.fMode);
451
452 LogFlowFunc(("pszPath=%s, cbPath=%RU32, fMode=0x%x\n", data.pszPath, data.cbPath, data.fMode));
453
454 if (RT_SUCCESS(rc))
455 {
456 if (!VBoxSvcClipboardDirDataIsValid(&data))
457 rc = VERR_INVALID_PARAMETER;
458 }
459
460 if (RT_SUCCESS(rc))
461 {
462 const char *pszCacheDir = pTransfer->Cache.GetDirAbs();
463 char *pszDir = RTPathJoinA(pszCacheDir, data.pszPath);
464 if (pszDir)
465 {
466 rc = RTDirCreateFullPath(pszDir, data.fMode);
467 if (RT_SUCCESS(rc))
468 {
469 /* Add for having a proper rollback. */
470 int rc2 = pTransfer->Cache.AddDir(pszDir);
471 AssertRC(rc2);
472 }
473 }
474 else
475 rc = VERR_NO_MEMORY;
476 }
477 }
478 break;
479 }
480
481 case VBOX_SHARED_CLIPBOARD_FN_READ_FILE_HDR:
482 {
483 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_READ_FILE_HDR\n"));
484 AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED);
485 break;
486 }
487
488 case VBOX_SHARED_CLIPBOARD_FN_WRITE_FILE_HDR:
489 {
490 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_FILE_HDR\n"));
491 if ( cParms == VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_FILE_HDR
492 && pClientData->cTransfers) /* Some transfer in-flight? */
493 {
494 VBOXCLIPBOARDFILEHDR data;
495 RT_ZERO(data);
496 /* Note: Context ID (paParms[0]) not used yet. */
497 rc = HGCMSvcGetPv(&paParms[1], (void**)&data.pszFilePath, &data.cbFilePath);
498 if (RT_SUCCESS(rc))
499 rc = HGCMSvcGetU32(&paParms[2], &data.cbFilePath);
500 if (RT_SUCCESS(rc))
501 rc = HGCMSvcGetU32(&paParms[3], &data.fFlags);
502 if (RT_SUCCESS(rc))
503 rc = HGCMSvcGetU32(&paParms[4], &data.fMode);
504 if (RT_SUCCESS(rc))
505 rc = HGCMSvcGetU64(&paParms[5], &data.cbSize);
506
507 LogFlowFunc(("pszPath=%s, cbPath=%RU32, fMode=0x%x, cbSize=%RU64\n",
508 data.pszFilePath, data.cbFilePath, data.fMode, data.cbSize));
509
510 if (RT_SUCCESS(rc))
511 {
512 if (!VBoxSvcClipboardFileHdrIsValid(&data, &pTransfer->Hdr))
513 rc = VERR_INVALID_PARAMETER;
514
515 if (pTransfer->ObjCtx.pObj == NULL)
516 {
517 pTransfer->ObjCtx.pObj = new SharedClipboardURIObject(SharedClipboardURIObject::Type_File);
518 if (!pTransfer->ObjCtx.pObj) /** @todo Can this throw? */
519 rc = VERR_NO_MEMORY;
520 }
521 else /* There still is another object being processed? */
522 rc = VERR_WRONG_ORDER;
523 }
524
525 if (RT_SUCCESS(rc))
526 {
527 const char *pszCacheDir = pTransfer->Cache.GetDirAbs();
528
529 char pszPathAbs[RTPATH_MAX];
530 rc = RTPathJoin(pszPathAbs, sizeof(pszPathAbs), pszCacheDir, data.pszFilePath);
531 if (RT_SUCCESS(rc))
532 {
533 rc = SharedClipboardPathSanitize(pszPathAbs, sizeof(pszPathAbs));
534 if (RT_SUCCESS(rc))
535 {
536 SharedClipboardURIObject *pObj = vboxClipboardSvcURIObjCtxGetObj(&pTransfer->ObjCtx);
537
538 /** @todo Add sparse file support based on fFlags? (Use Open(..., fFlags | SPARSE). */
539 rc = pObj->OpenEx(pszPathAbs, SharedClipboardURIObject::View_Target,
540 RTFILE_O_CREATE_REPLACE | RTFILE_O_WRITE | RTFILE_O_DENY_WRITE,
541 (data.fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR);
542 if (RT_SUCCESS(rc))
543 {
544 rc = pObj->SetSize(data.cbSize);
545
546 /** @todo Unescape path before printing. */
547 LogRel2(("Clipboard: Transferring guest file '%s' to host (%RU64 bytes, mode 0x%x)\n",
548 pObj->GetDestPathAbs().c_str(), pObj->GetSize(), pObj->GetMode()));
549
550 if (pObj->IsComplete()) /* 0-byte file? We're done already. */
551 {
552 /** @todo Sanitize path. */
553 LogRel2(("Clipboard: Transferring guest file '%s' (0 bytes) to host complete\n",
554 pObj->GetDestPathAbs().c_str()));
555
556 vboxClipboardSvcURIObjCtxUninit(&pTransfer->ObjCtx);
557 }
558
559 /* Add for having a proper rollback. */
560 int rc2 = pTransfer->Cache.AddFile(pszPathAbs);
561 AssertRC(rc2);
562 }
563 else
564 LogRel(("Clipboard: Error opening/creating guest file '%s' on host, rc=%Rrc\n", pszPathAbs, rc));
565 }
566 }
567 }
568 }
569 break;
570 }
571
572 case VBOX_SHARED_CLIPBOARD_FN_READ_FILE_DATA:
573 {
574 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_READ_FILE_DATA\n"));
575 AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED);
576 break;
577 }
578
579 case VBOX_SHARED_CLIPBOARD_FN_WRITE_FILE_DATA:
580 {
581 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_FILE_DATA\n"));
582 if ( cParms == VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_FILE_DATA
583 && pClientData->cTransfers) /* Some transfer in-flight? */
584 {
585 VBOXCLIPBOARDFILEDATA data;
586 RT_ZERO(data);
587 /* Note: Context ID (paParms[0]) not used yet. */
588 rc = HGCMSvcGetPv(&paParms[1], (void**)&data.pvData, &data.cbData);
589 if (RT_SUCCESS(rc))
590 rc = HGCMSvcGetU32(&paParms[2], &data.cbData);
591 if (RT_SUCCESS(rc))
592 rc = HGCMSvcGetPv(&paParms[3], (void**)&data.pvChecksum, &data.cbChecksum);
593 if (RT_SUCCESS(rc))
594 rc = HGCMSvcGetU32(&paParms[4], &data.cbChecksum);
595
596 LogFlowFunc(("pvData=0x%p, cbData=%RU32\n", data.pvData, data.cbData));
597
598 if (RT_SUCCESS(rc))
599 {
600 if (!VBoxSvcClipboardFileDataIsValid(&data, &pTransfer->Hdr))
601 rc = VERR_INVALID_PARAMETER;
602
603 if (!vboxClipboardSvcURIObjCtxIsValid(&pTransfer->ObjCtx))
604 rc = VERR_WRONG_ORDER;
605 }
606
607 if (RT_SUCCESS(rc))
608 {
609 SharedClipboardURIObject *pObj = vboxClipboardSvcURIObjCtxGetObj(&pTransfer->ObjCtx);
610
611 uint32_t cbWritten;
612 rc = pObj->Write(data.pvData, data.cbData, &cbWritten);
613 if (RT_SUCCESS(rc))
614 {
615 Assert(cbWritten <= data.cbData);
616 if (cbWritten < data.cbData)
617 {
618 /** @todo What to do when the host's disk is full? */
619 rc = VERR_DISK_FULL;
620 }
621
622 if ( pObj->IsComplete()
623 || RT_FAILURE(rc))
624 vboxClipboardSvcURIObjCtxUninit(&pTransfer->ObjCtx);
625 }
626 else
627 LogRel(("Clipboard: Error writing guest file data for '%s', rc=%Rrc\n", pObj->GetDestPathAbs().c_str(), rc));
628 }
629 }
630 break;
631 }
632
633 case VBOX_SHARED_CLIPBOARD_FN_WRITE_CANCEL:
634 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_CANCEL\n"));
635 AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED);
636 break;
637
638 case VBOX_SHARED_CLIPBOARD_FN_WRITE_ERROR:
639 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_ERROR\n"));
640 AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED);
641 break;
642
643 default:
644 AssertMsgFailed(("Not implemented\n"));
645 break;
646 }
647
648 LogFlowFuncLeaveRC(rc);
649 return rc;
650}
651
652/**
653 * URI host handler for the Shared Clipboard host service.
654 *
655 * @returns VBox status code.
656 * @param u32Function Function number being called.
657 * @param cParms Number of function parameters supplied.
658 * @param paParms Array function parameters supplied.
659 */
660int vboxClipboardSvcURIHostHandler(uint32_t u32Function,
661 uint32_t cParms,
662 VBOXHGCMSVCPARM paParms[])
663{
664 RT_NOREF(cParms, paParms);
665
666 int rc = VERR_INVALID_PARAMETER; /* Play safe. */
667
668 switch (u32Function)
669 {
670 case VBOX_SHARED_CLIPBOARD_HOST_FN_CANCEL:
671 break;
672
673 case VBOX_SHARED_CLIPBOARD_HOST_FN_ERROR:
674 break;
675
676 default:
677 AssertMsgFailed(("Not implemented\n"));
678 break;
679
680 }
681
682 LogFlowFuncLeaveRC(rc);
683 return rc;
684}
685
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