VirtualBox

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

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

Shared Clipboard/URI: First commit; work in progress.

  • Property svn:eol-style set to native
  • Property svn:keyword set to Id
  • Property svn:keywords set to Author Date Id Revision
File size: 21.0 KB
Line 
1/* $Id: VBoxGuestR3LibClipboard.cpp 78307 2019-04-26 06:41:46Z vboxsync $ */
2/** @file
3 * VBoxGuestR3Lib - Ring-3 Support Library for VirtualBox guest additions, 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.215389.xyz. 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#include <iprt/string.h>
39#include <iprt/cpp/ministring.h>
40#include "VBoxGuestR3LibInternal.h"
41
42
43/*********************************************************************************************************************************
44* Prototypes *
45*********************************************************************************************************************************/
46#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
47static int vbglR3ClipboardSendErrorInternal(HGCMCLIENTID idClient, int rcErr);
48static int vbglR3ClipboardSendURIData(HGCMCLIENTID idClient, const void *pvData, size_t cbData);
49#endif
50
51
52/**
53 * Connects to the clipboard service.
54 *
55 * @returns VBox status code
56 * @param pidClient Where to put the client id on success. The client id
57 * must be passed to all the other clipboard calls.
58 */
59VBGLR3DECL(int) VbglR3ClipboardConnect(HGCMCLIENTID *pidClient)
60{
61 int rc = VbglR3HGCMConnect("VBoxSharedClipboard", pidClient);
62 if (rc == VERR_HGCM_SERVICE_NOT_FOUND)
63 rc = VINF_PERMISSION_DENIED;
64 return rc;
65}
66
67
68/**
69 * Disconnect from the clipboard service.
70 *
71 * @returns VBox status code.
72 * @param idClient The client id returned by VbglR3ClipboardConnect().
73 */
74VBGLR3DECL(int) VbglR3ClipboardDisconnect(HGCMCLIENTID idClient)
75{
76 return VbglR3HGCMDisconnect(idClient);
77}
78
79
80/**
81 * Get a host message.
82 *
83 * This will block until a message becomes available.
84 *
85 * @returns VBox status code.
86 * @param idClient The client id returned by VbglR3ClipboardConnect().
87 * @param pidMsg Where to store the message id.
88 * @param pfFormats Where to store the format(s) the message applies to.
89 */
90VBGLR3DECL(int) VbglR3ClipboardGetHostMsg(HGCMCLIENTID idClient, uint32_t *pidMsg, uint32_t *pfFormats)
91{
92 VBoxClipboardGetHostMsg Msg;
93
94 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_GET_HOST_MSG, 2);
95 VbglHGCMParmUInt32Set(&Msg.msg, 0);
96 VbglHGCMParmUInt32Set(&Msg.formats, 0);
97
98 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
99 if (RT_SUCCESS(rc))
100 {
101 int rc2 = VbglHGCMParmUInt32Get(&Msg.msg, pidMsg);
102 if (RT_SUCCESS(rc))
103 {
104 rc2 = VbglHGCMParmUInt32Get(&Msg.formats, pfFormats);
105 if (RT_SUCCESS(rc2))
106 return rc;
107 }
108 rc = rc2;
109 }
110 *pidMsg = UINT32_MAX - 1;
111 *pfFormats = UINT32_MAX;
112 return rc;
113}
114
115
116/**
117 * Reads data from the host clipboard.
118 *
119 * @returns VBox status code.
120 * @retval VINF_BUFFER_OVERFLOW If there is more data available than the caller provided buffer space for.
121 *
122 * @param idClient The client id returned by VbglR3ClipboardConnect().
123 * @param fFormat The format we're requesting the data in.
124 * @param pv Where to store the data.
125 * @param cb The size of the buffer pointed to by pv.
126 * @param pcb The actual size of the host clipboard data. May be larger than cb.
127 */
128VBGLR3DECL(int) VbglR3ClipboardReadData(HGCMCLIENTID idClient, uint32_t fFormat, void *pv, uint32_t cb, uint32_t *pcb)
129{
130 VBoxClipboardReadData Msg;
131
132 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_READ_DATA, 3);
133 VbglHGCMParmUInt32Set(&Msg.format, fFormat);
134 VbglHGCMParmPtrSet(&Msg.ptr, pv, cb);
135 VbglHGCMParmUInt32Set(&Msg.size, 0);
136
137 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
138 if (RT_SUCCESS(rc))
139 {
140 uint32_t cbActual;
141 int rc2 = VbglHGCMParmUInt32Get(&Msg.size, &cbActual);
142 if (RT_SUCCESS(rc2))
143 {
144 *pcb = cbActual;
145 if (cbActual > cb)
146 return VINF_BUFFER_OVERFLOW;
147 return rc;
148 }
149 rc = rc2;
150 }
151 return rc;
152}
153
154
155/**
156 * Writes (advertises) guest clipboard formats to the host.
157 *
158 * @returns VBox status code.
159 * @param idClient The client id returned by VbglR3ClipboardConnect().
160 * @param fFormats The formats to advertise.
161 */
162VBGLR3DECL(int) VbglR3ClipboardWriteFormats(HGCMCLIENTID idClient, uint32_t fFormats)
163{
164 VBoxClipboardWriteFormats Msg;
165
166 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_WRITE_FORMATS, 1);
167 VbglHGCMParmUInt32Set(&Msg.formats, fFormats);
168
169 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
170}
171
172/**
173 * Sends guest clipboard data to the host.
174 *
175 * This is usually called in reply to a VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA message
176 * from the host.
177 *
178 * @returns VBox status code.
179 * @param idClient The client id returned by VbglR3ClipboardConnect().
180 * @param fFormat The format of the data.
181 * @param pv The data.
182 * @param cb The size of the data.
183 */
184static int vbglR3ClipboardWriteDataRaw(HGCMCLIENTID idClient, uint32_t fFormat, void *pv, uint32_t cb)
185{
186 VBoxClipboardWriteData Msg;
187 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_WRITE_DATA, 2);
188 VbglHGCMParmUInt32Set(&Msg.format, fFormat);
189 VbglHGCMParmPtrSet(&Msg.ptr, pv, cb);
190
191 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
192}
193
194/**
195 * Send guest clipboard data to the host.
196 *
197 * This is usually called in reply to a VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA message
198 * from the host.
199 *
200 * @returns VBox status code.
201 * @param idClient The client id returned by VbglR3ClipboardConnect().
202 * @param fFormat The format of the data.
203 * @param pv The data.
204 * @param cb The size of the data.
205 */
206VBGLR3DECL(int) VbglR3ClipboardWriteData(HGCMCLIENTID idClient, uint32_t fFormat, void *pv, uint32_t cb)
207{
208 int rc;
209#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
210 if (fFormat == VBOX_SHARED_CLIPBOARD_FMT_URI_LIST)
211 {
212 rc = vbglR3ClipboardSendURIData(idClient, pv, cb);
213 }
214 else
215#else
216 RT_NOREF(fFormat);
217#endif
218 rc = vbglR3ClipboardWriteDataRaw(idClient, fFormat, pv, cb);
219
220 if (RT_FAILURE(rc))
221 {
222 int rc2 = vbglR3ClipboardSendErrorInternal(idClient, rc);
223 if (RT_FAILURE(rc2))
224 LogFlowFunc(("Unable to send error (%Rrc) to host, rc=%Rrc\n", rc, rc2));
225 }
226
227 return rc;
228}
229
230#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
231/**
232 * Guest -> Host
233 * Utility function to send clipboard data from guest to the host.
234 *
235 * @returns IPRT status code.
236 * @param idClient The client id returned by VbglR3ClipboardConnect().
237 * @param pvData Data block to send.
238 * @param cbData Size (in bytes) of data block to send.
239 * @param pDataHdr Data header to use -- needed for accounting.
240 */
241static int vbglR3ClipboardSendDataInternal(HGCMCLIENTID idClient,
242 void *pvData, uint64_t cbData, PVBOXCLIPBOARDDATAHDR pDataHdr)
243{
244 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
245 AssertReturn(cbData, VERR_INVALID_PARAMETER);
246 AssertPtrReturn(pDataHdr, VERR_INVALID_POINTER);
247
248 VBoxClipboardWriteDataHdrMsg MsgHdr;
249 RT_ZERO(MsgHdr);
250
251 VBGL_HGCM_HDR_INIT(&MsgHdr.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_WRITE_DATA_HDR, 12);
252 MsgHdr.uContext.SetUInt32(0); /** @todo Not used yet. */
253 MsgHdr.uFlags.SetUInt32(0); /** @todo Not used yet. */
254 MsgHdr.uScreenId.SetUInt32(0); /** @todo Not used for guest->host (yet). */
255 MsgHdr.cbTotal.SetUInt64(pDataHdr->cbTotal);
256 MsgHdr.cbMeta.SetUInt32(pDataHdr->cbMeta);
257 MsgHdr.pvMetaFmt.SetPtr(pDataHdr->pvMetaFmt, pDataHdr->cbMetaFmt);
258 MsgHdr.cbMetaFmt.SetUInt32(pDataHdr->cbMetaFmt);
259 MsgHdr.cObjects.SetUInt64(pDataHdr->cObjects);
260 MsgHdr.enmCompression.SetUInt32(0); /** @todo Not used yet. */
261 MsgHdr.enmChecksumType.SetUInt32(RTDIGESTTYPE_INVALID); /** @todo Not used yet. */
262 MsgHdr.pvChecksum.SetPtr(NULL, 0); /** @todo Not used yet. */
263 MsgHdr.cbChecksum.SetUInt32(0); /** @todo Not used yet. */
264
265 int rc = VbglR3HGCMCall(&MsgHdr.hdr, sizeof(MsgHdr));
266
267 LogFlowFunc(("cbTotal=%RU64, cbMeta=%RU32, cObjects=%RU64, rc=%Rrc\n",
268 pDataHdr->cbTotal, pDataHdr->cbMeta, pDataHdr->cObjects, rc));
269
270 if (RT_SUCCESS(rc))
271 {
272 VBoxClipboardWriteDataChunkMsg MsgData;
273 RT_ZERO(MsgData);
274
275 VBGL_HGCM_HDR_INIT(&MsgData.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_WRITE_DATA_CHUNK, 5);
276 MsgData.uContext.SetUInt32(0); /** @todo Not used yet. */
277 MsgData.pvChecksum.SetPtr(NULL, 0); /** @todo Not used yet. */
278 MsgData.cbChecksum.SetUInt32(0); /** @todo Not used yet. */
279
280 uint32_t cbCurChunk;
281 const uint32_t cbMaxChunk = VBOX_SHARED_CLIPBOARD_MAX_CHUNK_SIZE;
282 uint32_t cbSent = 0;
283
284 HGCMFunctionParameter *pParm = &MsgData.pvData;
285
286 while (cbSent < cbData)
287 {
288 cbCurChunk = RT_MIN(cbData - cbSent, cbMaxChunk);
289 pParm->SetPtr(static_cast<uint8_t *>(pvData) + cbSent, cbCurChunk);
290
291 MsgData.cbData.SetUInt32(cbCurChunk);
292
293 rc = VbglR3HGCMCall(&MsgData.hdr, sizeof(MsgData));
294 if (RT_FAILURE(rc))
295 break;
296
297 cbSent += cbCurChunk;
298 }
299
300 LogFlowFunc(("cbMaxChunk=%RU32, cbData=%RU64, cbSent=%RU32, rc=%Rrc\n",
301 cbMaxChunk, cbData, cbSent, rc));
302
303 if (RT_SUCCESS(rc))
304 Assert(cbSent == cbData);
305 }
306
307 LogFlowFuncLeaveRC(rc);
308 return rc;
309}
310
311/**
312 * Guest -> Host
313 * Utility function to send a guest directory to the host.
314 *
315 * @returns IPRT status code.
316 * @param idClient The client id returned by VbglR3ClipboardConnect().
317 * @param pObj URI object containing the directory to send.
318 */
319static int vbglR3ClipboardSendDir(HGCMCLIENTID idClient, SharedClipboardURIObject *pObj)
320{
321 AssertPtrReturn(pObj, VERR_INVALID_POINTER);
322 AssertReturn(pObj->GetType() == SharedClipboardURIObject::Type_Directory, VERR_INVALID_PARAMETER);
323
324 RTCString strPath = pObj->GetDestPathAbs();
325 LogFlowFunc(("strDir=%s (%zu), fMode=0x%x\n",
326 strPath.c_str(), strPath.length(), pObj->GetMode()));
327
328 if (strPath.length() > RTPATH_MAX)
329 return VERR_INVALID_PARAMETER;
330
331 const uint32_t cbPath = (uint32_t)strPath.length() + 1; /* Include termination. */
332
333 VBoxClipboardWriteDirMsg Msg;
334 RT_ZERO(Msg);
335
336 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_WRITE_DIR, 4);
337 /** @todo Context ID not used yet. */
338 Msg.pvName.SetPtr((void *)strPath.c_str(), (uint32_t)cbPath);
339 Msg.cbName.SetUInt32((uint32_t)cbPath);
340 Msg.fMode.SetUInt32(pObj->GetMode());
341
342 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
343}
344
345/**
346 * Guest -> Host
347 * Utility function to send a file from the guest to the host.
348 *
349 * @returns IPRT status code.
350 * @param idClient The client id returned by VbglR3ClipboardConnect().
351 * @param pObj URI object containing the file to send.
352 */
353static int vbglR3ClipboardSendFile(HGCMCLIENTID idClient, SharedClipboardURIObject *pObj)
354{
355 AssertPtrReturn(pObj, VERR_INVALID_POINTER);
356 AssertReturn(pObj->GetType() == SharedClipboardURIObject::Type_File, VERR_INVALID_PARAMETER);
357 AssertReturn(pObj->IsOpen(), VERR_INVALID_STATE);
358
359 uint32_t cbBuf = _64K; /** @todo Make this configurable? */
360 void *pvBuf = RTMemAlloc(cbBuf);
361 if (!pvBuf)
362 return VERR_NO_MEMORY;
363
364 RTCString strPath = pObj->GetDestPathAbs();
365
366 LogFlowFunc(("strFile=%s (%zu), cbSize=%RU64, fMode=0x%x\n", strPath.c_str(), strPath.length(),
367 pObj->GetSize(), pObj->GetMode()));
368
369 VBoxClipboardWriteFileHdrMsg MsgHdr;
370 RT_ZERO(MsgHdr);
371
372 VBGL_HGCM_HDR_INIT(&MsgHdr.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_WRITE_FILE_HDR, 6);
373 MsgHdr.uContext.SetUInt32(0); /* Context ID; unused at the moment. */
374 MsgHdr.pvName.SetPtr((void *)strPath.c_str(), (uint32_t)(strPath.length() + 1));
375 MsgHdr.cbName.SetUInt32((uint32_t)(strPath.length() + 1));
376 MsgHdr.uFlags.SetUInt32(0); /* Flags; unused at the moment. */
377 MsgHdr.fMode.SetUInt32(pObj->GetMode()); /* File mode */
378 MsgHdr.cbTotal.SetUInt64(pObj->GetSize()); /* File size (in bytes). */
379
380 int rc = VbglR3HGCMCall(&MsgHdr.hdr, sizeof(MsgHdr));
381
382 LogFlowFunc(("Sending file header resulted in %Rrc\n", rc));
383
384 if (RT_SUCCESS(rc))
385 {
386 /*
387 * Send the actual file data, chunk by chunk.
388 */
389 VBoxClipboardWriteFileDataMsg Msg;
390 RT_ZERO(Msg);
391
392 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_WRITE_FILE_DATA, 5);
393 Msg.uContext.SetUInt32(0);
394 Msg.pvChecksum.SetPtr(NULL, 0);
395 Msg.cbChecksum.SetUInt32(0);
396
397 uint64_t cbToReadTotal = pObj->GetSize();
398 uint64_t cbWrittenTotal = 0;
399 while (cbToReadTotal)
400 {
401 uint32_t cbToRead = RT_MIN(cbToReadTotal, cbBuf);
402 uint32_t cbRead = 0;
403 if (cbToRead)
404 rc = pObj->Read(pvBuf, cbToRead, &cbRead);
405
406 LogFlowFunc(("cbToReadTotal=%RU64, cbToRead=%RU32, cbRead=%RU32, rc=%Rrc\n",
407 cbToReadTotal, cbToRead, cbRead, rc));
408
409 if ( RT_SUCCESS(rc)
410 && cbRead)
411 {
412 Msg.pvData.SetPtr(pvBuf, cbRead);
413 Msg.cbData.SetUInt32(cbRead);
414 /** @todo Calculate + set checksums. */
415
416 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
417 }
418
419 if (RT_FAILURE(rc))
420 {
421 LogFlowFunc(("Reading failed with rc=%Rrc\n", rc));
422 break;
423 }
424
425 Assert(cbRead <= cbToReadTotal);
426 cbToReadTotal -= cbRead;
427 cbWrittenTotal += cbRead;
428
429 LogFlowFunc(("%RU64/%RU64 -- %RU8%%\n", cbWrittenTotal, pObj->GetSize(), cbWrittenTotal * 100 / pObj->GetSize()));
430 };
431 }
432
433 RTMemFree(pvBuf);
434
435 LogFlowFuncLeaveRC(rc);
436 return rc;
437}
438
439/**
440 * Guest -> Host
441 * Utility function to send an URI object from guest to the host.
442 *
443 * @returns IPRT status code.
444 * @param idClient The client id returned by VbglR3ClipboardConnect().
445 * @param pObj URI object to send from guest to the host.
446 */
447static int vbglR3ClipboardSendURIObject(HGCMCLIENTID idClient, SharedClipboardURIObject *pObj)
448{
449 AssertPtrReturn(pObj, VERR_INVALID_POINTER);
450
451 int rc;
452
453 switch (pObj->GetType())
454 {
455 case SharedClipboardURIObject::Type_Directory:
456 rc = vbglR3ClipboardSendDir(idClient, pObj);
457 break;
458
459 case SharedClipboardURIObject::Type_File:
460 rc = vbglR3ClipboardSendFile(idClient, pObj);
461 break;
462
463 default:
464 AssertMsgFailed(("Object type %ld not implemented\n", pObj->GetType()));
465 rc = VERR_NOT_IMPLEMENTED;
466 break;
467 }
468
469 return rc;
470}
471
472/**
473 * Guest -> Host
474 * Utility function to send URI data from guest to the host.
475 *
476 * @returns IPRT status code.
477 * @param idClient The client id returned by VbglR3ClipboardConnect().
478 * @param pvData Block to URI data to send.
479 * @param cbData Size (in bytes) of URI data to send.
480 */
481static int vbglR3ClipboardSendURIData(HGCMCLIENTID idClient, const void *pvData, size_t cbData)
482{
483 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
484 AssertReturn(cbData, VERR_INVALID_PARAMETER);
485
486 RTCList<RTCString> lstPaths =
487 RTCString((const char *)pvData, cbData).split("\r\n");
488
489 /** @todo Add symlink support (SHAREDCLIPBOARDURILIST_FLAGS_RESOLVE_SYMLINKS) here. */
490 /** @todo Add lazy loading (SHAREDCLIPBOARDURILIST_FLAGS_LAZY) here. */
491 uint32_t fFlags = SHAREDCLIPBOARDURILIST_FLAGS_KEEP_OPEN;
492
493 SharedClipboardURIList lstURI;
494 int rc = lstURI.AppendURIPathsFromList(lstPaths, fFlags);
495 if (RT_SUCCESS(rc))
496 {
497 /*
498 * Send the (meta) data; in case of URIs it's the (non-recursive) file/directory
499 * URI list the host needs to know upfront to set up the drag'n drop operation.
500 */
501 RTCString strRootDest = lstURI.GetRootEntries();
502 if (strRootDest.isNotEmpty())
503 {
504 void *pvURIList = (void *)strRootDest.c_str(); /* URI root list. */
505 uint32_t cbURLIist = (uint32_t)strRootDest.length() + 1; /* Include string termination. */
506
507 /* The total size also contains the size of the meta data. */
508 uint64_t cbTotal = cbURLIist;
509 cbTotal += lstURI.GetTotalBytes();
510
511 /* We're going to send an URI list in text format. */
512 const char szMetaFmt[] = "text/uri-list";
513 const uint32_t cbMetaFmt = (uint32_t)strlen(szMetaFmt) + 1; /* Include termination. */
514
515 VBOXCLIPBOARDDATAHDR dataHdr;
516 dataHdr.uFlags = 0; /* Flags not used yet. */
517 dataHdr.cbTotal = cbTotal;
518 dataHdr.cbMeta = cbURLIist;
519 dataHdr.pvMetaFmt = (void *)szMetaFmt;
520 dataHdr.cbMetaFmt = cbMetaFmt;
521 dataHdr.cObjects = lstURI.GetTotalCount();
522
523 rc = vbglR3ClipboardSendDataInternal(idClient,
524 pvURIList, cbURLIist, &dataHdr);
525 }
526 else
527 rc = VERR_INVALID_PARAMETER;
528 }
529
530 if (RT_SUCCESS(rc))
531 {
532 while (!lstURI.IsEmpty())
533 {
534 SharedClipboardURIObject *pNextObj = lstURI.First();
535
536 rc = vbglR3ClipboardSendURIObject(idClient, pNextObj);
537 if (RT_FAILURE(rc))
538 break;
539
540 lstURI.RemoveFirst();
541 }
542 }
543
544 return rc;
545}
546
547/**
548 * Guest -> Host
549 * Sends an error back to the host.
550 *
551 * @returns IPRT status code.
552 * @param idClient The client id returned by VbglR3ClipboardConnect().
553 * @param rcErr Error (IPRT-style) to send.
554 */
555static int vbglR3ClipboardSendErrorInternal(HGCMCLIENTID idClient, int rcErr)
556{
557 VBoxClipboardWriteErrorMsg Msg;
558 RT_ZERO(Msg);
559
560 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_WRITE_ERROR, 2);
561 /** @todo Context ID not used yet. */
562 Msg.uContext.SetUInt32(0);
563 Msg.rc.SetUInt32((uint32_t)rcErr); /* uint32_t vs. int. */
564
565 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
566
567 /*
568 * Never return an error if the host did not accept the error at the current
569 * time. This can be due to the host not having any appropriate callbacks
570 * set which would handle that error.
571 *
572 * bird: Looks like VERR_NOT_SUPPORTED is what the host will return if it
573 * doesn't an appropriate callback. The code used to ignore ALL errors
574 * the host would return, also relevant ones.
575 */
576 if (RT_FAILURE(rc))
577 LogFlowFunc(("Sending error %Rrc failed with rc=%Rrc\n", rcErr, rc));
578 if (rc == VERR_NOT_SUPPORTED)
579 rc = VINF_SUCCESS;
580
581 return rc;
582}
583
584/**
585 * Guest -> Host
586 * Send an error back to the host.
587 *
588 * @returns IPRT status code.
589 * @param idClient The client id returned by VbglR3ClipboardConnect().
590 * @param rcErr Error (IPRT-style) to send.
591 */
592VBGLR3DECL(int) VbglR3ClipboardSendError(HGCMCLIENTID idClient, int rcErr)
593{
594 return vbglR3ClipboardSendErrorInternal(idClient, rcErr);
595}
596#endif /* VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */
597
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