VirtualBox

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

Last change on this file since 78554 was 78315, 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: 21.0 KB
Line 
1/* $Id: VBoxGuestR3LibClipboard.cpp 78315 2019-04-26 09:06:32Z 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.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#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 * Reports (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) VbglR3ClipboardReportFormats(HGCMCLIENTID idClient, uint32_t fFormats)
163{
164 VBoxClipboardWriteFormats Msg;
165
166 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_REPORT_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#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
221 if (RT_FAILURE(rc))
222 {
223 int rc2 = vbglR3ClipboardSendErrorInternal(idClient, rc);
224 if (RT_FAILURE(rc2))
225 LogFlowFunc(("Unable to send error (%Rrc) to host, rc=%Rrc\n", rc, rc2));
226 }
227#endif
228
229 return rc;
230}
231
232#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
233/**
234 * Guest -> Host
235 * Utility function to send clipboard data from guest to the host.
236 *
237 * @returns IPRT status code.
238 * @param idClient The client id returned by VbglR3ClipboardConnect().
239 * @param pvData Data block to send.
240 * @param cbData Size (in bytes) of data block to send.
241 * @param pDataHdr Data header to use -- needed for accounting.
242 */
243static int vbglR3ClipboardSendDataInternal(HGCMCLIENTID idClient,
244 void *pvData, uint64_t cbData, PVBOXCLIPBOARDDATAHDR pDataHdr)
245{
246 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
247 AssertReturn(cbData, VERR_INVALID_PARAMETER);
248 AssertPtrReturn(pDataHdr, VERR_INVALID_POINTER);
249
250 VBoxClipboardWriteDataHdrMsg MsgHdr;
251 RT_ZERO(MsgHdr);
252
253 VBGL_HGCM_HDR_INIT(&MsgHdr.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_WRITE_DATA_HDR, 12);
254 MsgHdr.uContext.SetUInt32(0); /** @todo Not used yet. */
255 MsgHdr.uFlags.SetUInt32(0); /** @todo Not used yet. */
256 MsgHdr.uScreenId.SetUInt32(0); /** @todo Not used for guest->host (yet). */
257 MsgHdr.cbTotal.SetUInt64(pDataHdr->cbTotal);
258 MsgHdr.cbMeta.SetUInt32(pDataHdr->cbMeta);
259 MsgHdr.pvMetaFmt.SetPtr(pDataHdr->pvMetaFmt, pDataHdr->cbMetaFmt);
260 MsgHdr.cbMetaFmt.SetUInt32(pDataHdr->cbMetaFmt);
261 MsgHdr.cObjects.SetUInt64(pDataHdr->cObjects);
262 MsgHdr.enmCompression.SetUInt32(0); /** @todo Not used yet. */
263 MsgHdr.enmChecksumType.SetUInt32(RTDIGESTTYPE_INVALID); /** @todo Not used yet. */
264 MsgHdr.pvChecksum.SetPtr(NULL, 0); /** @todo Not used yet. */
265 MsgHdr.cbChecksum.SetUInt32(0); /** @todo Not used yet. */
266
267 int rc = VbglR3HGCMCall(&MsgHdr.hdr, sizeof(MsgHdr));
268
269 LogFlowFunc(("cbTotal=%RU64, cbMeta=%RU32, cObjects=%RU64, rc=%Rrc\n",
270 pDataHdr->cbTotal, pDataHdr->cbMeta, pDataHdr->cObjects, rc));
271
272 if (RT_SUCCESS(rc))
273 {
274 VBoxClipboardWriteDataChunkMsg MsgData;
275 RT_ZERO(MsgData);
276
277 VBGL_HGCM_HDR_INIT(&MsgData.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_WRITE_DATA_CHUNK, 5);
278 MsgData.uContext.SetUInt32(0); /** @todo Not used yet. */
279 MsgData.pvChecksum.SetPtr(NULL, 0); /** @todo Not used yet. */
280 MsgData.cbChecksum.SetUInt32(0); /** @todo Not used yet. */
281
282 uint32_t cbCurChunk;
283 const uint32_t cbMaxChunk = VBOX_SHARED_CLIPBOARD_MAX_CHUNK_SIZE;
284 uint32_t cbSent = 0;
285
286 HGCMFunctionParameter *pParm = &MsgData.pvData;
287
288 while (cbSent < cbData)
289 {
290 cbCurChunk = RT_MIN(cbData - cbSent, cbMaxChunk);
291 pParm->SetPtr(static_cast<uint8_t *>(pvData) + cbSent, cbCurChunk);
292
293 MsgData.cbData.SetUInt32(cbCurChunk);
294
295 rc = VbglR3HGCMCall(&MsgData.hdr, sizeof(MsgData));
296 if (RT_FAILURE(rc))
297 break;
298
299 cbSent += cbCurChunk;
300 }
301
302 LogFlowFunc(("cbMaxChunk=%RU32, cbData=%RU64, cbSent=%RU32, rc=%Rrc\n",
303 cbMaxChunk, cbData, cbSent, rc));
304
305 if (RT_SUCCESS(rc))
306 Assert(cbSent == cbData);
307 }
308
309 LogFlowFuncLeaveRC(rc);
310 return rc;
311}
312
313/**
314 * Guest -> Host
315 * Utility function to send a guest directory to the host.
316 *
317 * @returns IPRT status code.
318 * @param idClient The client id returned by VbglR3ClipboardConnect().
319 * @param pObj URI object containing the directory to send.
320 */
321static int vbglR3ClipboardSendDir(HGCMCLIENTID idClient, SharedClipboardURIObject *pObj)
322{
323 AssertPtrReturn(pObj, VERR_INVALID_POINTER);
324 AssertReturn(pObj->GetType() == SharedClipboardURIObject::Type_Directory, VERR_INVALID_PARAMETER);
325
326 RTCString strPath = pObj->GetDestPathAbs();
327 LogFlowFunc(("strDir=%s (%zu), fMode=0x%x\n",
328 strPath.c_str(), strPath.length(), pObj->GetMode()));
329
330 if (strPath.length() > RTPATH_MAX)
331 return VERR_INVALID_PARAMETER;
332
333 const uint32_t cbPath = (uint32_t)strPath.length() + 1; /* Include termination. */
334
335 VBoxClipboardWriteDirMsg Msg;
336 RT_ZERO(Msg);
337
338 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_WRITE_DIR, 4);
339 /** @todo Context ID not used yet. */
340 Msg.pvName.SetPtr((void *)strPath.c_str(), (uint32_t)cbPath);
341 Msg.cbName.SetUInt32((uint32_t)cbPath);
342 Msg.fMode.SetUInt32(pObj->GetMode());
343
344 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
345}
346
347/**
348 * Guest -> Host
349 * Utility function to send a file from the guest to the host.
350 *
351 * @returns IPRT status code.
352 * @param idClient The client id returned by VbglR3ClipboardConnect().
353 * @param pObj URI object containing the file to send.
354 */
355static int vbglR3ClipboardSendFile(HGCMCLIENTID idClient, SharedClipboardURIObject *pObj)
356{
357 AssertPtrReturn(pObj, VERR_INVALID_POINTER);
358 AssertReturn(pObj->GetType() == SharedClipboardURIObject::Type_File, VERR_INVALID_PARAMETER);
359 AssertReturn(pObj->IsOpen(), VERR_INVALID_STATE);
360
361 uint32_t cbBuf = _64K; /** @todo Make this configurable? */
362 void *pvBuf = RTMemAlloc(cbBuf);
363 if (!pvBuf)
364 return VERR_NO_MEMORY;
365
366 RTCString strPath = pObj->GetDestPathAbs();
367
368 LogFlowFunc(("strFile=%s (%zu), cbSize=%RU64, fMode=0x%x\n", strPath.c_str(), strPath.length(),
369 pObj->GetSize(), pObj->GetMode()));
370
371 VBoxClipboardWriteFileHdrMsg MsgHdr;
372 RT_ZERO(MsgHdr);
373
374 VBGL_HGCM_HDR_INIT(&MsgHdr.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_WRITE_FILE_HDR, 6);
375 MsgHdr.uContext.SetUInt32(0); /* Context ID; unused at the moment. */
376 MsgHdr.pvName.SetPtr((void *)strPath.c_str(), (uint32_t)(strPath.length() + 1));
377 MsgHdr.cbName.SetUInt32((uint32_t)(strPath.length() + 1));
378 MsgHdr.uFlags.SetUInt32(0); /* Flags; unused at the moment. */
379 MsgHdr.fMode.SetUInt32(pObj->GetMode()); /* File mode */
380 MsgHdr.cbTotal.SetUInt64(pObj->GetSize()); /* File size (in bytes). */
381
382 int rc = VbglR3HGCMCall(&MsgHdr.hdr, sizeof(MsgHdr));
383
384 LogFlowFunc(("Sending file header resulted in %Rrc\n", rc));
385
386 if (RT_SUCCESS(rc))
387 {
388 /*
389 * Send the actual file data, chunk by chunk.
390 */
391 VBoxClipboardWriteFileDataMsg Msg;
392 RT_ZERO(Msg);
393
394 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_WRITE_FILE_DATA, 5);
395 Msg.uContext.SetUInt32(0);
396 Msg.pvChecksum.SetPtr(NULL, 0);
397 Msg.cbChecksum.SetUInt32(0);
398
399 uint64_t cbToReadTotal = pObj->GetSize();
400 uint64_t cbWrittenTotal = 0;
401 while (cbToReadTotal)
402 {
403 uint32_t cbToRead = RT_MIN(cbToReadTotal, cbBuf);
404 uint32_t cbRead = 0;
405 if (cbToRead)
406 rc = pObj->Read(pvBuf, cbToRead, &cbRead);
407
408 LogFlowFunc(("cbToReadTotal=%RU64, cbToRead=%RU32, cbRead=%RU32, rc=%Rrc\n",
409 cbToReadTotal, cbToRead, cbRead, rc));
410
411 if ( RT_SUCCESS(rc)
412 && cbRead)
413 {
414 Msg.pvData.SetPtr(pvBuf, cbRead);
415 Msg.cbData.SetUInt32(cbRead);
416 /** @todo Calculate + set checksums. */
417
418 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
419 }
420
421 if (RT_FAILURE(rc))
422 {
423 LogFlowFunc(("Reading failed with rc=%Rrc\n", rc));
424 break;
425 }
426
427 Assert(cbRead <= cbToReadTotal);
428 cbToReadTotal -= cbRead;
429 cbWrittenTotal += cbRead;
430
431 LogFlowFunc(("%RU64/%RU64 -- %RU8%%\n", cbWrittenTotal, pObj->GetSize(), cbWrittenTotal * 100 / pObj->GetSize()));
432 };
433 }
434
435 RTMemFree(pvBuf);
436
437 LogFlowFuncLeaveRC(rc);
438 return rc;
439}
440
441/**
442 * Guest -> Host
443 * Utility function to send an URI object from guest to the host.
444 *
445 * @returns IPRT status code.
446 * @param idClient The client id returned by VbglR3ClipboardConnect().
447 * @param pObj URI object to send from guest to the host.
448 */
449static int vbglR3ClipboardSendURIObject(HGCMCLIENTID idClient, SharedClipboardURIObject *pObj)
450{
451 AssertPtrReturn(pObj, VERR_INVALID_POINTER);
452
453 int rc;
454
455 switch (pObj->GetType())
456 {
457 case SharedClipboardURIObject::Type_Directory:
458 rc = vbglR3ClipboardSendDir(idClient, pObj);
459 break;
460
461 case SharedClipboardURIObject::Type_File:
462 rc = vbglR3ClipboardSendFile(idClient, pObj);
463 break;
464
465 default:
466 AssertMsgFailed(("Object type %ld not implemented\n", pObj->GetType()));
467 rc = VERR_NOT_IMPLEMENTED;
468 break;
469 }
470
471 return rc;
472}
473
474/**
475 * Guest -> Host
476 * Utility function to send URI data from guest to the host.
477 *
478 * @returns IPRT status code.
479 * @param idClient The client id returned by VbglR3ClipboardConnect().
480 * @param pvData Block to URI data to send.
481 * @param cbData Size (in bytes) of URI data to send.
482 */
483static int vbglR3ClipboardSendURIData(HGCMCLIENTID idClient, const void *pvData, size_t cbData)
484{
485 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
486 AssertReturn(cbData, VERR_INVALID_PARAMETER);
487
488 RTCList<RTCString> lstPaths =
489 RTCString((const char *)pvData, cbData).split("\r\n");
490
491 /** @todo Add symlink support (SHAREDCLIPBOARDURILIST_FLAGS_RESOLVE_SYMLINKS) here. */
492 /** @todo Add lazy loading (SHAREDCLIPBOARDURILIST_FLAGS_LAZY) here. */
493 uint32_t fFlags = SHAREDCLIPBOARDURILIST_FLAGS_KEEP_OPEN;
494
495 SharedClipboardURIList lstURI;
496 int rc = lstURI.AppendURIPathsFromList(lstPaths, fFlags);
497 if (RT_SUCCESS(rc))
498 {
499 /*
500 * Send the (meta) data; in case of URIs it's the (non-recursive) file/directory
501 * URI list the host needs to know upfront to set up the drag'n drop operation.
502 */
503 RTCString strRootDest = lstURI.GetRootEntries();
504 if (strRootDest.isNotEmpty())
505 {
506 void *pvURIList = (void *)strRootDest.c_str(); /* URI root list. */
507 uint32_t cbURLIist = (uint32_t)strRootDest.length() + 1; /* Include string termination. */
508
509 /* The total size also contains the size of the meta data. */
510 uint64_t cbTotal = cbURLIist;
511 cbTotal += lstURI.GetTotalBytes();
512
513 /* We're going to send an URI list in text format. */
514 const char szMetaFmt[] = "text/uri-list";
515 const uint32_t cbMetaFmt = (uint32_t)strlen(szMetaFmt) + 1; /* Include termination. */
516
517 VBOXCLIPBOARDDATAHDR dataHdr;
518 dataHdr.uFlags = 0; /* Flags not used yet. */
519 dataHdr.cbTotal = cbTotal;
520 dataHdr.cbMeta = cbURLIist;
521 dataHdr.pvMetaFmt = (void *)szMetaFmt;
522 dataHdr.cbMetaFmt = cbMetaFmt;
523 dataHdr.cObjects = lstURI.GetTotalCount();
524
525 rc = vbglR3ClipboardSendDataInternal(idClient,
526 pvURIList, cbURLIist, &dataHdr);
527 }
528 else
529 rc = VERR_INVALID_PARAMETER;
530 }
531
532 if (RT_SUCCESS(rc))
533 {
534 while (!lstURI.IsEmpty())
535 {
536 SharedClipboardURIObject *pNextObj = lstURI.First();
537
538 rc = vbglR3ClipboardSendURIObject(idClient, pNextObj);
539 if (RT_FAILURE(rc))
540 break;
541
542 lstURI.RemoveFirst();
543 }
544 }
545
546 return rc;
547}
548
549/**
550 * Guest -> Host
551 * Sends an error back to the host.
552 *
553 * @returns IPRT status code.
554 * @param idClient The client id returned by VbglR3ClipboardConnect().
555 * @param rcErr Error (IPRT-style) to send.
556 */
557static int vbglR3ClipboardSendErrorInternal(HGCMCLIENTID idClient, int rcErr)
558{
559 VBoxClipboardWriteErrorMsg Msg;
560 RT_ZERO(Msg);
561
562 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_FN_WRITE_ERROR, 2);
563 /** @todo Context ID not used yet. */
564 Msg.uContext.SetUInt32(0);
565 Msg.rc.SetUInt32((uint32_t)rcErr); /* uint32_t vs. int. */
566
567 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
568
569 /*
570 * Never return an error if the host did not accept the error at the current
571 * time. This can be due to the host not having any appropriate callbacks
572 * set which would handle that error.
573 *
574 * bird: Looks like VERR_NOT_SUPPORTED is what the host will return if it
575 * doesn't an appropriate callback. The code used to ignore ALL errors
576 * the host would return, also relevant ones.
577 */
578 if (RT_FAILURE(rc))
579 LogFlowFunc(("Sending error %Rrc failed with rc=%Rrc\n", rcErr, rc));
580 if (rc == VERR_NOT_SUPPORTED)
581 rc = VINF_SUCCESS;
582
583 return rc;
584}
585
586/**
587 * Guest -> Host
588 * Send an error back to the host.
589 *
590 * @returns IPRT status code.
591 * @param idClient The client id returned by VbglR3ClipboardConnect().
592 * @param rcErr Error (IPRT-style) to send.
593 */
594VBGLR3DECL(int) VbglR3ClipboardSendError(HGCMCLIENTID idClient, int rcErr)
595{
596 return vbglR3ClipboardSendErrorInternal(idClient, rcErr);
597}
598#endif /* VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */
599
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