VirtualBox

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

Last change on this file since 78943 was 78943, 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 78943 2019-06-03 19:13:27Z 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#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
420/**
421 * Reads the actual meta data from the host.
422 *
423 * @returns IPRT status code.
424 * @param idClient The client id returned by VbglR3ClipboardConnect().
425 * @param URIList Where to store received meta data.
426 */
427VBGLR3DECL(int) VbglR3ClipboardReadMetaData(HGCMCLIENTID idClient, SharedClipboardURIList &URIList)
428{
429 return vbglR3ClipboardReadMetaDataEx(idClient, URIList);
430}
431
432VBGLR3DECL(int) VbglR3ClipboardWriteMetaData(HGCMCLIENTID idClient, const SharedClipboardURIList &URIList)
433{
434 RT_NOREF(idClient, URIList);
435 return 0;
436}
437
438/**
439 * Reads a directory entry from the host.
440 *
441 * @returns IPRT status code.
442 * @param idClient The client id returned by VbglR3ClipboardConnect().
443 * @param pszDirname Where to store the directory name of the directory being created.
444 * @param cbDirname Size (in bytes) of where to store the directory name of the directory being created.
445 * @param pcbDirnameRecv Size (in bytes) of the actual directory name received.
446 * @param pfMode Where to store the directory creation mode.
447 */
448VBGLR3DECL(int) VbglR3ClipboardReadDir(HGCMCLIENTID idClient,
449 char *pszDirname,
450 uint32_t cbDirname,
451 uint32_t *pcbDirnameRecv,
452 uint32_t *pfMode)
453{
454 AssertPtrReturn(pszDirname, VERR_INVALID_POINTER);
455 AssertReturn(cbDirname, VERR_INVALID_PARAMETER);
456 AssertPtrReturn(pcbDirnameRecv, VERR_INVALID_POINTER);
457 AssertPtrReturn(pfMode, VERR_INVALID_POINTER);
458
459 VBoxClipboardReadDirMsg Msg;
460 RT_ZERO(Msg);
461
462 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_READ_DIR, VBOX_SHARED_CLIPBOARD_CPARMS_READ_DIR);
463 /** @todo Context ID not used yet. */
464 Msg.uContext.SetUInt32(0);
465 Msg.pvName.SetPtr(pszDirname, cbDirname);
466 Msg.cbName.SetUInt32(cbDirname);
467 Msg.fMode.SetUInt32(0);
468
469 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
470 if (RT_SUCCESS(rc))
471 {
472 /** @todo Context ID not used yet. */
473 rc = Msg.cbName.GetUInt32(pcbDirnameRecv); AssertRC(rc);
474 rc = Msg.fMode.GetUInt32(pfMode); AssertRC(rc);
475
476 AssertReturn(cbDirname >= *pcbDirnameRecv, VERR_TOO_MUCH_DATA);
477 }
478
479 return rc;
480}
481
482/**
483 * Writes a guest directory to the host.
484 *
485 * @returns IPRT status code.
486 * @param idClient The client id returned by VbglR3ClipboardConnect().
487 * @param pszPath Directory path.
488 * @param cbPath Size (in bytes) of directory path.
489 * @param fMode File mode for directory (IPRT-style).
490 */
491VBGLR3DECL(int) VbglR3ClipboardWriteDir(HGCMCLIENTID idClient,
492 const char *pszPath,
493 uint32_t cbPath,
494 uint32_t fMode)
495{
496 const size_t cchDir = strlen(pszPath);
497
498 if ( !cchDir
499 || cchDir > RTPATH_MAX
500 || cchDir != cbPath) /* UTF-8 */
501 return VERR_INVALID_PARAMETER;
502
503 const uint32_t cbPathSz = (uint32_t)cchDir + 1; /* Include termination. */
504
505 VBoxClipboardWriteDirMsg Msg;
506 RT_ZERO(Msg);
507
508 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_WRITE_DIR, VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_DIR);
509 /** @todo Context ID not used yet. */
510 Msg.pvName.SetPtr((void *)pszPath, (uint32_t)cbPathSz);
511 Msg.cbName.SetUInt32(cbPathSz);
512 Msg.fMode.SetUInt32(fMode);
513
514 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
515}
516
517/**
518 * Receives a file header from the host.
519 *
520 * @returns IPRT status code.
521 * @param idClient The client id returned by VbglR3ClipboardConnect().
522 * @param pszFilename Where to store the file name of the file being transferred.
523 * @param cbFilename Size (in bytes) of where to store the file name of the file being transferred.
524 * @param puFlags File transfer flags. Currently not being used.
525 * @param pfMode Where to store the file creation mode.
526 * @param pcbTotal Where to store the file size (in bytes).
527 */
528VBGLR3DECL(int) VbglR3ClipboardReadFileHdr(HGCMCLIENTID idClient,
529 char *pszFilename,
530 uint32_t cbFilename,
531 uint32_t *puFlags,
532 uint32_t *pfMode,
533 uint64_t *pcbTotal)
534{
535 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
536 AssertReturn(cbFilename, VERR_INVALID_PARAMETER);
537 AssertPtrReturn(puFlags, VERR_INVALID_POINTER);
538 AssertPtrReturn(pfMode, VERR_INVALID_POINTER);
539 AssertReturn(pcbTotal, VERR_INVALID_POINTER);
540
541 VBoxClipboardReadFileHdrMsg Msg;
542 RT_ZERO(Msg);
543
544 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
545 VBOX_SHARED_CLIPBOARD_FN_READ_FILE_HDR, VBOX_SHARED_CLIPBOARD_CPARMS_READ_FILE_HDR);
546 Msg.uContext.SetUInt32(0); /** @todo Not used yet. */
547 Msg.pvName.SetPtr(pszFilename, cbFilename);
548 Msg.cbName.SetUInt32(cbFilename);
549 Msg.uFlags.SetUInt32(0);
550 Msg.fMode.SetUInt32(0);
551 Msg.cbTotal.SetUInt64(0);
552
553 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
554 if (RT_SUCCESS(rc))
555 {
556 /** @todo Get context ID. */
557 rc = Msg.uFlags.GetUInt32(puFlags); AssertRC(rc);
558 rc = Msg.fMode.GetUInt32(pfMode); AssertRC(rc);
559 rc = Msg.cbTotal.GetUInt64(pcbTotal); AssertRC(rc);
560 }
561
562 return rc;
563}
564
565/**
566 * Writes a file header from the guest to the host.
567 *
568 * @returns VBox status code.
569 * @param idClient The client id returned by VbglR3ClipboardConnect().
570 * @param pszFilename File name this header belong to.
571 * @param cbFilename Size (in bytes) of file name.
572 * @param fFlags Transfer flags; not being used and will be ignored.
573 * @param fMode File mode.
574 * @param cbTotal File size (in bytes).
575 */
576VBGLR3DECL(int) VbglR3ClipboardWriteFileHdr(HGCMCLIENTID idClient, const char *pszFilename, uint32_t cbFilename,
577 uint32_t fFlags, uint32_t fMode, uint64_t cbTotal)
578{
579 RT_NOREF(fFlags);
580
581 const size_t cchFile = strlen(pszFilename);
582
583 if ( !cchFile
584 || cchFile > RTPATH_MAX
585 || cchFile != cbFilename)
586 return VERR_INVALID_PARAMETER;
587
588 const uint32_t cbFileSz = (uint32_t)cchFile + 1; /* Include termination. */
589
590 VBoxClipboardWriteFileHdrMsg MsgHdr;
591 RT_ZERO(MsgHdr);
592
593 VBGL_HGCM_HDR_INIT(&MsgHdr.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_WRITE_FILE_HDR, VBOX_SHARED_CLIPBOARD_CPARMS_READ_FILE_HDR);
594 MsgHdr.uContext.SetUInt32(0); /* Context ID; unused at the moment. */
595 MsgHdr.pvName.SetPtr((void *)pszFilename, (uint32_t)(cbFileSz));
596 MsgHdr.cbName.SetUInt32(cbFileSz);
597 MsgHdr.uFlags.SetUInt32(0); /* Flags; unused at the moment. */
598 MsgHdr.fMode.SetUInt32(fMode); /* File mode */
599 MsgHdr.cbTotal.SetUInt64(cbTotal); /* File size (in bytes). */
600
601 return VbglR3HGCMCall(&MsgHdr.hdr, sizeof(MsgHdr));
602}
603
604/**
605 * Reads a file data chunk from the host.
606 *
607 * @returns IPRT status code.
608 * @param idClient The client id returned by VbglR3ClipboardConnect().
609 * @param pvData Where to store the file data chunk.
610 * @param cbData Size (in bytes) of where to store the data chunk.
611 * @param pcbRead Size (in bytes) of the actual data chunk size read.
612 */
613VBGLR3DECL(int) VbglR3ClipboardReadFileData(HGCMCLIENTID idClient,
614 void *pvData,
615 uint32_t cbData,
616 uint32_t *pcbRead)
617{
618 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
619 AssertReturn(cbData, VERR_INVALID_PARAMETER);
620 AssertPtrReturn(pcbRead, VERR_INVALID_POINTER);
621
622 VBoxClipboardReadFileDataMsg Msg;
623 RT_ZERO(Msg);
624
625 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
626 VBOX_SHARED_CLIPBOARD_FN_READ_FILE_DATA, VBOX_SHARED_CLIPBOARD_CPARMS_READ_FILE_DATA);
627 Msg.uContext.SetUInt32(0);
628 Msg.pvData.SetPtr(pvData, cbData);
629 Msg.cbData.SetUInt32(0);
630 Msg.pvChecksum.SetPtr(NULL, 0);
631 Msg.cbChecksum.SetUInt32(0);
632
633 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
634 if (RT_SUCCESS(rc))
635 {
636 /** @todo Context ID not used yet. */
637 rc = Msg.cbData.GetUInt32(pcbRead); AssertRC(rc);
638 AssertReturn(cbData >= *pcbRead, VERR_TOO_MUCH_DATA);
639 /** @todo Add checksum support. */
640 }
641
642 return rc;
643}
644
645/**
646 * Writes a file data chunk to the host.
647 *
648 * @returns VBox status code.
649 * @param idClient The client id returned by VbglR3ClipboardConnect().
650 * @param pvData Data chunk to write.
651 * @param cbData Size (in bytes) of data chunk to write.
652 * @param pcbWritten Returns how many bytes written.
653 */
654VBGLR3DECL(int) VbglR3ClipboardWriteFileData(HGCMCLIENTID idClient, void *pvData, uint32_t cbData, uint32_t *pcbWritten)
655{
656 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
657 AssertReturn(cbData, VERR_INVALID_PARAMETER);
658 AssertPtrReturn(pcbWritten, VERR_INVALID_POINTER);
659
660 VBoxClipboardWriteFileDataMsg MsgData;
661 RT_ZERO(MsgData);
662
663 VBGL_HGCM_HDR_INIT(&MsgData.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_WRITE_FILE_DATA, VBOX_SHARED_CLIPBOARD_CPARMS_READ_FILE_DATA);
664 MsgData.uContext.SetUInt32(0); /* Context ID; unused at the moment. */
665 MsgData.pvData.SetPtr(pvData, cbData);
666 MsgData.cbData.SetUInt32(cbData);
667 MsgData.pvChecksum.SetPtr(NULL, 0);
668 MsgData.cbChecksum.SetUInt32(0);
669
670 int rc = VbglR3HGCMCall(&MsgData.hdr, sizeof(MsgData));
671 if (RT_SUCCESS(rc))
672 {
673 *pcbWritten = cbData;
674 }
675
676 return rc;
677}
678#endif /* VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */
679
680/**
681 * Reports (advertises) guest clipboard formats to the host.
682 *
683 * @returns VBox status code.
684 * @param idClient The client id returned by VbglR3ClipboardConnect().
685 * @param fFormats The formats to advertise.
686 */
687VBGLR3DECL(int) VbglR3ClipboardReportFormats(HGCMCLIENTID idClient, uint32_t fFormats)
688{
689 VBoxClipboardWriteFormatsMsg Msg;
690
691 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_REPORT_FORMATS, 1);
692 VbglHGCMParmUInt32Set(&Msg.formats, fFormats);
693
694 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
695}
696
697/**
698 * Sends guest clipboard data to the host.
699 *
700 * This is usually called in reply to a VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA message
701 * from the host.
702 *
703 * @returns VBox status code.
704 * @param idClient The client id returned by VbglR3ClipboardConnect().
705 * @param fFormat The format of the data.
706 * @param pv The data.
707 * @param cb The size of the data.
708 */
709static int vbglR3ClipboardWriteDataRaw(HGCMCLIENTID idClient, uint32_t fFormat, void *pv, uint32_t cb)
710{
711 VBoxClipboardWriteDataMsg Msg;
712 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_WRITE_DATA, 2);
713 VbglHGCMParmUInt32Set(&Msg.format, fFormat);
714 VbglHGCMParmPtrSet(&Msg.ptr, pv, cb);
715
716 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
717}
718
719/**
720 * Send guest clipboard data to the host.
721 *
722 * This is usually called in reply to a VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA message
723 * from the host.
724 *
725 * @returns VBox status code.
726 * @param idClient The client id returned by VbglR3ClipboardConnect().
727 * @param fFormat The format of the data.
728 * @param pv The data.
729 * @param cb The size of the data.
730 */
731VBGLR3DECL(int) VbglR3ClipboardWriteData(HGCMCLIENTID idClient, uint32_t fFormat, void *pv, uint32_t cb)
732{
733 int rc = vbglR3ClipboardWriteDataRaw(idClient, fFormat, pv, cb);
734#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
735 if (RT_FAILURE(rc))
736 {
737 int rc2 = vbglR3ClipboardWriteErrorInternal(idClient, rc);
738 if (RT_FAILURE(rc2))
739 LogFlowFunc(("Unable to send error (%Rrc) to host, rc=%Rrc\n", rc, rc2));
740 }
741#endif
742
743 return rc;
744}
745
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