VirtualBox

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

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

Shared Clipboard/URI: Update (more glue code, transfer callbacks).

  • Property svn:eol-style set to native
  • Property svn:keyword set to Id
  • Property svn:keywords set to Author Date Id Revision
File size: 29.1 KB
Line 
1/* $Id: VBoxGuestR3LibClipboard.cpp 79027 2019-06-06 14:47:16Z 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 */
167VBGLR3DECL(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 * Sends a guest clipboard data header to the host.
209 *
210 * This is usually called in reply to a VBOX_SHARED_CLIPBOARD_HOST_MSG_WRITE_DATA_HDR message
211 * from the host.
212 *
213 * @returns VBox status code.
214 * @param idClient The client id returned by VbglR3ClipboardConnect().
215 * @param pDataHdr Pointer to data header to send.
216 */
217VBGLR3DECL(int) VbglR3ClipboardWriteDataHdr(HGCMCLIENTID idClient, const PVBOXCLIPBOARDDATAHDR pDataHdr)
218{
219 VBoxClipboardWriteDataHdrMsg Msg;
220 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_WRITE_DATA_HDR, VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_DATA_HDR);
221
222 VbglHGCMParmUInt32Set(&Msg.uFlags, pDataHdr->uFlags); /** @todo Not used yet. */
223 VbglHGCMParmUInt32Set(&Msg.uScreenId, pDataHdr->uScreenId); /** @todo Not used for guest->host (yet). */
224 VbglHGCMParmUInt64Set(&Msg.cbTotal, pDataHdr->cbTotal);
225 VbglHGCMParmUInt32Set(&Msg.cbMeta, pDataHdr->cbMeta);
226 VbglHGCMParmPtrSet(&Msg.cbMetaFmt, pDataHdr->pvMetaFmt, pDataHdr->cbMetaFmt);
227 VbglHGCMParmUInt32Set(&Msg.cbMetaFmt, pDataHdr->cbMetaFmt);
228 VbglHGCMParmUInt64Set(&Msg.cObjects, pDataHdr->cObjects);
229 VbglHGCMParmUInt32Set(&Msg.enmCompression, pDataHdr->enmCompression); /** @todo Not used yet. */
230 VbglHGCMParmUInt32Set(&Msg.enmChecksumType, pDataHdr->enmChecksumType); /** @todo Not used yet. */
231 VbglHGCMParmPtrSet(&Msg.cbChecksum, pDataHdr->pvChecksum, pDataHdr->cbChecksum); /** @todo Not used yet. */
232 VbglHGCMParmUInt32Set(&Msg.cbChecksum, pDataHdr->cbChecksum); /** @todo Not used yet. */
233
234 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
235}
236
237/**
238 * Reads a (meta) data chunk from the host.
239 *
240 * @returns IPRT status code.
241 * @param idClient The client id returned by VbglR3ClipboardConnect().
242 * @param pDataHdr Data header to use. Need for accounting and stuff.
243 * @param pvData Where to store the received data from the host.
244 * @param cbData Size (in bytes) of where to store the received data.
245 * @param pcbDataRecv Where to store the received amount of data (in bytes).
246 */
247static int vbglR3ClipboardReadDataChunk(HGCMCLIENTID idClient, PVBOXCLIPBOARDDATAHDR pDataHdr,
248 void *pvData, uint32_t cbData, uint32_t *pcbDataRecv)
249{
250 AssertPtrReturn(pDataHdr, VERR_INVALID_POINTER);
251 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
252 AssertReturn(cbData, VERR_INVALID_PARAMETER);
253 AssertPtrNullReturn(pcbDataRecv, VERR_INVALID_POINTER);
254
255 LogFlowFunc(("pvDate=%p, cbData=%RU32\n", pvData, cbData));
256
257 VBoxClipboardReadDataChunkMsg Msg;
258 RT_ZERO(Msg);
259
260 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
261 VBOX_SHARED_CLIPBOARD_FN_READ_DATA_CHUNK, VBOX_SHARED_CLIPBOARD_CPARMS_READ_DATA_CHUNK);
262 Msg.pvData.SetPtr(pvData, cbData);
263 Msg.cbData.SetUInt32(0);
264 Msg.pvChecksum.SetPtr(NULL, 0);
265 Msg.cbChecksum.SetUInt32(0);
266
267 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
268 if (RT_SUCCESS(rc))
269 {
270 uint32_t cbDataRecv;
271 rc = Msg.cbData.GetUInt32(&cbDataRecv);
272 AssertRC(rc);
273 if (RT_SUCCESS(rc))
274 {
275 /** @todo Use checksum for validating the received data. */
276 if (pcbDataRecv)
277 *pcbDataRecv = cbDataRecv;
278 LogFlowFuncLeaveRC(rc);
279 return rc;
280 }
281 }
282
283 /* failure */
284 LogFlowFuncLeaveRC(rc);
285 return rc;
286}
287
288/**
289 * Helper function for reading the actual clipboard (meta) data from the host. Do not call directly.
290 *
291 * @returns IPRT status code.
292 * @param idClient The client id returned by VbglR3ClipboardConnect().
293 * @param pDataHdr Pointer to data header to use.
294 * @param pvMeta Where to store the received meta data.
295 * @param cbMeta Size (in bytes) of meta data buffer.
296 * @param pcbRead How much bytes were read on success. Optional.
297 */
298static int vbglR3ClipboardReadMetaDataLoop(HGCMCLIENTID idClient, PVBOXCLIPBOARDDATAHDR pDataHdr,
299 void *pvMeta, uint32_t cbMeta, uint32_t *pcbRead)
300{
301 AssertPtrReturn(pDataHdr, VERR_INVALID_POINTER);
302 AssertPtrReturn(pvMeta, VERR_INVALID_POINTER);
303
304 LogFlowFuncEnter();
305
306 int rc = VINF_SUCCESS;
307
308 uint32_t cbReadTotal = 0;
309
310 LogFlowFunc(("cbTotal=%RU64, cbMeta=%RU32, cObjects=%RU32\n", pDataHdr->cbTotal, pDataHdr->cbMeta, pDataHdr->cObjects));
311 if (pDataHdr->cbMeta)
312 {
313 uint32_t cbToRead = RT_MIN(cbMeta, pDataHdr->cbMeta);
314 while (cbToRead)
315 {
316 uint32_t cbRead;
317 rc = vbglR3ClipboardReadDataChunk(idClient, pDataHdr,
318 (uint8_t *)pvMeta + cbReadTotal, cbToRead, &cbRead);
319 if (RT_FAILURE(rc))
320 break;
321
322 Assert(cbToRead >= cbRead);
323 cbToRead -= cbRead;
324
325 cbReadTotal += cbRead;
326 }
327 }
328
329 if (RT_SUCCESS(rc))
330 {
331 if (pcbRead)
332 *pcbRead = cbReadTotal;
333 }
334
335 LogFlowFuncLeaveRC(rc);
336 return rc;
337}
338
339/**
340 * Reads the actual meta data from the host, extended version.
341 *
342 * @returns IPRT status code.
343 * @param idClient The client id returned by VbglR3ClipboardConnect().
344 * @param pDataHdr Pointer to data header to use.
345 * @param pvMeta Where to store the received meta data.
346 * @param cbMeta Size (in bytes) of meta data buffer.
347 * @param pcbRead How much bytes were read on success. Optional.
348 */
349static int vbglR3ClipboardReadMetaDataInternal(HGCMCLIENTID idClient, PVBOXCLIPBOARDDATAHDR pDataHdr,
350 void *pvMeta, uint32_t cbMeta, uint32_t *pcbRead)
351{
352 LogFlowFuncEnter();
353
354 int rc = vbglR3ClipboardReadMetaDataLoop(idClient, pDataHdr, pvMeta, cbMeta, pcbRead);
355
356 LogFlowFuncLeaveRC(rc);
357 return rc;
358}
359
360/**
361 * Reads the actual meta data from the host, extended version.
362 *
363 * @returns IPRT status code.
364 * @param idClient The client id returned by VbglR3ClipboardConnect().
365 * @param pvMeta Where to store the received meta data.
366 * @param cbMeta Size (in bytes) of meta data buffer.
367 * @param pcbRead How much bytes were read on success. Optional.
368 */
369VBGLR3DECL(int) VbglR3ClipboardReadMetaDataEx(HGCMCLIENTID idClient, PVBOXCLIPBOARDDATAHDR pDataHdr,
370 void *pvMeta, uint32_t cbMeta, uint32_t *pcbRead)
371{
372 return vbglR3ClipboardReadMetaDataInternal(idClient, pDataHdr, pvMeta, cbMeta, pcbRead);
373}
374
375/**
376 * Reads the actual meta data from the host.
377 *
378 * @returns IPRT status code.
379 * @param idClient The client id returned by VbglR3ClipboardConnect().
380 * @param pvMeta Where to store the received meta data.
381 * @param cbMeta Size (in bytes) of meta data buffer.
382 * @param pcbRead How much bytes were read on success. Optional.
383 */
384VBGLR3DECL(int) VbglR3ClipboardReadMetaData(HGCMCLIENTID idClient, PVBOXCLIPBOARDDATAHDR pDataHdr,
385 void *pvMeta, uint32_t cbMeta, uint32_t *pcbRead)
386{
387 return VbglR3ClipboardReadMetaDataEx(idClient, pDataHdr, pvMeta, cbMeta, pcbRead);
388}
389
390/**
391 * Writes the actual meta data to the host, extended version.
392 *
393 * @returns IPRT status code.
394 * @param idClient The client id returned by VbglR3ClipboardConnect().
395 * @param pvMeta Pointer to meta data buffer.
396 * @param cbMeta Size (in bytes) of meta data buffer.
397 * @param pcbWritten How much bytes were written on success. Optional.
398 */
399VBGLR3DECL(int) VbglR3ClipboardWriteMetaDataEx(HGCMCLIENTID idClient, const void *pvMeta, uint32_t cbMeta, uint32_t *pcbWritten)
400{
401 RT_NOREF(idClient, pvMeta, cbMeta, pcbWritten);
402 return 0;
403}
404
405/**
406 * Writes the actual meta data to the host.
407 *
408 * @returns IPRT status code.
409 * @param idClient The client id returned by VbglR3ClipboardConnect().
410 * @param pvMeta Pointer to meta data buffer.
411 * @param cbMeta Size (in bytes) of meta data buffer.
412 * @param pcbWritten How much bytes were written on success. Optional.
413 */
414VBGLR3DECL(int) VbglR3ClipboardWriteMetaData(HGCMCLIENTID idClient, const void *pvMeta, uint32_t cbMeta, uint32_t *pcbWritten)
415{
416 return VbglR3ClipboardWriteMetaDataEx(idClient, pvMeta, cbMeta, pcbWritten);
417}
418
419/**
420 * Reads a directory entry from the host.
421 *
422 * @returns IPRT status code.
423 * @param idClient The client id returned by VbglR3ClipboardConnect().
424 * @param pszDirname Where to store the directory name of the directory being created.
425 * @param cbDirname Size (in bytes) of where to store the directory name of the directory being created.
426 * @param pcbDirnameRecv Size (in bytes) of the actual directory name received.
427 * @param pfMode Where to store the directory creation mode.
428 */
429VBGLR3DECL(int) VbglR3ClipboardReadDir(HGCMCLIENTID idClient,
430 char *pszDirname,
431 uint32_t cbDirname,
432 uint32_t *pcbDirnameRecv,
433 uint32_t *pfMode)
434{
435 AssertPtrReturn(pszDirname, VERR_INVALID_POINTER);
436 AssertReturn(cbDirname, VERR_INVALID_PARAMETER);
437 AssertPtrReturn(pcbDirnameRecv, VERR_INVALID_POINTER);
438 AssertPtrReturn(pfMode, VERR_INVALID_POINTER);
439
440 VBoxClipboardReadDirMsg Msg;
441 RT_ZERO(Msg);
442
443 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_READ_DIR, VBOX_SHARED_CLIPBOARD_CPARMS_READ_DIR);
444 /** @todo Context ID not used yet. */
445 Msg.uContext.SetUInt32(0);
446 Msg.pvName.SetPtr(pszDirname, cbDirname);
447 Msg.cbName.SetUInt32(cbDirname);
448 Msg.fMode.SetUInt32(0);
449
450 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
451 if (RT_SUCCESS(rc))
452 {
453 /** @todo Context ID not used yet. */
454 rc = Msg.cbName.GetUInt32(pcbDirnameRecv); AssertRC(rc);
455 rc = Msg.fMode.GetUInt32(pfMode); AssertRC(rc);
456
457 AssertReturn(cbDirname >= *pcbDirnameRecv, VERR_TOO_MUCH_DATA);
458 }
459
460 return rc;
461}
462
463/**
464 * Writes a guest directory to the host.
465 *
466 * @returns IPRT status code.
467 * @param idClient The client id returned by VbglR3ClipboardConnect().
468 * @param pszPath Directory path.
469 * @param cbPath Size (in bytes) of directory path.
470 * @param fMode File mode for directory (IPRT-style).
471 */
472VBGLR3DECL(int) VbglR3ClipboardWriteDir(HGCMCLIENTID idClient,
473 const char *pszPath,
474 uint32_t cbPath,
475 uint32_t fMode)
476{
477 const size_t cchDir = strlen(pszPath);
478
479 if ( !cchDir
480 || cchDir > RTPATH_MAX
481 || cchDir != cbPath) /* UTF-8 */
482 return VERR_INVALID_PARAMETER;
483
484 const uint32_t cbPathSz = (uint32_t)cchDir + 1; /* Include termination. */
485
486 VBoxClipboardWriteDirMsg Msg;
487 RT_ZERO(Msg);
488
489 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_WRITE_DIR, VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_DIR);
490 /** @todo Context ID not used yet. */
491 Msg.pvName.SetPtr((void *)pszPath, (uint32_t)cbPathSz);
492 Msg.cbName.SetUInt32(cbPathSz);
493 Msg.fMode.SetUInt32(fMode);
494
495 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
496}
497
498/**
499 * Receives a file header from the host.
500 *
501 * @returns IPRT status code.
502 * @param idClient The client id returned by VbglR3ClipboardConnect().
503 * @param pszFilename Where to store the file name of the file being transferred.
504 * @param cbFilename Size (in bytes) of where to store the file name of the file being transferred.
505 * @param puFlags File transfer flags. Currently not being used.
506 * @param pfMode Where to store the file creation mode.
507 * @param pcbTotal Where to store the file size (in bytes).
508 */
509VBGLR3DECL(int) VbglR3ClipboardReadFileHdr(HGCMCLIENTID idClient,
510 char *pszFilename,
511 uint32_t cbFilename,
512 uint32_t *puFlags,
513 uint32_t *pfMode,
514 uint64_t *pcbTotal)
515{
516 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
517 AssertReturn(cbFilename, VERR_INVALID_PARAMETER);
518 AssertPtrReturn(puFlags, VERR_INVALID_POINTER);
519 AssertPtrReturn(pfMode, VERR_INVALID_POINTER);
520 AssertReturn(pcbTotal, VERR_INVALID_POINTER);
521
522 VBoxClipboardReadFileHdrMsg Msg;
523 RT_ZERO(Msg);
524
525 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
526 VBOX_SHARED_CLIPBOARD_FN_READ_FILE_HDR, VBOX_SHARED_CLIPBOARD_CPARMS_READ_FILE_HDR);
527 Msg.uContext.SetUInt32(0); /** @todo Not used yet. */
528 Msg.pvName.SetPtr(pszFilename, cbFilename);
529 Msg.cbName.SetUInt32(cbFilename);
530 Msg.uFlags.SetUInt32(0);
531 Msg.fMode.SetUInt32(0);
532 Msg.cbTotal.SetUInt64(0);
533
534 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
535 if (RT_SUCCESS(rc))
536 {
537 /** @todo Get context ID. */
538 rc = Msg.uFlags.GetUInt32(puFlags); AssertRC(rc);
539 rc = Msg.fMode.GetUInt32(pfMode); AssertRC(rc);
540 rc = Msg.cbTotal.GetUInt64(pcbTotal); AssertRC(rc);
541 }
542
543 return rc;
544}
545
546/**
547 * Writes a file header from the guest to the host.
548 *
549 * @returns VBox status code.
550 * @param idClient The client id returned by VbglR3ClipboardConnect().
551 * @param pszFilename File name this header belong to.
552 * @param cbFilename Size (in bytes) of file name.
553 * @param fFlags Transfer flags; not being used and will be ignored.
554 * @param fMode File mode.
555 * @param cbTotal File size (in bytes).
556 */
557VBGLR3DECL(int) VbglR3ClipboardWriteFileHdr(HGCMCLIENTID idClient, const char *pszFilename, uint32_t cbFilename,
558 uint32_t fFlags, uint32_t fMode, uint64_t cbTotal)
559{
560 RT_NOREF(fFlags);
561
562 const size_t cchFile = strlen(pszFilename);
563
564 if ( !cchFile
565 || cchFile > RTPATH_MAX
566 || cchFile != cbFilename)
567 return VERR_INVALID_PARAMETER;
568
569 const uint32_t cbFileSz = (uint32_t)cchFile + 1; /* Include termination. */
570
571 VBoxClipboardWriteFileHdrMsg MsgHdr;
572 RT_ZERO(MsgHdr);
573
574 VBGL_HGCM_HDR_INIT(&MsgHdr.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_WRITE_FILE_HDR, VBOX_SHARED_CLIPBOARD_CPARMS_READ_FILE_HDR);
575 MsgHdr.uContext.SetUInt32(0); /* Context ID; unused at the moment. */
576 MsgHdr.pvName.SetPtr((void *)pszFilename, (uint32_t)(cbFileSz));
577 MsgHdr.cbName.SetUInt32(cbFileSz);
578 MsgHdr.uFlags.SetUInt32(0); /* Flags; unused at the moment. */
579 MsgHdr.fMode.SetUInt32(fMode); /* File mode */
580 MsgHdr.cbTotal.SetUInt64(cbTotal); /* File size (in bytes). */
581
582 return VbglR3HGCMCall(&MsgHdr.hdr, sizeof(MsgHdr));
583}
584
585/**
586 * Reads a file data chunk from the host.
587 *
588 * @returns IPRT status code.
589 * @param idClient The client id returned by VbglR3ClipboardConnect().
590 * @param pvData Where to store the file data chunk.
591 * @param cbData Size (in bytes) of where to store the data chunk.
592 * @param pcbRead Size (in bytes) of the actual data chunk size read.
593 */
594VBGLR3DECL(int) VbglR3ClipboardReadFileData(HGCMCLIENTID idClient,
595 void *pvData,
596 uint32_t cbData,
597 uint32_t *pcbRead)
598{
599 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
600 AssertReturn(cbData, VERR_INVALID_PARAMETER);
601 AssertPtrReturn(pcbRead, VERR_INVALID_POINTER);
602
603 VBoxClipboardReadFileDataMsg Msg;
604 RT_ZERO(Msg);
605
606 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
607 VBOX_SHARED_CLIPBOARD_FN_READ_FILE_DATA, VBOX_SHARED_CLIPBOARD_CPARMS_READ_FILE_DATA);
608 Msg.uContext.SetUInt32(0);
609 Msg.pvData.SetPtr(pvData, cbData);
610 Msg.cbData.SetUInt32(0);
611 Msg.pvChecksum.SetPtr(NULL, 0);
612 Msg.cbChecksum.SetUInt32(0);
613
614 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
615 if (RT_SUCCESS(rc))
616 {
617 /** @todo Context ID not used yet. */
618 rc = Msg.cbData.GetUInt32(pcbRead); AssertRC(rc);
619 AssertReturn(cbData >= *pcbRead, VERR_TOO_MUCH_DATA);
620 /** @todo Add checksum support. */
621 }
622
623 return rc;
624}
625
626/**
627 * Writes a file data chunk to the host.
628 *
629 * @returns VBox status code.
630 * @param idClient The client id returned by VbglR3ClipboardConnect().
631 * @param pvData Data chunk to write.
632 * @param cbData Size (in bytes) of data chunk to write.
633 * @param pcbWritten Returns how many bytes written.
634 */
635VBGLR3DECL(int) VbglR3ClipboardWriteFileData(HGCMCLIENTID idClient, void *pvData, uint32_t cbData, uint32_t *pcbWritten)
636{
637 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
638 AssertReturn(cbData, VERR_INVALID_PARAMETER);
639 AssertPtrReturn(pcbWritten, VERR_INVALID_POINTER);
640
641 VBoxClipboardWriteFileDataMsg MsgData;
642 RT_ZERO(MsgData);
643
644 VBGL_HGCM_HDR_INIT(&MsgData.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_WRITE_FILE_DATA, VBOX_SHARED_CLIPBOARD_CPARMS_READ_FILE_DATA);
645 MsgData.uContext.SetUInt32(0); /* Context ID; unused at the moment. */
646 MsgData.pvData.SetPtr(pvData, cbData);
647 MsgData.cbData.SetUInt32(cbData);
648 MsgData.pvChecksum.SetPtr(NULL, 0);
649 MsgData.cbChecksum.SetUInt32(0);
650
651 int rc = VbglR3HGCMCall(&MsgData.hdr, sizeof(MsgData));
652 if (RT_SUCCESS(rc))
653 {
654 *pcbWritten = cbData;
655 }
656
657 return rc;
658}
659#endif /* VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */
660
661/**
662 * Reports (advertises) guest clipboard formats to the host.
663 *
664 * @returns VBox status code.
665 * @param idClient The client id returned by VbglR3ClipboardConnect().
666 * @param fFormats The formats to advertise.
667 */
668VBGLR3DECL(int) VbglR3ClipboardReportFormats(HGCMCLIENTID idClient, uint32_t fFormats)
669{
670 VBoxClipboardWriteFormatsMsg Msg;
671
672 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_REPORT_FORMATS, VBOX_SHARED_CLIPBOARD_CPARMS_FORMATS);
673 VbglHGCMParmUInt32Set(&Msg.formats, fFormats);
674
675 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
676}
677
678/**
679 * Sends guest clipboard data to the host.
680 *
681 * This is usually called in reply to a VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA message
682 * from the host.
683 *
684 * @returns VBox status code.
685 * @param idClient The client id returned by VbglR3ClipboardConnect().
686 * @param fFormat The format of the data.
687 * @param pv The data.
688 * @param cb The size of the data.
689 */
690static int vbglR3ClipboardWriteDataRaw(HGCMCLIENTID idClient, uint32_t fFormat, void *pv, uint32_t cb)
691{
692 VBoxClipboardWriteDataMsg Msg;
693 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_WRITE_DATA, VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_DATA);
694 VbglHGCMParmUInt32Set(&Msg.format, fFormat);
695 VbglHGCMParmPtrSet(&Msg.ptr, pv, cb);
696
697 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
698}
699
700/**
701 * Send guest clipboard data to the host.
702 *
703 * This is usually called in reply to a VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA message
704 * from the host.
705 *
706 * @returns VBox status code.
707 * @param idClient The client id returned by VbglR3ClipboardConnect().
708 * @param fFormat The format of the data.
709 * @param pv The data.
710 * @param cb The size of the data.
711 */
712VBGLR3DECL(int) VbglR3ClipboardWriteData(HGCMCLIENTID idClient, uint32_t fFormat, void *pv, uint32_t cb)
713{
714 int rc = vbglR3ClipboardWriteDataRaw(idClient, fFormat, pv, cb);
715#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
716 if (RT_FAILURE(rc))
717 {
718 int rc2 = vbglR3ClipboardWriteErrorInternal(idClient, rc);
719 if (RT_FAILURE(rc2))
720 LogFlowFunc(("Unable to send error (%Rrc) to host, rc=%Rrc\n", rc, rc2));
721 }
722#endif
723
724 return rc;
725}
726
727#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
728/**
729 * Writes an error to the host.
730 *
731 * @returns IPRT status code.
732 * @param idClient The client id returned by VbglR3ClipboardConnect().
733 * @param rcErr Error (IPRT-style) to send.
734 */
735static int vbglR3ClipboardWriteErrorInternal(HGCMCLIENTID idClient, int rcErr)
736{
737 VBoxClipboardWriteErrorMsg Msg;
738 RT_ZERO(Msg);
739
740 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_WRITE_ERROR, 2);
741 /** @todo Context ID not used yet. */
742 Msg.uContext.SetUInt32(0);
743 Msg.rc.SetUInt32((uint32_t)rcErr); /* uint32_t vs. int. */
744
745 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
746
747 /*
748 * Never return an error if the host did not accept the error at the current
749 * time. This can be due to the host not having any appropriate callbacks
750 * set which would handle that error.
751 *
752 * bird: Looks like VERR_NOT_SUPPORTED is what the host will return if it
753 * doesn't an appropriate callback. The code used to ignore ALL errors
754 * the host would return, also relevant ones.
755 */
756 if (RT_FAILURE(rc))
757 LogFlowFunc(("Sending error %Rrc failed with rc=%Rrc\n", rcErr, rc));
758 if (rc == VERR_NOT_SUPPORTED)
759 rc = VINF_SUCCESS;
760
761 return rc;
762}
763
764/**
765 * Writes an error back to the host.
766 *
767 * @returns IPRT status code.
768 * @param idClient The client id returned by VbglR3ClipboardConnect().
769 * @param rcErr Error (IPRT-style) to send.
770 */
771VBGLR3DECL(int) vbglR3ClipboardWriteError(HGCMCLIENTID idClient, int rcErr)
772{
773 return vbglR3ClipboardWriteErrorInternal(idClient, rcErr);
774}
775#endif /* VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */
776
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