VirtualBox

source: vbox/trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibClipboard.cpp@ 78946

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

Shared Clipboard/URI: Build fix.

  • Property svn:eol-style set to native
  • Property svn:keyword set to Id
  • Property svn:keywords set to Author Date Id Revision
File size: 28.1 KB
Line 
1/* $Id: VBoxGuestR3LibClipboard.cpp 78946 2019-06-03 19:46:30Z vboxsync $ */
2/** @file
3 * VBoxGuestR3Lib - Ring-3 Support Library for VirtualBox guest additions, Shared Clipboard.
4 */
5
6/*
7 * Copyright (C) 2007-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 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include <VBox/GuestHost/SharedClipboard.h>
32#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
33# include <VBox/GuestHost/SharedClipboard-uri.h>
34#endif
35#include <VBox/HostServices/VBoxClipboardSvc.h>
36#include <VBox/err.h>
37#include <iprt/assert.h>
38#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
39# include <iprt/dir.h>
40# include <iprt/file.h>
41# include <iprt/path.h>
42#endif
43#include <iprt/string.h>
44#include <iprt/cpp/ministring.h>
45
46#include "VBoxGuestR3LibInternal.h"
47
48
49/*********************************************************************************************************************************
50* Prototypes *
51*********************************************************************************************************************************/
52#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
53static int vbglR3ClipboardWriteErrorInternal(HGCMCLIENTID idClient, int rcErr);
54#endif
55
56
57/**
58 * Connects to the clipboard service.
59 *
60 * @returns VBox status code
61 * @param pidClient Where to put the client id on success. The client id
62 * must be passed to all the other clipboard calls.
63 */
64VBGLR3DECL(int) VbglR3ClipboardConnect(HGCMCLIENTID *pidClient)
65{
66 int rc = VbglR3HGCMConnect("VBoxSharedClipboard", pidClient);
67 if (rc == VERR_HGCM_SERVICE_NOT_FOUND)
68 rc = VINF_PERMISSION_DENIED;
69 return rc;
70}
71
72
73/**
74 * Disconnect from the clipboard service.
75 *
76 * @returns VBox status code.
77 * @param idClient The client id returned by VbglR3ClipboardConnect().
78 */
79VBGLR3DECL(int) VbglR3ClipboardDisconnect(HGCMCLIENTID idClient)
80{
81 return VbglR3HGCMDisconnect(idClient);
82}
83
84
85/**
86 * Get a host message.
87 *
88 * This will block until a message becomes available.
89 *
90 * @returns VBox status code.
91 * @param idClient The client id returned by VbglR3ClipboardConnect().
92 * @param pidMsg Where to store the message id.
93 * @param pfFormats Where to store the format(s) the message applies to.
94 */
95VBGLR3DECL(int) VbglR3ClipboardGetHostMsg(HGCMCLIENTID idClient, uint32_t *pidMsg, uint32_t *pfFormats)
96{
97 VBoxClipboardGetHostMsg Msg;
98
99 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_GET_HOST_MSG, 2);
100 VbglHGCMParmUInt32Set(&Msg.msg, 0);
101 VbglHGCMParmUInt32Set(&Msg.formats, 0);
102
103 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
104 if (RT_SUCCESS(rc))
105 {
106 int rc2 = VbglHGCMParmUInt32Get(&Msg.msg, pidMsg);
107 if (RT_SUCCESS(rc))
108 {
109 rc2 = VbglHGCMParmUInt32Get(&Msg.formats, pfFormats);
110 if (RT_SUCCESS(rc2))
111 return rc;
112 }
113 rc = rc2;
114 }
115 *pidMsg = UINT32_MAX - 1;
116 *pfFormats = UINT32_MAX;
117 return rc;
118}
119
120
121/**
122 * Reads data from the host clipboard.
123 *
124 * @returns VBox status code.
125 * @retval VINF_BUFFER_OVERFLOW If there is more data available than the caller provided buffer space for.
126 *
127 * @param idClient The client id returned by VbglR3ClipboardConnect().
128 * @param fFormat The format we're requesting the data in.
129 * @param pv Where to store the data.
130 * @param cb The size of the buffer pointed to by pv.
131 * @param pcb The actual size of the host clipboard data. May be larger than cb.
132 */
133VBGLR3DECL(int) VbglR3ClipboardReadData(HGCMCLIENTID idClient, uint32_t fFormat, void *pv, uint32_t cb, uint32_t *pcb)
134{
135 VBoxClipboardReadDataMsg Msg;
136
137 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_READ_DATA, 3);
138 VbglHGCMParmUInt32Set(&Msg.format, fFormat);
139 VbglHGCMParmPtrSet(&Msg.ptr, pv, cb);
140 VbglHGCMParmUInt32Set(&Msg.size, 0);
141
142 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
143 if (RT_SUCCESS(rc))
144 {
145 uint32_t cbActual;
146 int rc2 = VbglHGCMParmUInt32Get(&Msg.size, &cbActual);
147 if (RT_SUCCESS(rc2))
148 {
149 *pcb = cbActual;
150 if (cbActual > cb)
151 return VINF_BUFFER_OVERFLOW;
152 return rc;
153 }
154 rc = rc2;
155 }
156 return rc;
157}
158
159#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
160/**
161 * Reads a (meta) data header from the host.
162 *
163 * @returns IPRT status code.
164 * @param idClient The client id returned by VbglR3ClipboardConnect().
165 * @param pDataHdr Where to store the read meta data header.
166 */
167static int vbglR3ClipboardReadDataHdr(HGCMCLIENTID idClient, PVBOXCLIPBOARDDATAHDR pDataHdr)
168{
169 AssertPtrReturn(pDataHdr, VERR_INVALID_POINTER);
170
171 VBoxClipboardReadDataHdrMsg Msg;
172 RT_ZERO(Msg);
173 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
174 VBOX_SHARED_CLIPBOARD_FN_READ_DATA_HDR, VBOX_SHARED_CLIPBOARD_CPARMS_READ_DATA_HDR);
175 Msg.uContext.SetUInt32(0);
176 Msg.uFlags.SetUInt32(0);
177 Msg.uScreenId.SetUInt32(0);
178 Msg.cbTotal.SetUInt64(0);
179 Msg.cbMeta.SetUInt32(0);
180 Msg.pvMetaFmt.SetPtr(pDataHdr->pvMetaFmt, pDataHdr->cbMetaFmt);
181 Msg.cbMetaFmt.SetUInt32(0);
182 Msg.cObjects.SetUInt64(0);
183 Msg.enmCompression.SetUInt32(0);
184 Msg.enmChecksumType.SetUInt32(0);
185 Msg.pvChecksum.SetPtr(pDataHdr->pvChecksum, pDataHdr->cbChecksum);
186 Msg.cbChecksum.SetUInt32(0);
187
188 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
189 if (RT_SUCCESS(rc))
190 {
191 /* Msg.uContext not needed here. */
192 Msg.uFlags.GetUInt32(&pDataHdr->uFlags);
193 Msg.uScreenId.GetUInt32(&pDataHdr->uScreenId);
194 Msg.cbTotal.GetUInt64(&pDataHdr->cbTotal);
195 Msg.cbMeta.GetUInt32(&pDataHdr->cbMeta);
196 Msg.cbMetaFmt.GetUInt32(&pDataHdr->cbMetaFmt);
197 Msg.cObjects.GetUInt64(&pDataHdr->cObjects);
198 Msg.enmCompression.GetUInt32(&pDataHdr->enmCompression);
199 Msg.enmChecksumType.GetUInt32((uint32_t *)&pDataHdr->enmChecksumType);
200 Msg.cbChecksum.GetUInt32(&pDataHdr->cbChecksum);
201 }
202
203 LogFlowFuncLeaveRC(rc);
204 return rc;
205}
206
207/**
208 * Reads a (meta) data chunk from the host.
209 *
210 * @returns IPRT status code.
211 * @param idClient The client id returned by VbglR3ClipboardConnect().
212 * @param pDataHdr Data header to use. Need for accounting and stuff.
213 * @param pvData Where to store the received data from the host.
214 * @param cbData Size (in bytes) of where to store the received data.
215 * @param pcbDataRecv Where to store the received amount of data (in bytes).
216 */
217static int vbglR3ClipboardReadDataChunk(HGCMCLIENTID idClient, PVBOXCLIPBOARDDATAHDR pDataHdr,
218 void *pvData, uint32_t cbData, uint32_t *pcbDataRecv)
219{
220 AssertPtrReturn(pDataHdr, VERR_INVALID_POINTER);
221 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
222 AssertReturn(cbData, VERR_INVALID_PARAMETER);
223 AssertPtrNullReturn(pcbDataRecv, VERR_INVALID_POINTER);
224
225 LogFlowFunc(("pvDate=%p, cbData=%RU32\n", pvData, cbData));
226
227 VBoxClipboardReadDataChunkMsg Msg;
228 RT_ZERO(Msg);
229
230 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
231 VBOX_SHARED_CLIPBOARD_FN_READ_DATA_CHUNK, VBOX_SHARED_CLIPBOARD_CPARMS_READ_DATA_CHUNK);
232 Msg.pvData.SetPtr(pvData, cbData);
233 Msg.cbData.SetUInt32(0);
234 Msg.pvChecksum.SetPtr(NULL, 0);
235 Msg.cbChecksum.SetUInt32(0);
236
237 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
238 if (RT_SUCCESS(rc))
239 {
240 uint32_t cbDataRecv;
241 rc = Msg.cbData.GetUInt32(&cbDataRecv);
242 AssertRC(rc);
243 if (RT_SUCCESS(rc))
244 {
245 /** @todo Use checksum for validating the received data. */
246 if (pcbDataRecv)
247 *pcbDataRecv = cbDataRecv;
248 LogFlowFuncLeaveRC(rc);
249 return rc;
250 }
251 }
252
253 /* failure */
254 LogFlowFuncLeaveRC(rc);
255 return rc;
256}
257
258/**
259 * Helper function for reading the actual clipboard (meta) data from the host. Do not call directly.
260 *
261 * @returns IPRT status code.
262 * @param idClient The client id returned by VbglR3ClipboardConnect().
263 * @param pDataHdr Where to store the data header data.
264 * @param pMetaData Returns the received meta data. Needs to be free'd by the caller.
265 */
266static int vbglR3ClipboardReadMetaDataLoop(HGCMCLIENTID idClient, PVBOXCLIPBOARDDATAHDR pDataHdr,
267 PSHAREDCLIPBOARDMETADATA pMetaData)
268{
269 AssertPtrReturn(pDataHdr, VERR_INVALID_POINTER);
270 AssertPtrReturn(pMetaData, VERR_INVALID_POINTER);
271
272 int rc;
273 uint32_t cbDataRecv;
274
275 LogFlowFuncEnter();
276
277 rc = vbglR3ClipboardReadDataHdr(idClient, pDataHdr);
278 if (RT_FAILURE(rc))
279 return rc;
280
281 LogFlowFunc(("cbTotal=%RU64, cbMeta=%RU32, cObjects=%RU32\n", pDataHdr->cbTotal, pDataHdr->cbMeta, pDataHdr->cObjects));
282 if (pDataHdr->cbMeta)
283 {
284 uint64_t cbDataTmp = 0;
285 void *pvDataTmp = RTMemAlloc(pDataHdr->cbMeta);
286 if (!pvDataTmp)
287 rc = VERR_NO_MEMORY;
288
289 if (RT_SUCCESS(rc))
290 {
291 const uint32_t cbMaxChunkSize = VBOX_SHARED_CLIPBOARD_MAX_CHUNK_SIZE;
292
293 uint8_t *pvDataOff = (uint8_t *)pvDataTmp;
294 while (cbDataTmp < pDataHdr->cbMeta)
295 {
296 rc = vbglR3ClipboardReadDataChunk(idClient, pDataHdr,
297 pvDataOff, RT_MIN(pDataHdr->cbMeta - cbDataTmp, cbMaxChunkSize),
298 &cbDataRecv);
299 if (RT_SUCCESS(rc))
300 {
301 LogFlowFunc(("cbDataRecv=%RU32, cbDataTmp=%RU64\n", cbDataRecv, cbDataTmp));
302 Assert(cbDataTmp + cbDataRecv <= pDataHdr->cbMeta);
303 cbDataTmp += cbDataRecv;
304 pvDataOff += cbDataRecv;
305 }
306 else
307 break;
308 }
309
310 if (RT_SUCCESS(rc))
311 {
312 Assert(cbDataTmp == pDataHdr->cbMeta);
313
314 LogFlowFunc(("Received %RU64 bytes of data\n", cbDataTmp));
315
316 pMetaData->pvMeta = pvDataTmp;
317 pMetaData->cbMeta = cbDataTmp;
318 pMetaData->cbUsed = cbDataTmp;
319 }
320 else
321 RTMemFree(pvDataTmp);
322 }
323 }
324 else
325 SharedClipboardMetaDataDestroy(pMetaData);
326
327 LogFlowFuncLeaveRC(rc);
328 return rc;
329}
330
331/**
332 * Reads the actual meta data from the host, extended version.
333 *
334 * @returns IPRT status code.
335 * @param idClient The client id returned by VbglR3ClipboardConnect().
336 * @param URIList Where to store received meta data.
337 */
338static int vbglR3ClipboardReadMetaDataEx(HGCMCLIENTID idClient, SharedClipboardURIList &URIList)
339{
340 /* The rest is optional. */
341
342 VBOXCLIPBOARDDATAHDR dataHdr;
343 RT_ZERO(dataHdr);
344
345 dataHdr.cbMetaFmt = VBOX_SHARED_CLIPBOARD_MAX_CHUNK_SIZE;
346 dataHdr.pvMetaFmt = RTMemAlloc(dataHdr.cbMetaFmt);
347 if (!dataHdr.pvMetaFmt)
348 return VERR_NO_MEMORY;
349
350 SHAREDCLIPBOARDMETADATA dataMeta;
351 SharedClipboardMetaDataInit(&dataMeta);
352
353 int rc = vbglR3ClipboardReadMetaDataLoop(idClient, &dataHdr, &dataMeta);
354 if (RT_SUCCESS(rc))
355 {
356 /**
357 * Check if this is an URI event. If so, let VbglR3 do all the actual
358 * data transfer + file/directory creation internally without letting
359 * the caller know.
360 *
361 * This keeps the actual (guest OS-)dependent client (like VBoxClient /
362 * VBoxTray) small by not having too much redundant code.
363 */
364 Assert(dataHdr.cbMetaFmt);
365 AssertPtr(dataHdr.pvMetaFmt);
366 if (SharedClipboardMIMEHasFileURLs((char *)dataHdr.pvMetaFmt, dataHdr.cbMetaFmt)) /* URI data. */
367 {
368 rc = URIList.SetFromURIData(dataMeta.pvMeta, dataMeta.cbMeta, 0 /* fFlags */);
369
370 #if 0
371 if (RT_SUCCESS(rc))
372 rc = vbglR3ClipboardReadURIData(idClient, &dataHdr);
373
374 if (RT_SUCCESS(rc))
375 {
376 if (pvData)
377 {
378 /* Reuse data buffer to fill in the transformed URI file list. */
379 RTMemFree(pvData);
380 pvData = NULL;
381 }
382
383 #if 0
384 RTCString strData = lstURI.GetRootEntries(clipboardCache.GetDirAbs());
385 Assert(!strData.isEmpty());
386
387 cbData = strData.length() + 1;
388 LogFlowFunc(("URI list has %zu bytes\n", cbData));
389
390 pvData = RTMemAlloc(cbData);
391 if (pvData)
392 {
393 memcpy(pvData, strData.c_str(), cbData);
394 }
395 else
396 rc = VERR_NO_MEMORY;
397 #endif
398 }
399 #endif
400 }
401 else /* Raw data. */
402 {
403 /** @todo Implement this. */
404 }
405
406 SharedClipboardMetaDataDestroy(&dataMeta);
407 }
408
409 if (dataHdr.pvMetaFmt)
410 {
411 RTMemFree(dataHdr.pvMetaFmt);
412 dataHdr.pvMetaFmt = NULL;
413 }
414
415 LogFlowFuncLeaveRC(rc);
416 return rc;
417}
418
419/**
420 * Reads the actual meta data from the host.
421 *
422 * @returns IPRT status code.
423 * @param idClient The client id returned by VbglR3ClipboardConnect().
424 * @param URIList Where to store received meta data.
425 */
426VBGLR3DECL(int) VbglR3ClipboardReadMetaData(HGCMCLIENTID idClient, SharedClipboardURIList &URIList)
427{
428 return vbglR3ClipboardReadMetaDataEx(idClient, URIList);
429}
430
431VBGLR3DECL(int) VbglR3ClipboardWriteMetaData(HGCMCLIENTID idClient, const SharedClipboardURIList &URIList)
432{
433 RT_NOREF(idClient, URIList);
434 return 0;
435}
436
437/**
438 * Reads a directory entry from the host.
439 *
440 * @returns IPRT status code.
441 * @param idClient The client id returned by VbglR3ClipboardConnect().
442 * @param pszDirname Where to store the directory name of the directory being created.
443 * @param cbDirname Size (in bytes) of where to store the directory name of the directory being created.
444 * @param pcbDirnameRecv Size (in bytes) of the actual directory name received.
445 * @param pfMode Where to store the directory creation mode.
446 */
447VBGLR3DECL(int) VbglR3ClipboardReadDir(HGCMCLIENTID idClient,
448 char *pszDirname,
449 uint32_t cbDirname,
450 uint32_t *pcbDirnameRecv,
451 uint32_t *pfMode)
452{
453 AssertPtrReturn(pszDirname, VERR_INVALID_POINTER);
454 AssertReturn(cbDirname, VERR_INVALID_PARAMETER);
455 AssertPtrReturn(pcbDirnameRecv, VERR_INVALID_POINTER);
456 AssertPtrReturn(pfMode, VERR_INVALID_POINTER);
457
458 VBoxClipboardReadDirMsg Msg;
459 RT_ZERO(Msg);
460
461 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_READ_DIR, VBOX_SHARED_CLIPBOARD_CPARMS_READ_DIR);
462 /** @todo Context ID not used yet. */
463 Msg.uContext.SetUInt32(0);
464 Msg.pvName.SetPtr(pszDirname, cbDirname);
465 Msg.cbName.SetUInt32(cbDirname);
466 Msg.fMode.SetUInt32(0);
467
468 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
469 if (RT_SUCCESS(rc))
470 {
471 /** @todo Context ID not used yet. */
472 rc = Msg.cbName.GetUInt32(pcbDirnameRecv); AssertRC(rc);
473 rc = Msg.fMode.GetUInt32(pfMode); AssertRC(rc);
474
475 AssertReturn(cbDirname >= *pcbDirnameRecv, VERR_TOO_MUCH_DATA);
476 }
477
478 return rc;
479}
480
481/**
482 * Writes a guest directory to the host.
483 *
484 * @returns IPRT status code.
485 * @param idClient The client id returned by VbglR3ClipboardConnect().
486 * @param pszPath Directory path.
487 * @param cbPath Size (in bytes) of directory path.
488 * @param fMode File mode for directory (IPRT-style).
489 */
490VBGLR3DECL(int) VbglR3ClipboardWriteDir(HGCMCLIENTID idClient,
491 const char *pszPath,
492 uint32_t cbPath,
493 uint32_t fMode)
494{
495 const size_t cchDir = strlen(pszPath);
496
497 if ( !cchDir
498 || cchDir > RTPATH_MAX
499 || cchDir != cbPath) /* UTF-8 */
500 return VERR_INVALID_PARAMETER;
501
502 const uint32_t cbPathSz = (uint32_t)cchDir + 1; /* Include termination. */
503
504 VBoxClipboardWriteDirMsg Msg;
505 RT_ZERO(Msg);
506
507 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_WRITE_DIR, VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_DIR);
508 /** @todo Context ID not used yet. */
509 Msg.pvName.SetPtr((void *)pszPath, (uint32_t)cbPathSz);
510 Msg.cbName.SetUInt32(cbPathSz);
511 Msg.fMode.SetUInt32(fMode);
512
513 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
514}
515
516/**
517 * Receives a file header from the host.
518 *
519 * @returns IPRT status code.
520 * @param idClient The client id returned by VbglR3ClipboardConnect().
521 * @param pszFilename Where to store the file name of the file being transferred.
522 * @param cbFilename Size (in bytes) of where to store the file name of the file being transferred.
523 * @param puFlags File transfer flags. Currently not being used.
524 * @param pfMode Where to store the file creation mode.
525 * @param pcbTotal Where to store the file size (in bytes).
526 */
527VBGLR3DECL(int) VbglR3ClipboardReadFileHdr(HGCMCLIENTID idClient,
528 char *pszFilename,
529 uint32_t cbFilename,
530 uint32_t *puFlags,
531 uint32_t *pfMode,
532 uint64_t *pcbTotal)
533{
534 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
535 AssertReturn(cbFilename, VERR_INVALID_PARAMETER);
536 AssertPtrReturn(puFlags, VERR_INVALID_POINTER);
537 AssertPtrReturn(pfMode, VERR_INVALID_POINTER);
538 AssertReturn(pcbTotal, VERR_INVALID_POINTER);
539
540 VBoxClipboardReadFileHdrMsg Msg;
541 RT_ZERO(Msg);
542
543 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
544 VBOX_SHARED_CLIPBOARD_FN_READ_FILE_HDR, VBOX_SHARED_CLIPBOARD_CPARMS_READ_FILE_HDR);
545 Msg.uContext.SetUInt32(0); /** @todo Not used yet. */
546 Msg.pvName.SetPtr(pszFilename, cbFilename);
547 Msg.cbName.SetUInt32(cbFilename);
548 Msg.uFlags.SetUInt32(0);
549 Msg.fMode.SetUInt32(0);
550 Msg.cbTotal.SetUInt64(0);
551
552 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
553 if (RT_SUCCESS(rc))
554 {
555 /** @todo Get context ID. */
556 rc = Msg.uFlags.GetUInt32(puFlags); AssertRC(rc);
557 rc = Msg.fMode.GetUInt32(pfMode); AssertRC(rc);
558 rc = Msg.cbTotal.GetUInt64(pcbTotal); AssertRC(rc);
559 }
560
561 return rc;
562}
563
564/**
565 * Writes a file header from the guest to the host.
566 *
567 * @returns VBox status code.
568 * @param idClient The client id returned by VbglR3ClipboardConnect().
569 * @param pszFilename File name this header belong to.
570 * @param cbFilename Size (in bytes) of file name.
571 * @param fFlags Transfer flags; not being used and will be ignored.
572 * @param fMode File mode.
573 * @param cbTotal File size (in bytes).
574 */
575VBGLR3DECL(int) VbglR3ClipboardWriteFileHdr(HGCMCLIENTID idClient, const char *pszFilename, uint32_t cbFilename,
576 uint32_t fFlags, uint32_t fMode, uint64_t cbTotal)
577{
578 RT_NOREF(fFlags);
579
580 const size_t cchFile = strlen(pszFilename);
581
582 if ( !cchFile
583 || cchFile > RTPATH_MAX
584 || cchFile != cbFilename)
585 return VERR_INVALID_PARAMETER;
586
587 const uint32_t cbFileSz = (uint32_t)cchFile + 1; /* Include termination. */
588
589 VBoxClipboardWriteFileHdrMsg MsgHdr;
590 RT_ZERO(MsgHdr);
591
592 VBGL_HGCM_HDR_INIT(&MsgHdr.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_WRITE_FILE_HDR, VBOX_SHARED_CLIPBOARD_CPARMS_READ_FILE_HDR);
593 MsgHdr.uContext.SetUInt32(0); /* Context ID; unused at the moment. */
594 MsgHdr.pvName.SetPtr((void *)pszFilename, (uint32_t)(cbFileSz));
595 MsgHdr.cbName.SetUInt32(cbFileSz);
596 MsgHdr.uFlags.SetUInt32(0); /* Flags; unused at the moment. */
597 MsgHdr.fMode.SetUInt32(fMode); /* File mode */
598 MsgHdr.cbTotal.SetUInt64(cbTotal); /* File size (in bytes). */
599
600 return VbglR3HGCMCall(&MsgHdr.hdr, sizeof(MsgHdr));
601}
602
603/**
604 * Reads a file data chunk from the host.
605 *
606 * @returns IPRT status code.
607 * @param idClient The client id returned by VbglR3ClipboardConnect().
608 * @param pvData Where to store the file data chunk.
609 * @param cbData Size (in bytes) of where to store the data chunk.
610 * @param pcbRead Size (in bytes) of the actual data chunk size read.
611 */
612VBGLR3DECL(int) VbglR3ClipboardReadFileData(HGCMCLIENTID idClient,
613 void *pvData,
614 uint32_t cbData,
615 uint32_t *pcbRead)
616{
617 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
618 AssertReturn(cbData, VERR_INVALID_PARAMETER);
619 AssertPtrReturn(pcbRead, VERR_INVALID_POINTER);
620
621 VBoxClipboardReadFileDataMsg Msg;
622 RT_ZERO(Msg);
623
624 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
625 VBOX_SHARED_CLIPBOARD_FN_READ_FILE_DATA, VBOX_SHARED_CLIPBOARD_CPARMS_READ_FILE_DATA);
626 Msg.uContext.SetUInt32(0);
627 Msg.pvData.SetPtr(pvData, cbData);
628 Msg.cbData.SetUInt32(0);
629 Msg.pvChecksum.SetPtr(NULL, 0);
630 Msg.cbChecksum.SetUInt32(0);
631
632 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
633 if (RT_SUCCESS(rc))
634 {
635 /** @todo Context ID not used yet. */
636 rc = Msg.cbData.GetUInt32(pcbRead); AssertRC(rc);
637 AssertReturn(cbData >= *pcbRead, VERR_TOO_MUCH_DATA);
638 /** @todo Add checksum support. */
639 }
640
641 return rc;
642}
643
644/**
645 * Writes a file data chunk to the host.
646 *
647 * @returns VBox status code.
648 * @param idClient The client id returned by VbglR3ClipboardConnect().
649 * @param pvData Data chunk to write.
650 * @param cbData Size (in bytes) of data chunk to write.
651 * @param pcbWritten Returns how many bytes written.
652 */
653VBGLR3DECL(int) VbglR3ClipboardWriteFileData(HGCMCLIENTID idClient, void *pvData, uint32_t cbData, uint32_t *pcbWritten)
654{
655 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
656 AssertReturn(cbData, VERR_INVALID_PARAMETER);
657 AssertPtrReturn(pcbWritten, VERR_INVALID_POINTER);
658
659 VBoxClipboardWriteFileDataMsg MsgData;
660 RT_ZERO(MsgData);
661
662 VBGL_HGCM_HDR_INIT(&MsgData.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_WRITE_FILE_DATA, VBOX_SHARED_CLIPBOARD_CPARMS_READ_FILE_DATA);
663 MsgData.uContext.SetUInt32(0); /* Context ID; unused at the moment. */
664 MsgData.pvData.SetPtr(pvData, cbData);
665 MsgData.cbData.SetUInt32(cbData);
666 MsgData.pvChecksum.SetPtr(NULL, 0);
667 MsgData.cbChecksum.SetUInt32(0);
668
669 int rc = VbglR3HGCMCall(&MsgData.hdr, sizeof(MsgData));
670 if (RT_SUCCESS(rc))
671 {
672 *pcbWritten = cbData;
673 }
674
675 return rc;
676}
677#endif /* VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */
678
679/**
680 * Reports (advertises) guest clipboard formats to the host.
681 *
682 * @returns VBox status code.
683 * @param idClient The client id returned by VbglR3ClipboardConnect().
684 * @param fFormats The formats to advertise.
685 */
686VBGLR3DECL(int) VbglR3ClipboardReportFormats(HGCMCLIENTID idClient, uint32_t fFormats)
687{
688 VBoxClipboardWriteFormatsMsg Msg;
689
690 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_REPORT_FORMATS, 1);
691 VbglHGCMParmUInt32Set(&Msg.formats, fFormats);
692
693 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
694}
695
696/**
697 * Sends guest clipboard data to the host.
698 *
699 * This is usually called in reply to a VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA message
700 * from the host.
701 *
702 * @returns VBox status code.
703 * @param idClient The client id returned by VbglR3ClipboardConnect().
704 * @param fFormat The format of the data.
705 * @param pv The data.
706 * @param cb The size of the data.
707 */
708static int vbglR3ClipboardWriteDataRaw(HGCMCLIENTID idClient, uint32_t fFormat, void *pv, uint32_t cb)
709{
710 VBoxClipboardWriteDataMsg Msg;
711 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_WRITE_DATA, 2);
712 VbglHGCMParmUInt32Set(&Msg.format, fFormat);
713 VbglHGCMParmPtrSet(&Msg.ptr, pv, cb);
714
715 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
716}
717
718/**
719 * Send guest clipboard data to the host.
720 *
721 * This is usually called in reply to a VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA message
722 * from the host.
723 *
724 * @returns VBox status code.
725 * @param idClient The client id returned by VbglR3ClipboardConnect().
726 * @param fFormat The format of the data.
727 * @param pv The data.
728 * @param cb The size of the data.
729 */
730VBGLR3DECL(int) VbglR3ClipboardWriteData(HGCMCLIENTID idClient, uint32_t fFormat, void *pv, uint32_t cb)
731{
732 int rc = vbglR3ClipboardWriteDataRaw(idClient, fFormat, pv, cb);
733#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
734 if (RT_FAILURE(rc))
735 {
736 int rc2 = vbglR3ClipboardWriteErrorInternal(idClient, rc);
737 if (RT_FAILURE(rc2))
738 LogFlowFunc(("Unable to send error (%Rrc) to host, rc=%Rrc\n", rc, rc2));
739 }
740#endif
741
742 return rc;
743}
744
745#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
746/**
747 * Writes an error to the host.
748 *
749 * @returns IPRT status code.
750 * @param idClient The client id returned by VbglR3ClipboardConnect().
751 * @param rcErr Error (IPRT-style) to send.
752 */
753static int vbglR3ClipboardWriteErrorInternal(HGCMCLIENTID idClient, int rcErr)
754{
755 VBoxClipboardWriteErrorMsg Msg;
756 RT_ZERO(Msg);
757
758 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_WRITE_ERROR, 2);
759 /** @todo Context ID not used yet. */
760 Msg.uContext.SetUInt32(0);
761 Msg.rc.SetUInt32((uint32_t)rcErr); /* uint32_t vs. int. */
762
763 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
764
765 /*
766 * Never return an error if the host did not accept the error at the current
767 * time. This can be due to the host not having any appropriate callbacks
768 * set which would handle that error.
769 *
770 * bird: Looks like VERR_NOT_SUPPORTED is what the host will return if it
771 * doesn't an appropriate callback. The code used to ignore ALL errors
772 * the host would return, also relevant ones.
773 */
774 if (RT_FAILURE(rc))
775 LogFlowFunc(("Sending error %Rrc failed with rc=%Rrc\n", rcErr, rc));
776 if (rc == VERR_NOT_SUPPORTED)
777 rc = VINF_SUCCESS;
778
779 return rc;
780}
781
782/**
783 * Writes an error back to the host.
784 *
785 * @returns IPRT status code.
786 * @param idClient The client id returned by VbglR3ClipboardConnect().
787 * @param rcErr Error (IPRT-style) to send.
788 */
789VBGLR3DECL(int) vbglR3ClipboardWriteError(HGCMCLIENTID idClient, int rcErr)
790{
791 return vbglR3ClipboardWriteErrorInternal(idClient, rcErr);
792}
793#endif /* VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */
794
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