VirtualBox

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

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

Shared Clipboard/URI: Update.

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette