VirtualBox

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

Last change on this file since 80990 was 80990, checked in by vboxsync, 5 years ago

Shared Clipboard/Transfers: 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: 69.5 KB
Line 
1/* $Id: VBoxGuestR3LibClipboard.cpp 80990 2019-09-25 06:20:09Z 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#include <VBox/GuestHost/clipboard-helper.h>
33#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
34# include <VBox/GuestHost/SharedClipboard-transfers.h>
35#endif
36#include <VBox/HostServices/VBoxClipboardSvc.h>
37#include <VBox/err.h>
38#include <iprt/assert.h>
39#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
40# include <iprt/dir.h>
41# include <iprt/file.h>
42# include <iprt/path.h>
43#endif
44#include <iprt/string.h>
45#include <iprt/cpp/ministring.h>
46
47#include "VBoxGuestR3LibInternal.h"
48
49
50/**
51 * Function naming convention:
52 *
53 * FunctionNameRecv = Receives a host message (request).
54 * FunctionNameReply = Replies to a host message (request).
55 * FunctionNameSend = Sends a guest message to the host.
56 */
57
58
59/*********************************************************************************************************************************
60* Prototypes *
61*********************************************************************************************************************************/
62
63
64/**
65 * Connects to the Shared Clipboard service, legacy version, do not use anymore.
66 *
67 * @returns VBox status code
68 * @param pidClient Where to put the client id on success. The client id
69 * must be passed to all the other clipboard calls.
70 */
71VBGLR3DECL(int) VbglR3ClipboardConnect(HGCMCLIENTID *pidClient)
72{
73 int rc = VbglR3HGCMConnect("VBoxSharedClipboard", pidClient);
74 if (rc == VERR_HGCM_SERVICE_NOT_FOUND)
75 rc = VINF_PERMISSION_DENIED;
76
77 LogFlowFuncLeaveRC(rc);
78 return rc;
79}
80
81
82/**
83 * Connects to the Shared Clipboard service, extended version.
84 *
85 * @returns VBox status code.
86 * @param pCtx Shared Clipboard command context to use for the connection.
87 */
88VBGLR3DECL(int) VbglR3ClipboardConnectEx(PVBGLR3SHCLCMDCTX pCtx)
89{
90 int rc = VbglR3ClipboardConnect(&pCtx->uClientID);
91 if (RT_SUCCESS(rc))
92 {
93 VBoxShClConnect Msg;
94 RT_ZERO(Msg);
95
96 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID,
97 VBOX_SHCL_GUEST_FN_CONNECT, VBOX_SHCL_CPARMS_CONNECT);
98
99 VbglHGCMParmUInt32Set(&Msg.uProtocolVer, 0);
100 VbglHGCMParmUInt32Set(&Msg.uProtocolFlags, 0);
101 VbglHGCMParmUInt32Set(&Msg.cbChunkSize, 0);
102 VbglHGCMParmUInt32Set(&Msg.enmCompression, 0);
103 VbglHGCMParmUInt32Set(&Msg.enmChecksumType, 0);
104
105 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
106 if (RT_SUCCESS(rc))
107 {
108 rc = VbglHGCMParmUInt32Get(&Msg.uProtocolVer, &pCtx->uProtocolVer);
109 if (RT_SUCCESS(rc))
110 rc = VbglHGCMParmUInt32Get(&Msg.uProtocolFlags, &pCtx->uProtocolFlags);
111 if (RT_SUCCESS(rc))
112 rc = VbglHGCMParmUInt32Get(&Msg.cbChunkSize, &pCtx->cbChunkSize);
113
114 /** @todo Add / handle checksum + compression type. */
115 }
116 else
117 {
118 /* If the above call fails, make sure to use some sane defaults for
119 * the old (legacy) protocol. */
120 pCtx->uProtocolVer = 0;
121 pCtx->uProtocolFlags = 0;
122 pCtx->cbChunkSize = _64K;
123
124 rc = VINF_SUCCESS; /* Failing above is not fatal. */
125 }
126
127 LogFlowFunc(("uProtocolVer=%RU32, cbChunkSize=%RU32\n", pCtx->uProtocolVer, pCtx->cbChunkSize));
128
129 LogRel2(("Shared Clipboard: Client %RU32 connected, using protocol v%RU32 (cbChunkSize=%RU32)\n",
130 pCtx->uClientID, pCtx->uProtocolVer, pCtx->cbChunkSize));
131
132 }
133
134 LogFlowFuncLeaveRC(rc);
135 return rc;
136}
137
138
139/**
140 * Disconnects from the Shared Clipboard service, legacy version, do not use anymore.
141 *
142 * @returns VBox status code.
143 * @param idClient The client id returned by VbglR3ClipboardConnect().
144 */
145VBGLR3DECL(int) VbglR3ClipboardDisconnect(HGCMCLIENTID idClient)
146{
147 return VbglR3HGCMDisconnect(idClient);
148}
149
150
151/**
152 * Disconnects from the Shared Clipboard service, extended version.
153 *
154 * @returns VBox status code.
155 * @param pCtx Shared Clipboard command context to use for the connection.
156 */
157VBGLR3DECL(int) VbglR3ClipboardDisconnectEx(PVBGLR3SHCLCMDCTX pCtx)
158{
159 int rc = VbglR3ClipboardDisconnect(pCtx->uClientID);
160 if (RT_SUCCESS(rc))
161 {
162 pCtx->uClientID = 0;
163 }
164
165 LogFlowFuncLeaveRC(rc);
166 return rc;
167}
168
169
170VBGLR3DECL(int) VbglR3ClipboardFormatsReportRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLFORMATDATA pFormats)
171{
172 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
173 AssertPtrReturn(pFormats, VERR_INVALID_POINTER);
174
175 VBoxShClFormatsMsg Msg;
176 RT_ZERO(Msg);
177
178 if (pCtx->uProtocolVer >= 1)
179 {
180 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID,
181 VBOX_SHCL_GUEST_FN_MSG_GET, 3);
182
183 Msg.u.v1.uContext.SetUInt32(VBOX_SHCL_HOST_MSG_FORMATS_REPORT);
184 Msg.u.v1.uFormats.SetUInt32(0);
185 Msg.u.v1.fFlags.SetUInt32(0);
186 }
187
188 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
189 if (RT_SUCCESS(rc))
190 {
191 rc = Msg.u.v1.uContext.GetUInt32(&pCtx->uContextID);
192 if (RT_SUCCESS(rc))
193 rc = Msg.u.v1.uFormats.GetUInt32(&pFormats->uFormats);
194 if (RT_SUCCESS(rc))
195 rc = Msg.u.v1.fFlags.GetUInt32(&pFormats->fFlags);
196 }
197
198 LogFlowFuncLeaveRC(rc);
199 return rc;
200}
201
202
203VBGLR3DECL(int) VbglR3ClipboardReadDataRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLDATAREQ pDataReq)
204{
205 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
206 AssertPtrReturn(pDataReq, VERR_INVALID_POINTER);
207
208 VBoxShClReadDataReqMsg Msg;
209
210 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID,
211 VBOX_SHCL_GUEST_FN_MSG_GET, VBOX_SHCL_CPARMS_READ_DATA);
212
213 Msg.uContext.SetUInt32(VBOX_SHCL_HOST_MSG_READ_DATA);
214 Msg.uFormat.SetUInt32(0);
215 Msg.cbSize.SetUInt32(0);
216
217 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
218 if (RT_SUCCESS(rc))
219 {
220 rc = Msg.uContext.GetUInt32(&pCtx->uContextID);
221 if (RT_SUCCESS(rc))
222 rc = Msg.uFormat.GetUInt32(&pDataReq->uFmt);
223 if (RT_SUCCESS(rc))
224 rc = Msg.cbSize.GetUInt32(&pDataReq->cbSize);
225 }
226
227 LogFlowFuncLeaveRC(rc);
228 return rc;
229}
230
231
232/**
233 * Get a host message, legacy version (protocol v0). Do not use anymore.
234 *
235 * Note: This is the old message which still is being used for the non-URI Shared Clipboard transfers,
236 * to not break compatibility with older additions / VBox versions.
237 *
238 * This will block until a message becomes available.
239 *
240 * @returns VBox status code.
241 * @param idClient The client id returned by VbglR3ClipboardConnect().
242 * @param pidMsg Where to store the message id.
243 * @param pfFormats Where to store the format(s) the message applies to.
244 */
245VBGLR3DECL(int) VbglR3ClipboardGetHostMsgOld(HGCMCLIENTID idClient, uint32_t *pidMsg, uint32_t *pfFormats)
246{
247 VBoxShClGetHostMsgOld Msg;
248
249 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
250 VBOX_SHCL_GUEST_FN_GET_HOST_MSG_OLD, VBOX_SHCL_CPARMS_GET_HOST_MSG_OLD);
251
252 VbglHGCMParmUInt32Set(&Msg.msg, 0);
253 VbglHGCMParmUInt32Set(&Msg.formats, 0);
254
255 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
256 if (RT_SUCCESS(rc))
257 {
258 int rc2 = VbglHGCMParmUInt32Get(&Msg.msg, pidMsg);
259 if (RT_SUCCESS(rc))
260 {
261 rc2 = VbglHGCMParmUInt32Get(&Msg.formats, pfFormats);
262 if (RT_SUCCESS(rc2))
263 return rc;
264 }
265 rc = rc2;
266 }
267 *pidMsg = UINT32_MAX - 1;
268 *pfFormats = UINT32_MAX;
269 return rc;
270}
271
272
273/**
274 * Reads data from the host clipboard.
275 *
276 * @returns VBox status code.
277 * @retval VINF_BUFFER_OVERFLOW If there is more data available than the caller provided buffer space for.
278 *
279 * @param idClient The client id returned by VbglR3ClipboardConnect().
280 * @param fFormat The format we're requesting the data in.
281 * @param pv Where to store the data.
282 * @param cb The size of the buffer pointed to by pv.
283 * @param pcb The actual size of the host clipboard data. May be larger than cb.
284 */
285VBGLR3DECL(int) VbglR3ClipboardReadData(HGCMCLIENTID idClient, uint32_t fFormat, void *pv, uint32_t cb, uint32_t *pcb)
286{
287 VBoxShClReadDataMsg Msg;
288
289 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHCL_GUEST_FN_DATA_READ, VBOX_SHCL_CPARMS_READ_DATA);
290 VbglHGCMParmUInt32Set(&Msg.format, fFormat);
291 VbglHGCMParmPtrSet(&Msg.ptr, pv, cb);
292 VbglHGCMParmUInt32Set(&Msg.size, 0);
293
294 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
295 if (RT_SUCCESS(rc))
296 {
297 uint32_t cbActual;
298 int rc2 = VbglHGCMParmUInt32Get(&Msg.size, &cbActual);
299 if (RT_SUCCESS(rc2))
300 {
301 *pcb = cbActual;
302 if (cbActual > cb)
303 return VINF_BUFFER_OVERFLOW;
304 return rc;
305 }
306 rc = rc2;
307 }
308 return rc;
309}
310
311/**
312 * Peeks at the next host message, waiting for one to turn up.
313 *
314 * @returns VBox status code.
315 * @retval VERR_INTERRUPTED if interrupted. Does the necessary cleanup, so
316 * caller just have to repeat this call.
317 * @retval VERR_VM_RESTORED if the VM has been restored (idRestoreCheck).
318 *
319 * @param pCtx Shared Clipboard command context to use for the connection.
320 * @param pidMsg Where to store the message id.
321 * @param pcParameters Where to store the number of parameters which will
322 * be received in a second call to the host.
323 * @param pidRestoreCheck Pointer to the VbglR3GetSessionId() variable to use
324 * for the VM restore check. Optional.
325 *
326 * @note Restore check is only performed optimally with a 6.0 host.
327 */
328int VbglR3ClipboardMsgPeekWait(PVBGLR3SHCLCMDCTX pCtx, uint32_t *pidMsg, uint32_t *pcParameters, uint64_t *pidRestoreCheck)
329{
330 AssertPtrReturn(pidMsg, VERR_INVALID_POINTER);
331 AssertPtrReturn(pcParameters, VERR_INVALID_POINTER);
332
333 int rc;
334
335 struct
336 {
337 VBGLIOCHGCMCALL Hdr;
338 HGCMFunctionParameter idMsg; /* Doubles as restore check on input. */
339 HGCMFunctionParameter cParameters;
340 } Msg;
341 VBGL_HGCM_HDR_INIT(&Msg.Hdr, pCtx->uClientID, VBOX_SHCL_GUEST_FN_MSG_PEEK_WAIT, 2);
342 VbglHGCMParmUInt64Set(&Msg.idMsg, pidRestoreCheck ? *pidRestoreCheck : 0);
343 VbglHGCMParmUInt32Set(&Msg.cParameters, 0);
344 rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
345 LogFlowFunc(("VbglR3HGCMCall -> %Rrc\n", rc));
346 if (RT_SUCCESS(rc))
347 {
348 AssertMsgReturn( Msg.idMsg.type == VMMDevHGCMParmType_64bit
349 && Msg.cParameters.type == VMMDevHGCMParmType_32bit,
350 ("msg.type=%d num_parms.type=%d\n", Msg.idMsg.type, Msg.cParameters.type),
351 VERR_INTERNAL_ERROR_3);
352
353 *pidMsg = (uint32_t)Msg.idMsg.u.value64;
354 *pcParameters = Msg.cParameters.u.value32;
355 return rc;
356 }
357
358 /*
359 * If interrupted we must cancel the call so it doesn't prevent us from making another one.
360 */
361 if (rc == VERR_INTERRUPTED)
362 {
363 VBGL_HGCM_HDR_INIT(&Msg.Hdr, pCtx->uClientID, VBOX_SHCL_GUEST_FN_CANCEL, 0);
364 int rc2 = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg.Hdr));
365 AssertRC(rc2);
366 }
367
368 /*
369 * If restored, update pidRestoreCheck.
370 */
371 if (rc == VERR_VM_RESTORED && pidRestoreCheck)
372 *pidRestoreCheck = Msg.idMsg.u.value64;
373
374 *pidMsg = UINT32_MAX - 1;
375 *pcParameters = UINT32_MAX - 2;
376 return rc;
377}
378
379#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
380static int vbglR3ClipboardRootListHdrRead(PVBGLR3SHCLCMDCTX pCtx, PSHCLROOTLISTHDR pRootListHdr)
381{
382 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
383 AssertPtrReturn(pRootListHdr, VERR_INVALID_POINTER);
384
385 VBoxShClRootListHdrMsg Msg;
386 RT_ZERO(Msg);
387
388 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID,
389 VBOX_SHCL_GUEST_FN_ROOT_LIST_HDR_READ, VBOX_SHCL_CPARMS_ROOT_LIST_HDR_READ);
390
391 Msg.ReqParms.uContext.SetUInt32(pCtx->uContextID);
392 Msg.ReqParms.fRoots.SetUInt32(0);
393
394 Msg.cRoots.SetUInt32(0);
395
396 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
397 if (RT_SUCCESS(rc))
398 {
399 rc = Msg.ReqParms.fRoots.GetUInt32(&pRootListHdr->fRoots); AssertRC(rc);
400 if (RT_SUCCESS(rc))
401 rc = Msg.cRoots.GetUInt32(&pRootListHdr->cRoots); AssertRC(rc);
402 }
403
404 LogFlowFuncLeaveRC(rc);
405 return rc;
406}
407
408static int vbglR3ClipboardRootListEntryRead(PVBGLR3SHCLCMDCTX pCtx, uint32_t uIndex, PSHCLROOTLISTENTRY pRootListEntry)
409{
410 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
411 AssertPtrReturn(pRootListEntry, VERR_INVALID_POINTER);
412
413 VBoxShClRootListEntryMsg Msg;
414 RT_ZERO(Msg);
415
416 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID,
417 VBOX_SHCL_GUEST_FN_ROOT_LIST_ENTRY_READ, VBOX_SHCL_CPARMS_ROOT_LIST_ENTRY);
418
419 Msg.Parms.uContext.SetUInt32(pCtx->uContextID);
420 Msg.Parms.fInfo.SetUInt32(pRootListEntry->fInfo);
421 Msg.Parms.uIndex.SetUInt32(uIndex);
422
423 Msg.szName.SetPtr(pRootListEntry->pszName, pRootListEntry->cbName);
424 Msg.cbInfo.SetUInt32(pRootListEntry->cbInfo);
425 Msg.pvInfo.SetPtr(pRootListEntry->pvInfo, pRootListEntry->cbInfo);
426
427 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
428 if (RT_SUCCESS(rc))
429 {
430 rc = Msg.Parms.fInfo.GetUInt32(&pRootListEntry->fInfo); AssertRC(rc);
431 if (RT_SUCCESS(rc))
432 {
433 uint32_t cbInfo = 0;
434 rc = Msg.cbInfo.GetUInt32(&cbInfo); AssertRC(rc);
435 if (pRootListEntry->cbInfo != cbInfo)
436 rc = VERR_INVALID_PARAMETER;
437 }
438 }
439
440 LogFlowFuncLeaveRC(rc);
441 return rc;
442}
443
444VBGLR3DECL(int) VbglR3ClipboardRootListRead(PVBGLR3SHCLCMDCTX pCtx, PSHCLROOTLIST *ppRootList)
445{
446 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
447 AssertPtrReturn(ppRootList, VERR_INVALID_POINTER);
448
449 int rc;
450
451 PSHCLROOTLIST pRootList = SharedClipboardTransferRootListAlloc();
452 if (pRootList)
453 {
454 SHCLROOTLISTHDR srcRootListHdr;
455 rc = vbglR3ClipboardRootListHdrRead(pCtx, &srcRootListHdr);
456 if (RT_SUCCESS(rc))
457 {
458 pRootList->Hdr.cRoots = srcRootListHdr.cRoots;
459 pRootList->Hdr.fRoots = 0; /** @todo Implement this. */
460
461 if (srcRootListHdr.cRoots)
462 {
463 pRootList->paEntries =
464 (PSHCLROOTLISTENTRY)RTMemAllocZ(srcRootListHdr.cRoots * sizeof(SHCLROOTLISTENTRY));
465 if (pRootList->paEntries)
466 {
467 for (uint32_t i = 0; i < srcRootListHdr.cRoots; i++)
468 {
469 rc = vbglR3ClipboardRootListEntryRead(pCtx, i, &pRootList->paEntries[i]);
470 if (RT_FAILURE(rc))
471 break;
472 }
473 }
474 else
475 rc = VERR_NO_MEMORY;
476 }
477 }
478
479 if (RT_SUCCESS(rc))
480 {
481 *ppRootList = pRootList;
482 }
483 else
484 SharedClipboardTransferRootListFree(pRootList);
485 }
486 else
487 rc = VERR_NO_MEMORY;
488
489 LogFlowFuncLeaveRC(rc);
490 return rc;
491}
492
493VBGLR3DECL(int) VbglR3ClipboarTransferStatusRecv(PVBGLR3SHCLCMDCTX pCtx,
494 PSHCLTRANSFERDIR pEnmDir, PSHCLTRANSFERREPORT pReport)
495{
496 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
497 AssertPtrReturn(pReport, VERR_INVALID_POINTER);
498 AssertPtrReturn(pEnmDir, VERR_INVALID_POINTER);
499
500 VBoxShClTransferStatusMsg Msg;
501 RT_ZERO(Msg);
502
503 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID,
504 VBOX_SHCL_GUEST_FN_MSG_GET, VBOX_SHCL_CPARMS_TRANSFER_STATUS);
505
506 Msg.uContext.SetUInt32(VBOX_SHCL_HOST_MSG_TRANSFER_STATUS);
507 Msg.enmDir.SetUInt32(0);
508 Msg.enmStatus.SetUInt32(0);
509 Msg.rc.SetUInt32(0);
510 Msg.fFlags.SetUInt32(0);
511
512 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
513 if (RT_SUCCESS(rc))
514 {
515 rc = Msg.uContext.GetUInt32(&pCtx->uContextID); AssertRC(rc);
516 if (RT_SUCCESS(rc))
517 rc = Msg.enmDir.GetUInt32((uint32_t *)pEnmDir); AssertRC(rc);
518 if (RT_SUCCESS(rc))
519 rc = Msg.enmStatus.GetUInt32(&pReport->uStatus); AssertRC(rc);
520 if (RT_SUCCESS(rc))
521 rc = Msg.rc.GetUInt32((uint32_t *)&pReport->rc); AssertRC(rc);
522 if (RT_SUCCESS(rc))
523 rc = Msg.fFlags.GetUInt32(&pReport->fFlags); AssertRC(rc);
524 }
525
526 LogFlowFuncLeaveRC(rc);
527 return rc;
528}
529
530VBGLR3DECL(int) VbglR3ClipboardTransferStatusReply(PVBGLR3SHCLCMDCTX pCtx, PSHCLTRANSFER pTransfer,
531 SHCLTRANSFERSTATUS uStatus, int rcTransfer)
532{
533 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
534 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
535
536 RT_NOREF(pTransfer);
537
538 VBoxShClReplyMsg Msg;
539 RT_ZERO(Msg);
540
541 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID,
542 VBOX_SHCL_GUEST_FN_REPLY, VBOX_SHCL_CPARMS_REPLY_MIN + 1);
543
544 Msg.uContext.SetUInt32(pCtx->uContextID);
545 Msg.enmType.SetUInt32(VBOX_SHCL_REPLYMSGTYPE_TRANSFER_STATUS);
546 Msg.rc.SetUInt32((uint32_t )rcTransfer); /* int vs. uint32_t */
547 Msg.cbPayload.SetUInt32(0);
548 Msg.pvPayload.SetPtr(NULL, 0);
549
550 Msg.u.TransferStatus.enmStatus.SetUInt32((uint32_t)uStatus);
551
552 LogFlowFunc(("%s\n", VBoxShClTransferStatusToStr(uStatus)));
553
554 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
555
556 LogFlowFuncLeaveRC(rc);
557 return rc;
558}
559
560VBGLR3DECL(int) VbglR3ClipboardRootListHdrReadReq(PVBGLR3SHCLCMDCTX pCtx, uint32_t *pfRoots)
561{
562 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
563 AssertPtrReturn(pfRoots, VERR_INVALID_POINTER);
564
565 VBoxShClRootListReadReqMsg Msg;
566 RT_ZERO(Msg);
567
568 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID,
569 VBOX_SHCL_GUEST_FN_MSG_GET, VBOX_SHCL_CPARMS_ROOT_LIST_HDR_READ);
570
571 Msg.ReqParms.uContext.SetUInt32(VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_HDR_READ);
572 Msg.ReqParms.fRoots.SetUInt32(0);
573
574 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
575 if (RT_SUCCESS(rc))
576 {
577 rc = Msg.ReqParms.uContext.GetUInt32(&pCtx->uContextID); AssertRC(rc);
578 if (RT_SUCCESS(rc))
579 rc = Msg.ReqParms.fRoots.GetUInt32(pfRoots); AssertRC(rc);
580 }
581
582 LogFlowFuncLeaveRC(rc);
583 return rc;
584}
585
586VBGLR3DECL(int) VbglR3ClipboardRootListHdrReadReply(PVBGLR3SHCLCMDCTX pCtx, PSHCLROOTLISTHDR pRootListHdr)
587{
588 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
589 AssertPtrReturn(pRootListHdr, VERR_INVALID_POINTER);
590
591 VBoxShClRootListHdrMsg Msg;
592 RT_ZERO(Msg);
593
594 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID,
595 VBOX_SHCL_GUEST_FN_ROOT_LIST_HDR_WRITE, VBOX_SHCL_CPARMS_ROOT_LIST_HDR);
596
597 Msg.ReqParms.uContext.SetUInt32(pCtx->uContextID);
598 Msg.ReqParms.fRoots.SetUInt32(pRootListHdr->fRoots);
599
600 Msg.cRoots.SetUInt32(pRootListHdr->cRoots);
601
602 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
603
604 LogFlowFuncLeaveRC(rc);
605 return rc;
606}
607
608VBGLR3DECL(int) VbglR3ClipboardRootListEntryReadReq(PVBGLR3SHCLCMDCTX pCtx, uint32_t *puIndex, uint32_t *pfInfo)
609{
610 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
611 AssertPtrReturn(puIndex, VERR_INVALID_POINTER);
612 AssertPtrReturn(pfInfo, VERR_INVALID_POINTER);
613
614 VBoxShClRootListEntryReadReqMsg Msg;
615 RT_ZERO(Msg);
616
617 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID,
618 VBOX_SHCL_GUEST_FN_MSG_GET, VBOX_SHCL_CPARMS_ROOT_LIST_ENTRY_READ_REQ);
619
620 Msg.Parms.uContext.SetUInt32(VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_ENTRY_READ);
621 Msg.Parms.fInfo.SetUInt32(0);
622 Msg.Parms.uIndex.SetUInt32(0);
623
624 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
625 if (RT_SUCCESS(rc))
626 {
627 rc = Msg.Parms.uContext.GetUInt32(&pCtx->uContextID); AssertRC(rc);
628 if (RT_SUCCESS(rc))
629 rc = Msg.Parms.fInfo.GetUInt32(pfInfo); AssertRC(rc);
630 if (RT_SUCCESS(rc))
631 rc = Msg.Parms.uIndex.GetUInt32(puIndex); AssertRC(rc);
632 }
633
634 LogFlowFuncLeaveRC(rc);
635 return rc;
636}
637
638VBGLR3DECL(int) VbglR3ClipboardRootListEntryReadReply(PVBGLR3SHCLCMDCTX pCtx, uint32_t uIndex, PSHCLROOTLISTENTRY pEntry)
639{
640 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
641 AssertPtrReturn(pEntry, VERR_INVALID_POINTER);
642
643 VBoxShClRootListEntryMsg Msg;
644 RT_ZERO(Msg);
645
646 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID,
647 VBOX_SHCL_GUEST_FN_ROOT_LIST_ENTRY_WRITE, VBOX_SHCL_CPARMS_ROOT_LIST_ENTRY);
648
649 Msg.Parms.uContext.SetUInt32(pCtx->uContextID);
650 Msg.Parms.fInfo.SetUInt32(0);
651 Msg.Parms.uIndex.SetUInt32(uIndex);
652
653 Msg.szName.SetPtr(pEntry->pszName, pEntry->cbName);
654 Msg.cbInfo.SetUInt32(pEntry->cbInfo);
655 Msg.pvInfo.SetPtr(pEntry->pvInfo, pEntry->cbInfo);
656
657 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
658
659 LogFlowFuncLeaveRC(rc);
660 return rc;
661}
662
663VBGLR3DECL(int) VbglR3ClipboardListOpenSend(PVBGLR3SHCLCMDCTX pCtx, PSHCLLISTOPENPARMS pOpenParms,
664 PSHCLLISTHANDLE phList)
665{
666 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
667 AssertPtrReturn(pOpenParms, VERR_INVALID_POINTER);
668 AssertPtrReturn(phList, VERR_INVALID_POINTER);
669
670 VBoxShClListOpenMsg Msg;
671 RT_ZERO(Msg);
672
673 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID,
674 VBOX_SHCL_GUEST_FN_LIST_OPEN, VBOX_SHCL_CPARMS_LIST_OPEN);
675
676 Msg.uContext.SetUInt32(pCtx->uContextID);
677 Msg.fList.SetUInt32(0);
678 Msg.cbFilter.SetUInt32(pOpenParms->cbFilter);
679 Msg.pvFilter.SetPtr(pOpenParms->pszFilter, pOpenParms->cbFilter);
680 Msg.cbPath.SetUInt32(pOpenParms->cbPath);
681 Msg.pvFilter.SetPtr(pOpenParms->pszPath, pOpenParms->cbPath);
682
683 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
684 if (RT_SUCCESS(rc))
685 {
686 rc = Msg.uHandle.GetUInt64(phList); AssertRC(rc);
687 }
688
689 LogFlowFuncLeaveRC(rc);
690 return rc;
691}
692
693VBGLR3DECL(int) VbglR3ClipboardListOpenRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLLISTOPENPARMS pOpenParms)
694{
695 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
696 AssertPtrReturn(pOpenParms, VERR_INVALID_POINTER);
697
698 VBoxShClListOpenMsg Msg;
699 RT_ZERO(Msg);
700
701 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID,
702 VBOX_SHCL_GUEST_FN_MSG_GET, VBOX_SHCL_CPARMS_LIST_OPEN);
703
704 Msg.uContext.SetUInt32(VBOX_SHCL_HOST_MSG_TRANSFER_LIST_OPEN);
705 Msg.fList.SetUInt32(0);
706 Msg.cbPath.SetUInt32(pOpenParms->cbPath);
707 Msg.pvPath.SetPtr(pOpenParms->pszPath, pOpenParms->cbPath);
708 Msg.cbFilter.SetUInt32(pOpenParms->cbFilter);
709 Msg.pvFilter.SetPtr(pOpenParms->pszFilter, pOpenParms->cbFilter);
710 Msg.uHandle.SetUInt64(0);
711
712 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
713 if (RT_SUCCESS(rc))
714 {
715 rc = Msg.uContext.GetUInt32(&pCtx->uContextID);
716 if (RT_SUCCESS(rc))
717 rc = Msg.fList.GetUInt32(&pOpenParms->fList);
718 if (RT_SUCCESS(rc))
719 rc = Msg.cbFilter.GetUInt32(&pOpenParms->cbFilter);
720 if (RT_SUCCESS(rc))
721 rc = Msg.cbPath.GetUInt32(&pOpenParms->cbPath);
722 }
723
724 LogFlowFuncLeaveRC(rc);
725 return rc;
726}
727
728VBGLR3DECL(int) VbglR3ClipboardListOpenReply(PVBGLR3SHCLCMDCTX pCtx, int rcReply, SHCLLISTHANDLE hList)
729{
730 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
731
732 VBoxShClReplyMsg Msg;
733 RT_ZERO(Msg);
734
735 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID,
736 VBOX_SHCL_GUEST_FN_REPLY, VBOX_SHCL_CPARMS_REPLY_MIN + 1);
737
738 Msg.uContext.SetUInt32(pCtx->uContextID);
739 Msg.enmType.SetUInt32(VBOX_SHCL_REPLYMSGTYPE_LIST_OPEN);
740 Msg.rc.SetUInt32((uint32_t)rcReply); /** int vs. uint32_t */
741 Msg.cbPayload.SetUInt32(0);
742 Msg.pvPayload.SetPtr(NULL, 0);
743
744 Msg.u.ListOpen.uHandle.SetUInt64(hList);
745
746 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
747
748 LogFlowFuncLeaveRC(rc);
749 return rc;
750}
751
752VBGLR3DECL(int) VbglR3ClipboardListCloseRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLLISTHANDLE phList)
753{
754 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
755 AssertPtrReturn(phList, VERR_INVALID_POINTER);
756
757 VBoxShClListCloseMsg Msg;
758 RT_ZERO(Msg);
759
760 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID,
761 VBOX_SHCL_GUEST_FN_MSG_GET, VBOX_SHCL_CPARMS_LIST_CLOSE);
762
763 Msg.uContext.SetUInt32(VBOX_SHCL_HOST_MSG_TRANSFER_LIST_CLOSE);
764 Msg.uHandle.SetUInt64(0);
765
766 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
767 if (RT_SUCCESS(rc))
768 {
769 rc = Msg.uContext.GetUInt32(&pCtx->uContextID);
770 if (RT_SUCCESS(rc))
771 rc = Msg.uHandle.GetUInt64(phList); AssertRC(rc);
772 }
773
774 LogFlowFuncLeaveRC(rc);
775 return rc;
776}
777
778VBGLR3DECL(int) VbglR3ClipboardListCloseReply(PVBGLR3SHCLCMDCTX pCtx, int rcReply, SHCLLISTHANDLE hList)
779{
780 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
781
782 VBoxShClReplyMsg Msg;
783 RT_ZERO(Msg);
784
785 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID,
786 VBOX_SHCL_GUEST_FN_REPLY, VBOX_SHCL_CPARMS_REPLY_MIN + 1);
787
788 Msg.uContext.SetUInt32(pCtx->uContextID);
789 Msg.enmType.SetUInt32(VBOX_SHCL_REPLYMSGTYPE_LIST_CLOSE);
790 Msg.rc.SetUInt32((uint32_t)rcReply); /** int vs. uint32_t */
791 Msg.cbPayload.SetUInt32(0);
792 Msg.pvPayload.SetPtr(NULL, 0);
793
794 Msg.u.ListOpen.uHandle.SetUInt64(hList);
795
796 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
797
798 LogFlowFuncLeaveRC(rc);
799 return rc;
800}
801
802VBGLR3DECL(int) VbglR3ClipboardListCloseSend(PVBGLR3SHCLCMDCTX pCtx, SHCLLISTHANDLE hList)
803{
804 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
805
806 VBoxShClListCloseMsg Msg;
807 RT_ZERO(Msg);
808
809 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID,
810 VBOX_SHCL_HOST_MSG_TRANSFER_LIST_CLOSE, VBOX_SHCL_CPARMS_LIST_CLOSE);
811
812 Msg.uContext.SetUInt32(pCtx->uContextID);
813 Msg.uHandle.SetUInt64(hList);
814
815 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
816
817 LogFlowFuncLeaveRC(rc);
818 return rc;
819}
820
821
822VBGLR3DECL(int) VbglR3ClipboardListHdrRead(PVBGLR3SHCLCMDCTX pCtx, SHCLLISTHANDLE hList, uint32_t fFlags,
823 PSHCLLISTHDR pListHdr)
824{
825 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
826 AssertPtrReturn(pListHdr, VERR_INVALID_POINTER);
827
828 VBoxShClListHdrMsg Msg;
829 RT_ZERO(Msg);
830
831 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID,
832 VBOX_SHCL_GUEST_FN_LIST_HDR_READ, VBOX_SHCL_CPARMS_LIST_HDR);
833
834 Msg.ReqParms.uContext.SetUInt32(pCtx->uContextID);
835 Msg.ReqParms.uHandle.SetUInt64(hList);
836 Msg.ReqParms.fFlags.SetUInt32(fFlags);
837
838 Msg.fFeatures.SetUInt32(0);
839 Msg.cbTotalSize.SetUInt32(0);
840 Msg.cTotalObjects.SetUInt64(0);
841 Msg.cbTotalSize.SetUInt64(0);
842
843 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
844 if (RT_SUCCESS(rc))
845 {
846 rc = Msg.fFeatures.GetUInt32(&pListHdr->fFeatures);
847 if (RT_SUCCESS(rc))
848 rc = Msg.cTotalObjects.GetUInt64(&pListHdr->cTotalObjects);
849 if (RT_SUCCESS(rc))
850 rc = Msg.cbTotalSize.GetUInt64(&pListHdr->cbTotalSize);
851 }
852
853 LogFlowFuncLeaveRC(rc);
854 return rc;
855}
856
857VBGLR3DECL(int) VbglR3ClipboardListHdrReadRecvReq(PVBGLR3SHCLCMDCTX pCtx, PSHCLLISTHANDLE phList, uint32_t *pfFlags)
858{
859 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
860 AssertPtrReturn(phList, VERR_INVALID_POINTER);
861 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
862
863 VBoxShClListHdrReadReqMsg Msg;
864 RT_ZERO(Msg);
865
866 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID,
867 VBOX_SHCL_GUEST_FN_MSG_GET, VBOX_SHCL_CPARMS_LIST_HDR_READ_REQ);
868
869 Msg.ReqParms.uContext.SetUInt32(VBOX_SHCL_HOST_MSG_TRANSFER_LIST_HDR_READ);
870 Msg.ReqParms.uHandle.SetUInt64(0);
871 Msg.ReqParms.fFlags.SetUInt32(0);
872
873 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
874 if (RT_SUCCESS(rc))
875 {
876 rc = Msg.ReqParms.uContext.GetUInt32(&pCtx->uContextID);
877 if (RT_SUCCESS(rc))
878 rc = Msg.ReqParms.uHandle.GetUInt64(phList);
879 if (RT_SUCCESS(rc))
880 rc = Msg.ReqParms.fFlags.GetUInt32(pfFlags);
881 }
882
883 LogFlowFuncLeaveRC(rc);
884 return rc;
885}
886
887VBGLR3DECL(int) VbglR3ClipboardListHdrWrite(PVBGLR3SHCLCMDCTX pCtx, SHCLLISTHANDLE hList,
888 PSHCLLISTHDR pListHdr)
889{
890 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
891 AssertPtrReturn(pListHdr, VERR_INVALID_POINTER);
892
893 VBoxShClListHdrMsg Msg;
894 RT_ZERO(Msg);
895
896 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID,
897 VBOX_SHCL_GUEST_FN_LIST_HDR_WRITE, VBOX_SHCL_CPARMS_LIST_HDR);
898
899 Msg.ReqParms.uContext.SetUInt32(pCtx->uContextID);
900 Msg.ReqParms.uHandle.SetUInt64(hList);
901 Msg.ReqParms.fFlags.SetUInt32(0);
902
903 Msg.fFeatures.SetUInt32(0);
904 Msg.cbTotalSize.SetUInt32(pListHdr->fFeatures);
905 Msg.cTotalObjects.SetUInt64(pListHdr->cTotalObjects);
906 Msg.cbTotalSize.SetUInt64(pListHdr->cbTotalSize);
907
908 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
909
910 LogFlowFuncLeaveRC(rc);
911 return rc;
912}
913
914VBGLR3DECL(int) VbglR3ClipboardListEntryRead(PVBGLR3SHCLCMDCTX pCtx, SHCLLISTHANDLE hList,
915 PSHCLLISTENTRY pListEntry)
916{
917 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
918 AssertPtrReturn(pListEntry, VERR_INVALID_POINTER);
919
920 VBoxShClListEntryMsg Msg;
921 RT_ZERO(Msg);
922
923 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID,
924 VBOX_SHCL_GUEST_FN_LIST_ENTRY_READ, VBOX_SHCL_CPARMS_LIST_ENTRY);
925
926 Msg.ReqParms.uContext.SetUInt32(pCtx->uContextID);
927 Msg.ReqParms.uHandle.SetUInt64(hList);
928 Msg.ReqParms.fInfo.SetUInt32(0);
929
930 Msg.szName.SetPtr(pListEntry->pszName, pListEntry->cbName);
931 Msg.cbInfo.SetUInt32(pListEntry->cbInfo);
932 Msg.pvInfo.SetPtr(pListEntry->pvInfo, pListEntry->cbInfo);
933
934 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
935 if (RT_SUCCESS(rc))
936 {
937 rc = Msg.cbInfo.GetUInt32(&pListEntry->cbInfo); AssertRC(rc);
938 }
939
940 LogFlowFuncLeaveRC(rc);
941 return rc;
942}
943
944VBGLR3DECL(int) VbglR3ClipboardListEntryReadRecvReq(PVBGLR3SHCLCMDCTX pCtx, PSHCLLISTHANDLE phList, uint32_t *pfInfo)
945{
946 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
947 AssertPtrReturn(phList, VERR_INVALID_POINTER);
948 AssertPtrReturn(pfInfo, VERR_INVALID_POINTER);
949
950 VBoxShClListEntryReadReqMsg Msg;
951 RT_ZERO(Msg);
952
953 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID,
954 VBOX_SHCL_GUEST_FN_MSG_GET, VBOX_SHCL_CPARMS_LIST_ENTRY_READ);
955
956 Msg.ReqParms.uContext.SetUInt32(VBOX_SHCL_HOST_MSG_TRANSFER_LIST_ENTRY_READ);
957 Msg.ReqParms.uHandle.SetUInt64(0);
958 Msg.ReqParms.fInfo.SetUInt32(0);
959
960 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
961 if (RT_SUCCESS(rc))
962 {
963 rc = Msg.ReqParms.uContext.GetUInt32(&pCtx->uContextID);
964 if (RT_SUCCESS(rc))
965 rc = Msg.ReqParms.uHandle.GetUInt64(phList); AssertRC(rc);
966 if (RT_SUCCESS(rc))
967 rc = Msg.ReqParms.fInfo.GetUInt32(pfInfo); AssertRC(rc);
968 }
969
970 LogFlowFuncLeaveRC(rc);
971 return rc;
972}
973
974VBGLR3DECL(int) VbglR3ClipboardListEntryWrite(PVBGLR3SHCLCMDCTX pCtx, SHCLLISTHANDLE hList,
975 PSHCLLISTENTRY pListEntry)
976{
977 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
978 AssertPtrReturn(pListEntry, VERR_INVALID_POINTER);
979
980 VBoxShClListEntryMsg Msg;
981 RT_ZERO(Msg);
982
983 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID,
984 VBOX_SHCL_GUEST_FN_LIST_ENTRY_WRITE, VBOX_SHCL_CPARMS_LIST_ENTRY);
985
986 Msg.ReqParms.uContext.SetUInt32(pCtx->uContextID);
987 Msg.ReqParms.uHandle.SetUInt64(hList);
988 Msg.ReqParms.fInfo.SetUInt32(pListEntry->fInfo);
989
990 Msg.szName.SetPtr(pListEntry->pszName, pListEntry->cbName);
991 Msg.cbInfo.SetUInt32(pListEntry->cbInfo);
992 Msg.pvInfo.SetPtr(pListEntry->pvInfo, pListEntry->cbInfo);
993
994 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
995
996 LogFlowFuncLeaveRC(rc);
997 return rc;
998}
999
1000VBGLR3DECL(int) VbglR3ClipboardObjOpenRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLOBJOPENCREATEPARMS pCreateParms)
1001{
1002 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1003 AssertPtrReturn(pCreateParms, VERR_INVALID_POINTER);
1004
1005 VBoxShClObjOpenMsg Msg;
1006 RT_ZERO(Msg);
1007
1008 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID,
1009 VBOX_SHCL_GUEST_FN_MSG_GET, VBOX_SHCL_CPARMS_OBJ_OPEN);
1010
1011 Msg.uContext.SetUInt32(VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_OPEN);
1012 Msg.uHandle.SetUInt64(0);
1013 Msg.cbPath.SetUInt32(pCreateParms->cbPath);
1014 Msg.szPath.SetPtr(pCreateParms->pszPath, pCreateParms->cbPath);
1015 Msg.fCreate.SetUInt32(0);
1016
1017 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1018 if (RT_SUCCESS(rc))
1019 {
1020 rc = Msg.uContext.GetUInt32(&pCtx->uContextID);
1021 if (RT_SUCCESS(rc))
1022 rc = Msg.cbPath.GetUInt32(&pCreateParms->cbPath);
1023 if (RT_SUCCESS(rc))
1024 rc = Msg.fCreate.GetUInt32(&pCreateParms->fCreate);
1025 }
1026
1027 LogFlowFuncLeaveRC(rc);
1028 return rc;
1029}
1030
1031VBGLR3DECL(int) VbglR3ClipboardObjOpenReply(PVBGLR3SHCLCMDCTX pCtx, int rcReply, SHCLOBJHANDLE hObj)
1032{
1033 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1034
1035 VBoxShClReplyMsg Msg;
1036 RT_ZERO(Msg);
1037
1038 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID,
1039 VBOX_SHCL_GUEST_FN_REPLY, VBOX_SHCL_CPARMS_REPLY_MIN + 1);
1040
1041 Msg.uContext.SetUInt32(pCtx->uContextID);
1042 Msg.enmType.SetUInt32(VBOX_SHCL_REPLYMSGTYPE_OBJ_OPEN);
1043 Msg.rc.SetUInt32((uint32_t)rcReply); /** int vs. uint32_t */
1044 Msg.cbPayload.SetUInt32(0);
1045 Msg.pvPayload.SetPtr(NULL, 0);
1046
1047 Msg.u.ObjOpen.uHandle.SetUInt64(hObj);
1048
1049 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1050
1051 LogFlowFuncLeaveRC(rc);
1052 return rc;
1053}
1054
1055VBGLR3DECL(int) VbglR3ClipboardObjOpenSend(PVBGLR3SHCLCMDCTX pCtx, PSHCLOBJOPENCREATEPARMS pCreateParms,
1056 PSHCLOBJHANDLE phObj)
1057{
1058 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1059 AssertPtrReturn(pCreateParms, VERR_INVALID_POINTER);
1060 AssertPtrReturn(phObj, VERR_INVALID_POINTER);
1061
1062 VBoxShClObjOpenMsg Msg;
1063 RT_ZERO(Msg);
1064
1065 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID,
1066 VBOX_SHCL_GUEST_FN_OBJ_OPEN, VBOX_SHCL_CPARMS_OBJ_OPEN);
1067
1068 Msg.uContext.SetUInt32(pCtx->uContextID);
1069 Msg.uHandle.SetUInt64(0);
1070 Msg.cbPath.SetUInt32(pCreateParms->cbPath);
1071 Msg.szPath.SetPtr((void *)pCreateParms->pszPath, pCreateParms->cbPath + 1 /* Include terminating zero */);
1072 Msg.fCreate.SetUInt32(pCreateParms->fCreate);
1073
1074 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1075 if (RT_SUCCESS(rc))
1076 {
1077 Msg.uHandle.GetUInt64(phObj);
1078 }
1079
1080 LogFlowFuncLeaveRC(rc);
1081 return rc;
1082}
1083
1084VBGLR3DECL(int) VbglR3ClipboardObjCloseRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLOBJHANDLE phObj)
1085{
1086 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1087 AssertPtrReturn(phObj, VERR_INVALID_POINTER);
1088
1089 VBoxShClObjCloseMsg Msg;
1090 RT_ZERO(Msg);
1091
1092 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID,
1093 VBOX_SHCL_GUEST_FN_MSG_GET, VBOX_SHCL_CPARMS_OBJ_CLOSE);
1094
1095 Msg.uContext.SetUInt32(VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_CLOSE);
1096 Msg.uHandle.SetUInt64(0);
1097
1098 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1099 if (RT_SUCCESS(rc))
1100 {
1101 rc = Msg.uContext.GetUInt32(&pCtx->uContextID);
1102 if (RT_SUCCESS(rc))
1103 rc = Msg.uHandle.GetUInt64(phObj);
1104 }
1105
1106 LogFlowFuncLeaveRC(rc);
1107 return rc;
1108}
1109
1110VBGLR3DECL(int) VbglR3ClipboardObjCloseReply(PVBGLR3SHCLCMDCTX pCtx, int rcReply, SHCLOBJHANDLE hObj)
1111{
1112 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1113
1114 VBoxShClReplyMsg Msg;
1115 RT_ZERO(Msg);
1116
1117 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID,
1118 VBOX_SHCL_GUEST_FN_REPLY, VBOX_SHCL_CPARMS_REPLY_MIN + 1);
1119
1120 Msg.uContext.SetUInt32(pCtx->uContextID);
1121 Msg.enmType.SetUInt32(VBOX_SHCL_REPLYMSGTYPE_OBJ_CLOSE);
1122 Msg.rc.SetUInt32((uint32_t)rcReply); /** int vs. uint32_t */
1123 Msg.cbPayload.SetUInt32(0);
1124 Msg.pvPayload.SetPtr(NULL, 0);
1125
1126 Msg.u.ObjClose.uHandle.SetUInt64(hObj);
1127
1128 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1129
1130 LogFlowFuncLeaveRC(rc);
1131 return rc;
1132}
1133
1134VBGLR3DECL(int) VbglR3ClipboardObjCloseSend(PVBGLR3SHCLCMDCTX pCtx, SHCLOBJHANDLE hObj)
1135{
1136 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1137
1138 VBoxShClObjCloseMsg Msg;
1139 RT_ZERO(Msg);
1140
1141 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID,
1142 VBOX_SHCL_GUEST_FN_OBJ_CLOSE, VBOX_SHCL_CPARMS_OBJ_CLOSE);
1143
1144 Msg.uContext.SetUInt32(pCtx->uContextID);
1145 Msg.uHandle.SetUInt64(hObj);
1146
1147 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1148
1149 LogFlowFuncLeaveRC(rc);
1150 return rc;
1151}
1152
1153VBGLR3DECL(int) VbglR3ClipboardObjReadRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLOBJHANDLE phObj, uint32_t *pcbToRead,
1154 uint32_t *pfFlags)
1155{
1156 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1157 AssertPtrReturn(phObj, VERR_INVALID_POINTER);
1158 AssertPtrReturn(pcbToRead, VERR_INVALID_POINTER);
1159 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
1160
1161 VBoxShClObjReadReqMsg Msg;
1162 RT_ZERO(Msg);
1163
1164 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID,
1165 VBOX_SHCL_GUEST_FN_MSG_GET, VBOX_SHCL_CPARMS_OBJ_READ_REQ);
1166
1167 Msg.ReqParms.uContext.SetUInt32(VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_READ);
1168 Msg.ReqParms.uHandle.SetUInt64(0);
1169 Msg.ReqParms.cbToRead.SetUInt32(0);
1170 Msg.ReqParms.fRead.SetUInt32(0);
1171
1172 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1173 if (RT_SUCCESS(rc))
1174 {
1175 rc = Msg.ReqParms.uContext.GetUInt32(&pCtx->uContextID);
1176 if (RT_SUCCESS(rc))
1177 rc = Msg.ReqParms.uHandle.GetUInt64(phObj);
1178 if (RT_SUCCESS(rc))
1179 rc = Msg.ReqParms.cbToRead.GetUInt32(pcbToRead);
1180 if (RT_SUCCESS(rc))
1181 rc = Msg.ReqParms.fRead.GetUInt32(pfFlags);
1182 }
1183
1184 LogFlowFuncLeaveRC(rc);
1185 return rc;
1186}
1187
1188VBGLR3DECL(int) VbglR3ClipboardObjReadSend(PVBGLR3SHCLCMDCTX pCtx, SHCLOBJHANDLE hObj,
1189 void *pvData, uint32_t cbData, uint32_t *pcbRead)
1190{
1191 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1192 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
1193 AssertReturn(cbData, VERR_INVALID_PARAMETER);
1194 /* pcbRead is optional. */
1195
1196 VBoxShClObjReadWriteMsg Msg;
1197 RT_ZERO(Msg);
1198
1199 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID,
1200 VBOX_SHCL_GUEST_FN_OBJ_READ, VBOX_SHCL_CPARMS_OBJ_READ);
1201
1202 Msg.uContext.SetUInt32(pCtx->uContextID);
1203 Msg.uHandle.SetUInt64(hObj);
1204 Msg.pvData.SetPtr(pvData, cbData);
1205 Msg.cbData.SetUInt32(cbData);
1206 Msg.pvChecksum.SetPtr(NULL, 0);
1207 Msg.cbChecksum.SetUInt32(0);
1208
1209 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1210 if (RT_SUCCESS(rc))
1211 {
1212 /** @todo Add checksum support. */
1213
1214 if (pcbRead)
1215 {
1216 rc = Msg.cbData.GetUInt32(pcbRead); AssertRC(rc);
1217 AssertReturn(cbData >= *pcbRead, VERR_TOO_MUCH_DATA);
1218 }
1219 }
1220
1221 LogFlowFuncLeaveRC(rc);
1222 return rc;
1223}
1224
1225VBGLR3DECL(int) VbglR3ClipboardObjWriteSend(PVBGLR3SHCLCMDCTX pCtx, SHCLOBJHANDLE hObj,
1226 void *pvData, uint32_t cbData, uint32_t *pcbWritten)
1227{
1228 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1229 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
1230 /* cbData can be 0. */
1231 /* pcbWritten is optional. */
1232
1233 VBoxShClObjReadWriteMsg Msg;
1234 RT_ZERO(Msg);
1235
1236 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID,
1237 VBOX_SHCL_GUEST_FN_OBJ_WRITE, VBOX_SHCL_CPARMS_OBJ_WRITE);
1238
1239 Msg.uContext.SetUInt32(pCtx->uContextID);
1240 Msg.uHandle.SetUInt64(hObj);
1241 Msg.pvData.SetPtr(pvData, cbData);
1242 Msg.cbData.SetUInt32(cbData);
1243 Msg.pvChecksum.SetPtr(NULL, 0);
1244 Msg.cbChecksum.SetUInt32(0);
1245
1246 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1247 if (RT_SUCCESS(rc))
1248 {
1249 /** @todo Add checksum support. */
1250
1251 if (pcbWritten)
1252 *pcbWritten = cbData; /** @todo For now return all as being written. */
1253 }
1254
1255 LogFlowFuncLeaveRC(rc);
1256 return rc;
1257}
1258
1259/*********************************************************************************************************************************
1260* Transfer interface implementations *
1261*********************************************************************************************************************************/
1262
1263static int vbglR3ClipboardTransferIfaceGetRoots(PSHCLPROVIDERCTX pCtx, PSHCLROOTLIST *ppRootList)
1264{
1265 LogFlowFuncEnter();
1266
1267 PVBGLR3SHCLCMDCTX pCmdCtx = (PVBGLR3SHCLCMDCTX)pCtx->pvUser;
1268 AssertPtr(pCmdCtx);
1269
1270 int rc = VbglR3ClipboardRootListRead(pCmdCtx, ppRootList);
1271
1272 LogFlowFuncLeaveRC(rc);
1273 return rc;
1274}
1275
1276static int vbglR3ClipboardTransferIfaceListOpen(PSHCLPROVIDERCTX pCtx, PSHCLLISTOPENPARMS pOpenParms,
1277 PSHCLLISTHANDLE phList)
1278{
1279 LogFlowFuncEnter();
1280
1281 PVBGLR3SHCLCMDCTX pCmdCtx = (PVBGLR3SHCLCMDCTX)pCtx->pvUser;
1282 AssertPtr(pCmdCtx);
1283
1284 int rc = VbglR3ClipboardListOpenSend(pCmdCtx, pOpenParms, phList);
1285
1286 LogFlowFuncLeaveRC(rc);
1287 return rc;
1288}
1289
1290static int vbglR3ClipboardTransferIfaceListClose(PSHCLPROVIDERCTX pCtx, SHCLLISTHANDLE hList)
1291{
1292 LogFlowFuncEnter();
1293
1294 PVBGLR3SHCLCMDCTX pCmdCtx = (PVBGLR3SHCLCMDCTX)pCtx->pvUser;
1295 AssertPtr(pCmdCtx);
1296
1297 int rc = VbglR3ClipboardListCloseSend(pCmdCtx, hList);
1298
1299 LogFlowFuncLeaveRC(rc);
1300 return rc;
1301}
1302
1303static int vbglR3ClipboardTransferIfaceListHdrRead(PSHCLPROVIDERCTX pCtx,
1304 SHCLLISTHANDLE hList, PSHCLLISTHDR pListHdr)
1305{
1306 LogFlowFuncEnter();
1307
1308 PVBGLR3SHCLCMDCTX pCmdCtx = (PVBGLR3SHCLCMDCTX)pCtx->pvUser;
1309 AssertPtr(pCmdCtx);
1310
1311 int rc = SharedClipboardTransferListHdrInit(pListHdr);
1312 if (RT_SUCCESS(rc))
1313 {
1314 if (RT_SUCCESS(rc))
1315 {
1316 rc = VbglR3ClipboardListHdrRead(pCmdCtx, hList, 0 /* fFlags */, pListHdr);
1317 }
1318 else
1319 SharedClipboardTransferListHdrDestroy(pListHdr);
1320 }
1321
1322 LogFlowFuncLeaveRC(rc);
1323 return rc;
1324}
1325
1326static int vbglR3ClipboardTransferIfaceListEntryRead(PSHCLPROVIDERCTX pCtx,
1327 SHCLLISTHANDLE hList, PSHCLLISTENTRY pEntry)
1328{
1329 LogFlowFuncEnter();
1330
1331 PVBGLR3SHCLCMDCTX pCmdCtx = (PVBGLR3SHCLCMDCTX)pCtx->pvUser;
1332 AssertPtr(pCmdCtx);
1333
1334 int rc = VbglR3ClipboardListEntryRead(pCmdCtx, hList, pEntry);
1335
1336 LogFlowFuncLeaveRC(rc);
1337 return rc;
1338}
1339
1340static int vbglR3ClipboardTransferIfaceObjOpen(PSHCLPROVIDERCTX pCtx,
1341 PSHCLOBJOPENCREATEPARMS pCreateParms, PSHCLOBJHANDLE phObj)
1342{
1343 LogFlowFuncEnter();
1344
1345 PVBGLR3SHCLCMDCTX pCmdCtx = (PVBGLR3SHCLCMDCTX)pCtx->pvUser;
1346 AssertPtr(pCmdCtx);
1347
1348 int rc = VbglR3ClipboardObjOpenSend(pCmdCtx, pCreateParms, phObj);
1349
1350 LogFlowFuncLeaveRC(rc);
1351 return rc;
1352}
1353
1354static int vbglR3ClipboardTransferIfaceObjClose(PSHCLPROVIDERCTX pCtx, SHCLOBJHANDLE hObj)
1355{
1356 LogFlowFuncEnter();
1357
1358 PVBGLR3SHCLCMDCTX pCmdCtx = (PVBGLR3SHCLCMDCTX)pCtx->pvUser;
1359 AssertPtr(pCmdCtx);
1360
1361 int rc = VbglR3ClipboardObjCloseSend(pCmdCtx, hObj);
1362
1363 LogFlowFuncLeaveRC(rc);
1364 return rc;
1365}
1366
1367static int vbglR3ClipboardTransferIfaceObjRead(PSHCLPROVIDERCTX pCtx,
1368 SHCLOBJHANDLE hObj, void *pvData, uint32_t cbData,
1369 uint32_t fFlags, uint32_t *pcbRead)
1370{
1371 LogFlowFuncEnter();
1372
1373 PVBGLR3SHCLCMDCTX pCmdCtx = (PVBGLR3SHCLCMDCTX)pCtx->pvUser;
1374 AssertPtr(pCmdCtx);
1375
1376 RT_NOREF(fFlags); /* Not used yet. */
1377
1378 int rc = VbglR3ClipboardObjReadSend(pCmdCtx, hObj, pvData, cbData, pcbRead);
1379
1380 LogFlowFuncLeaveRC(rc);
1381 return rc;
1382}
1383
1384/**
1385 * Starts a transfer on the guest side.
1386 *
1387 * @returns VBox status code.
1388 * @param pCmdCtx Command context to use.
1389 * @param pTransferCtx Transfer context to create transfer for.
1390 * @param uTransferID ID to use for transfer to start.
1391 * @param enmDir Direction of transfer to start.
1392 * @param enmSource Source of transfer to start.
1393 * @param ppTransfer Where to return the transfer object on success. Optional.
1394 */
1395static int vbglR3ClipboardTransferStart(PVBGLR3SHCLCMDCTX pCmdCtx, PSHCLTRANSFERCTX pTransferCtx,
1396 SHCLTRANSFERID uTransferID, SHCLTRANSFERDIR enmDir, SHCLSOURCE enmSource,
1397 PSHCLTRANSFER *ppTransfer)
1398{
1399 PSHCLTRANSFER pTransfer;
1400 int rc = SharedClipboardTransferCreate(&pTransfer);
1401 if (RT_SUCCESS(rc))
1402 {
1403 SharedClipboardTransferSetCallbacks(pTransfer, &pCmdCtx->Transfers.Callbacks);
1404
1405 rc = SharedClipboardTransferCtxTransferRegisterByIndex(pTransferCtx, pTransfer, uTransferID);
1406 if (RT_SUCCESS(rc))
1407 {
1408 rc = SharedClipboardTransferInit(pTransfer, uTransferID, enmDir, enmSource);
1409 if (RT_SUCCESS(rc))
1410 {
1411 /* If this is a read transfer (reading data from host), set the interface to use
1412 * our VbglR3 routines here. */
1413 if (enmDir == SHCLTRANSFERDIR_READ)
1414 {
1415 SHCLPROVIDERCREATIONCTX creationCtx;
1416 RT_ZERO(creationCtx);
1417
1418 creationCtx.Interface.pfnRootsGet = vbglR3ClipboardTransferIfaceGetRoots;
1419
1420 creationCtx.Interface.pfnListOpen = vbglR3ClipboardTransferIfaceListOpen;
1421 creationCtx.Interface.pfnListClose = vbglR3ClipboardTransferIfaceListClose;
1422 creationCtx.Interface.pfnListHdrRead = vbglR3ClipboardTransferIfaceListHdrRead;
1423 creationCtx.Interface.pfnListEntryRead = vbglR3ClipboardTransferIfaceListEntryRead;
1424
1425 creationCtx.Interface.pfnObjOpen = vbglR3ClipboardTransferIfaceObjOpen;
1426 creationCtx.Interface.pfnObjClose = vbglR3ClipboardTransferIfaceObjClose;
1427 creationCtx.Interface.pfnObjRead = vbglR3ClipboardTransferIfaceObjRead;
1428
1429 rc = SharedClipboardTransferSetInterface(pTransfer, &creationCtx);
1430 }
1431
1432 if (RT_SUCCESS(rc))
1433 rc = SharedClipboardTransferStart(pTransfer);
1434 }
1435
1436 if (RT_FAILURE(rc))
1437 SharedClipboardTransferCtxTransferUnregister(pTransferCtx, uTransferID);
1438 }
1439 }
1440
1441 if (RT_SUCCESS(rc))
1442 {
1443 if (ppTransfer)
1444 *ppTransfer = pTransfer;
1445
1446 LogRel2(("Shared Clipboard: Transfer ID=%RU16 (%s %s) successfully started\n",
1447 uTransferID,
1448 enmDir == SHCLTRANSFERDIR_READ ? "reading from" : "writing to",
1449 enmSource == SHCLSOURCE_LOCAL ? "local" : "remote"));
1450 }
1451 else
1452 LogRel(("Shared Clipboard: Unable to start transfer ID=%RU16, rc=%Rrc\n", uTransferID, rc));
1453
1454 /* Send a reply in any case. */
1455 int rc2 = VbglR3ClipboardTransferStatusReply(pCmdCtx, pTransfer,
1456 RT_SUCCESS(rc)
1457 ? SHCLTRANSFERSTATUS_STARTED : SHCLTRANSFERSTATUS_ERROR, rc);
1458 AssertRC(rc2);
1459
1460 if (RT_FAILURE(rc))
1461 {
1462 SharedClipboardTransferDestroy(pTransfer);
1463 pTransfer = NULL;
1464 }
1465
1466 LogFlowFuncLeaveRC(rc);
1467 return rc;
1468}
1469
1470/**
1471 * Stops a transfer on the guest side.
1472 *
1473 * @returns VBox status code, or VERR_NOT_FOUND if transfer has not been found.
1474 * @param pCmdCtx Command context to use.
1475 * @param pTransferCtx Transfer context to stop transfer for.
1476 * @param uTransferID ID of transfer to stop.
1477 */
1478static int vbglR3ClipboardTransferStop(PVBGLR3SHCLCMDCTX pCmdCtx, PSHCLTRANSFERCTX pTransferCtx,
1479 SHCLTRANSFERID uTransferID)
1480{
1481 int rc;
1482
1483 PSHCLTRANSFER pTransfer = SharedClipboardTransferCtxGetTransfer(pTransferCtx, uTransferID);
1484 if (pTransfer)
1485 {
1486 rc = SharedClipboardTransferClose(pTransfer);
1487 if (RT_SUCCESS(rc))
1488 rc = SharedClipboardTransferCtxTransferUnregister(pTransferCtx, uTransferID);
1489
1490 if (RT_SUCCESS(rc))
1491 {
1492 LogRel2(("Shared Clipboard: Transfer ID=%RU16 successfully stopped\n", uTransferID));
1493 }
1494 else
1495 LogRel(("Shared Clipboard: Unable to stop transfer ID=%RU16, rc=%Rrc\n", uTransferID, rc));
1496
1497 /* Send a reply in any case. */
1498 int rc2 = VbglR3ClipboardTransferStatusReply(pCmdCtx, pTransfer,
1499 RT_SUCCESS(rc)
1500 ? SHCLTRANSFERSTATUS_STOPPED : SHCLTRANSFERSTATUS_ERROR, rc);
1501 AssertRC(rc2);
1502 }
1503 else
1504 rc = VERR_NOT_FOUND;
1505
1506 LogFlowFuncLeaveRC(rc);
1507 return rc;
1508}
1509
1510VBGLR3DECL(int) VbglR3ClipboardEventGetNextEx(uint32_t idMsg, uint32_t cParms,
1511 PVBGLR3SHCLCMDCTX pCmdCtx, PSHCLTRANSFERCTX pTransferCtx,
1512 PVBGLR3CLIPBOARDEVENT pEvent)
1513{
1514 AssertPtrReturn(pCmdCtx, VERR_INVALID_POINTER);
1515 AssertPtrReturn(pTransferCtx, VERR_INVALID_POINTER);
1516 AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
1517
1518 LogFunc(("Handling idMsg=%RU32 (%s), cParms=%RU32\n", idMsg, VBoxShClHostMsgToStr(idMsg), cParms));
1519
1520 int rc;
1521
1522 switch (idMsg)
1523 {
1524 case VBOX_SHCL_HOST_MSG_TRANSFER_STATUS:
1525 {
1526 SHCLTRANSFERDIR enmDir;
1527 SHCLTRANSFERREPORT transferReport;
1528 rc = VbglR3ClipboarTransferStatusRecv(pCmdCtx, &enmDir, &transferReport);
1529 if (RT_SUCCESS(rc))
1530 {
1531 const SHCLTRANSFERID uTransferID = VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->uContextID);
1532
1533 LogFlowFunc(("[Transfer %RU16] enmDir=%RU32, status=%s\n",
1534 uTransferID, enmDir, VBoxShClTransferStatusToStr(transferReport.uStatus)));
1535
1536 switch (transferReport.uStatus)
1537 {
1538 case SHCLTRANSFERSTATUS_INITIALIZED:
1539 RT_FALL_THROUGH();
1540 case SHCLTRANSFERSTATUS_STARTED:
1541 {
1542 SHCLSOURCE enmSource = SHCLSOURCE_INVALID;
1543
1544 /* The host announces the transfer direction from its point of view, so inverse the direction here. */
1545 if (enmDir == SHCLTRANSFERDIR_WRITE)
1546 {
1547 enmDir = SHCLTRANSFERDIR_READ;
1548 enmSource = SHCLSOURCE_REMOTE;
1549 }
1550 else if (enmDir == SHCLTRANSFERDIR_READ)
1551 {
1552 enmDir = SHCLTRANSFERDIR_WRITE;
1553 enmSource = SHCLSOURCE_LOCAL;
1554 }
1555 else
1556 AssertFailedBreakStmt(rc = VERR_INVALID_PARAMETER);
1557
1558 rc = vbglR3ClipboardTransferStart(pCmdCtx, pTransferCtx, uTransferID,
1559 enmDir, enmSource, NULL /* ppTransfer */);
1560 break;
1561 }
1562
1563 case SHCLTRANSFERSTATUS_STOPPED:
1564 RT_FALL_THROUGH();
1565 case SHCLTRANSFERSTATUS_CANCELED:
1566 RT_FALL_THROUGH();
1567 case SHCLTRANSFERSTATUS_KILLED:
1568 RT_FALL_THROUGH();
1569 case SHCLTRANSFERSTATUS_ERROR:
1570 {
1571 rc = vbglR3ClipboardTransferStop(pCmdCtx, pTransferCtx,
1572 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->uContextID));
1573 break;
1574 }
1575
1576 default:
1577 rc = VERR_NOT_SUPPORTED;
1578 break;
1579 }
1580
1581 if (RT_SUCCESS(rc))
1582 {
1583 pEvent->u.TransferStatus.enmDir = enmDir;
1584 pEvent->u.TransferStatus.Report = transferReport;
1585 pEvent->u.TransferStatus.uID = VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->uContextID);
1586
1587 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_URI_TRANSFER_STATUS;
1588
1589 LogRel2(("Shared Clipboard: Received status %s (rc=%Rrc) for transfer ID=%RU16\n",
1590 VBoxShClTransferStatusToStr(pEvent->u.TransferStatus.Report.uStatus), pEvent->u.TransferStatus.Report.rc,
1591 pEvent->u.TransferStatus.uID));
1592 }
1593 }
1594 break;
1595 }
1596
1597 case VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_HDR_READ:
1598 {
1599 uint32_t fRoots;
1600 rc = VbglR3ClipboardRootListHdrReadReq(pCmdCtx, &fRoots);
1601
1602 /** @todo Validate / handle fRoots. */
1603
1604 if (RT_SUCCESS(rc))
1605 {
1606 PSHCLTRANSFER pTransfer = SharedClipboardTransferCtxGetTransfer(pTransferCtx,
1607 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->uContextID));
1608 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND);
1609
1610 SHCLROOTLISTHDR rootListHdr;
1611 RT_ZERO(rootListHdr);
1612
1613 rootListHdr.cRoots = SharedClipboardTransferRootsCount(pTransfer);
1614
1615 LogFlowFunc(("cRoots=%RU32\n", rootListHdr.cRoots));
1616
1617 rc = VbglR3ClipboardRootListHdrReadReply(pCmdCtx, &rootListHdr);
1618 }
1619 break;
1620 }
1621
1622 case VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_ENTRY_READ:
1623 {
1624 uint32_t uIndex;
1625 uint32_t fInfo;
1626 rc = VbglR3ClipboardRootListEntryReadReq(pCmdCtx, &uIndex, &fInfo);
1627 if (RT_SUCCESS(rc))
1628 {
1629 PSHCLTRANSFER pTransfer = SharedClipboardTransferCtxGetTransfer(pTransferCtx,
1630 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->uContextID));
1631 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND);
1632
1633 SHCLROOTLISTENTRY rootListEntry;
1634 rc = SharedClipboardTransferRootsEntry(pTransfer, uIndex, &rootListEntry);
1635 if (RT_SUCCESS(rc))
1636 rc = VbglR3ClipboardRootListEntryReadReply(pCmdCtx, uIndex, &rootListEntry);
1637 }
1638 break;
1639 }
1640
1641 case VBOX_SHCL_HOST_MSG_TRANSFER_LIST_OPEN:
1642 {
1643 SHCLLISTOPENPARMS openParmsList;
1644 rc = SharedClipboardTransferListOpenParmsInit(&openParmsList);
1645 if (RT_SUCCESS(rc))
1646 {
1647 rc = VbglR3ClipboardListOpenRecv(pCmdCtx, &openParmsList);
1648 if (RT_SUCCESS(rc))
1649 {
1650 PSHCLTRANSFER pTransfer = SharedClipboardTransferCtxGetTransfer(pTransferCtx,
1651 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->uContextID));
1652 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND);
1653
1654 LogFlowFunc(("pszPath=%s\n", openParmsList.pszPath));
1655
1656 SHCLLISTHANDLE hList = SHCLLISTHANDLE_INVALID;
1657 rc = SharedClipboardTransferListOpen(pTransfer, &openParmsList, &hList);
1658
1659 /* Reply in any case. */
1660 int rc2 = VbglR3ClipboardListOpenReply(pCmdCtx, rc, hList);
1661 AssertRC(rc2);
1662 }
1663
1664 SharedClipboardTransferListOpenParmsDestroy(&openParmsList);
1665 }
1666
1667 break;
1668 }
1669
1670 case VBOX_SHCL_HOST_MSG_TRANSFER_LIST_CLOSE:
1671 {
1672 SHCLLISTHANDLE hList;
1673 rc = VbglR3ClipboardListCloseRecv(pCmdCtx, &hList);
1674 if (RT_SUCCESS(rc))
1675 {
1676 PSHCLTRANSFER pTransfer = SharedClipboardTransferCtxGetTransfer(pTransferCtx,
1677 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->uContextID));
1678 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND);
1679
1680 rc = SharedClipboardTransferListClose(pTransfer, hList);
1681
1682 /* Reply in any case. */
1683 int rc2 = VbglR3ClipboardListCloseReply(pCmdCtx, rc, hList);
1684 AssertRC(rc2);
1685 }
1686
1687 break;
1688 }
1689
1690 case VBOX_SHCL_HOST_MSG_TRANSFER_LIST_HDR_READ:
1691 {
1692 /** @todo Handle filter + list features. */
1693
1694 SHCLLISTHANDLE hList = SHCLLISTHANDLE_INVALID;
1695 uint32_t fFlags = 0;
1696 rc = VbglR3ClipboardListHdrReadRecvReq(pCmdCtx, &hList, &fFlags);
1697 if (RT_SUCCESS(rc))
1698 {
1699 PSHCLTRANSFER pTransfer = SharedClipboardTransferCtxGetTransfer(pTransferCtx,
1700 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->uContextID));
1701 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND);
1702
1703 SHCLLISTHDR hdrList;
1704 rc = SharedClipboardTransferListGetHeader(pTransfer, hList, &hdrList);
1705 if (RT_SUCCESS(rc))
1706 {
1707 rc = VbglR3ClipboardListHdrWrite(pCmdCtx, hList, &hdrList);
1708
1709 SharedClipboardTransferListHdrDestroy(&hdrList);
1710 }
1711 }
1712
1713 break;
1714 }
1715
1716 case VBOX_SHCL_HOST_MSG_TRANSFER_LIST_ENTRY_READ:
1717 {
1718 LogFlowFunc(("VBOX_SHCL_HOST_MSG_TRANSFER_LIST_ENTRY_READ\n"));
1719
1720 SHCLLISTENTRY entryList;
1721 rc = SharedClipboardTransferListEntryInit(&entryList);
1722 if (RT_SUCCESS(rc))
1723 {
1724 SHCLLISTHANDLE hList;
1725 uint32_t fInfo;
1726 rc = VbglR3ClipboardListEntryReadRecvReq(pCmdCtx, &hList, &fInfo);
1727 if (RT_SUCCESS(rc))
1728 {
1729 PSHCLTRANSFER pTransfer = SharedClipboardTransferCtxGetTransfer(pTransferCtx,
1730 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->uContextID));
1731 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND);
1732
1733 rc = SharedClipboardTransferListRead(pTransfer, hList, &entryList);
1734 if (RT_SUCCESS(rc))
1735 {
1736 PSHCLFSOBJINFO pObjInfo = (PSHCLFSOBJINFO)entryList.pvInfo;
1737 Assert(entryList.cbInfo == sizeof(SHCLFSOBJINFO));
1738
1739 RT_NOREF(pObjInfo);
1740
1741 LogFlowFunc(("\t%s (%RU64 bytes)\n", entryList.pszName, pObjInfo->cbObject));
1742
1743 rc = VbglR3ClipboardListEntryWrite(pCmdCtx, hList, &entryList);
1744 }
1745 }
1746
1747 SharedClipboardTransferListEntryDestroy(&entryList);
1748 }
1749
1750 break;
1751 }
1752
1753 case VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_OPEN:
1754 {
1755 SHCLOBJOPENCREATEPARMS openParms;
1756 rc = SharedClipboardTransferObjectOpenParmsInit(&openParms);
1757 if (RT_SUCCESS(rc))
1758 {
1759 rc = VbglR3ClipboardObjOpenRecv(pCmdCtx, &openParms);
1760 if (RT_SUCCESS(rc))
1761 {
1762 PSHCLTRANSFER pTransfer = SharedClipboardTransferCtxGetTransfer(pTransferCtx,
1763 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->uContextID));
1764 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND);
1765
1766 SHCLOBJHANDLE hObj;
1767 rc = SharedClipboardTransferObjectOpen(pTransfer, &openParms, &hObj);
1768
1769 /* Reply in any case. */
1770 int rc2 = VbglR3ClipboardObjOpenReply(pCmdCtx, rc, hObj);
1771 AssertRC(rc2);
1772 }
1773
1774 SharedClipboardTransferObjectOpenParmsDestroy(&openParms);
1775 }
1776
1777 break;
1778 }
1779
1780 case VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_CLOSE:
1781 {
1782 SHCLOBJHANDLE hObj;
1783 rc = VbglR3ClipboardObjCloseRecv(pCmdCtx, &hObj);
1784 if (RT_SUCCESS(rc))
1785 {
1786 PSHCLTRANSFER pTransfer = SharedClipboardTransferCtxGetTransfer(pTransferCtx,
1787 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->uContextID));
1788 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND);
1789
1790 rc = SharedClipboardTransferObjectClose(pTransfer, hObj);
1791
1792 /* Reply in any case. */
1793 int rc2 = VbglR3ClipboardObjCloseReply(pCmdCtx, rc, hObj);
1794 AssertRC(rc2);
1795 }
1796
1797 break;
1798 }
1799
1800 case VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_READ:
1801 {
1802 SHCLOBJHANDLE hObj;
1803 uint32_t cbBuf;
1804 uint32_t fFlags;
1805 rc = VbglR3ClipboardObjReadRecv(pCmdCtx, &hObj, &cbBuf, &fFlags);
1806 if (RT_SUCCESS(rc))
1807 {
1808 PSHCLTRANSFER pTransfer = SharedClipboardTransferCtxGetTransfer(pTransferCtx,
1809 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->uContextID));
1810 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND);
1811
1812 AssertBreakStmt(pCmdCtx->cbChunkSize, rc = VERR_INVALID_PARAMETER);
1813
1814 const uint32_t cbToRead = RT_MIN(cbBuf, pCmdCtx->cbChunkSize);
1815
1816 LogFlowFunc(("hObj=%RU64, cbBuf=%RU32, fFlags=0x%x -> cbChunkSize=%RU32, cbToRead=%RU32\n",
1817 hObj, cbBuf, fFlags, pCmdCtx->cbChunkSize, cbToRead));
1818
1819 void *pvBuf = RTMemAlloc(cbToRead);
1820 if (pvBuf)
1821 {
1822 uint32_t cbRead;
1823 rc = SharedClipboardTransferObjectRead(pTransfer, hObj, pvBuf, cbToRead, &cbRead, fFlags);
1824 if (RT_SUCCESS(rc))
1825 rc = VbglR3ClipboardObjWriteSend(pCmdCtx, hObj, pvBuf, cbRead, NULL /* pcbWritten */);
1826
1827 RTMemFree(pvBuf);
1828 }
1829 else
1830 rc = VERR_NO_MEMORY;
1831 }
1832
1833 break;
1834 }
1835
1836 default:
1837 {
1838 rc = VbglR3ClipboardEventGetNext(idMsg, cParms, pCmdCtx, pEvent);
1839 break;
1840 }
1841 }
1842
1843 LogFlowFuncLeaveRC(rc);
1844 return rc;
1845}
1846#endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
1847
1848VBGLR3DECL(int) VbglR3ClipboardEventGetNext(uint32_t idMsg, uint32_t cParms,
1849 PVBGLR3SHCLCMDCTX pCtx, PVBGLR3CLIPBOARDEVENT pEvent)
1850{
1851 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1852 AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
1853
1854 RT_NOREF(cParms);
1855
1856 int rc;
1857
1858#ifdef LOG_ENABLED
1859 LogFunc(("Handling idMsg=%RU32 (%s), protocol v%RU32\n", idMsg, VBoxShClHostMsgToStr(idMsg), pCtx->uProtocolVer));
1860#endif
1861 switch (idMsg)
1862 {
1863 case VBOX_SHCL_HOST_MSG_FORMATS_REPORT:
1864 {
1865 rc = VbglR3ClipboardFormatsReportRecv(pCtx, &pEvent->u.ReportedFormats);
1866 if (RT_SUCCESS(rc))
1867 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_REPORT_FORMATS;
1868 break;
1869 }
1870
1871 case VBOX_SHCL_HOST_MSG_READ_DATA:
1872 {
1873 rc = VbglR3ClipboardReadDataRecv(pCtx, &pEvent->u.ReadData);
1874 if (RT_SUCCESS(rc))
1875 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_READ_DATA;
1876 break;
1877 }
1878
1879 default:
1880 {
1881 rc = VERR_NOT_SUPPORTED;
1882 break;
1883 }
1884 }
1885
1886 if (RT_SUCCESS(rc))
1887 {
1888 /* Copy over our command context to the event. */
1889 pEvent->cmdCtx = *pCtx;
1890 }
1891 else
1892 {
1893 /* Report error back to the host. */
1894 int rc2 = VbglR3ClipboardWriteError(pCtx->uClientID, rc);
1895 AssertRC(rc2);
1896
1897 }
1898
1899 LogFlowFuncLeaveRC(rc);
1900 return rc;
1901}
1902
1903/**
1904 * Frees (destroys) a formerly allocated Shared Clipboard event.
1905 *
1906 * @returns IPRT status code.
1907 * @param pEvent Event to free (destroy).
1908 */
1909VBGLR3DECL(void) VbglR3ClipboardEventFree(PVBGLR3CLIPBOARDEVENT pEvent)
1910{
1911 if (!pEvent)
1912 return;
1913
1914 /* Some messages require additional cleanup. */
1915 switch (pEvent->enmType)
1916 {
1917 default:
1918 break;
1919 }
1920
1921 RTMemFree(pEvent);
1922 pEvent = NULL;
1923}
1924
1925/**
1926 * Reports (advertises) guest clipboard formats to the host.
1927 *
1928 * @returns VBox status code.
1929 * @param pCtx The command context returned by VbglR3ClipboardConnectEx().
1930 * @param pFormats The formats to report.
1931 */
1932VBGLR3DECL(int) VbglR3ClipboardFormatsReportEx(PVBGLR3SHCLCMDCTX pCtx, PSHCLFORMATDATA pFormats)
1933{
1934 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1935 AssertPtrReturn(pFormats, VERR_INVALID_POINTER);
1936
1937 VBoxShClFormatsMsg Msg;
1938
1939 int rc;
1940
1941 LogFlowFunc(("uFormats=0x%x\n", pFormats->uFormats));
1942
1943 if (pCtx->uProtocolVer == 0)
1944 {
1945 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, VBOX_SHCL_GUEST_FN_FORMATS_REPORT, 1);
1946 Msg.u.v0.uFormats.SetUInt32(pFormats->uFormats);
1947
1948 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg.hdr) + sizeof(Msg.u.v0));
1949 }
1950 else
1951 {
1952 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, VBOX_SHCL_GUEST_FN_FORMATS_REPORT, 3);
1953
1954 Msg.u.v1.uContext.SetUInt32(pCtx->uContextID);
1955 Msg.u.v1.uFormats.SetUInt32(pFormats->uFormats);
1956 Msg.u.v1.fFlags.SetUInt32(pFormats->fFlags);
1957
1958 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg.hdr) + sizeof(Msg.u.v1));
1959 }
1960
1961 LogFlowFuncLeaveRC(rc);
1962 return rc;
1963}
1964
1965/**
1966 * Reports (advertises) guest clipboard formats to the host.
1967 *
1968 * Legacy function, do not use anymore.
1969 *
1970 * @returns VBox status code.
1971 * @param idClient The client id returned by VbglR3ClipboardConnect().
1972 * @param fFormats The formats to report.
1973 */
1974VBGLR3DECL(int) VbglR3ClipboardFormatsReport(HGCMCLIENTID idClient, uint32_t fFormats)
1975{
1976 AssertReturn(idClient, VERR_INVALID_PARAMETER);
1977 AssertReturn(fFormats, VERR_INVALID_PARAMETER);
1978
1979 VBoxShClFormatsMsg Msg;
1980
1981 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHCL_GUEST_FN_FORMATS_REPORT, 1);
1982 VbglHGCMParmUInt32Set(&Msg.u.v0.uFormats, fFormats);
1983
1984 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg.hdr) + sizeof(Msg.u.v0));
1985}
1986
1987/**
1988 * Sends guest clipboard data to the host. Legacy function kept for compatibility, do not use anymore.
1989 *
1990 * This is usually called in reply to a VBOX_SHCL_HOST_MSG_READ_DATA message
1991 * from the host.
1992 *
1993 * @returns VBox status code.
1994 * @param idClient The client id returned by VbglR3ClipboardConnect().
1995 * @param fFormat The format of the data.
1996 * @param pv The data.
1997 * @param cb The size of the data.
1998 */
1999VBGLR3DECL(int) VbglR3ClipboardWriteData(HGCMCLIENTID idClient, uint32_t fFormat, void *pv, uint32_t cb)
2000{
2001 AssertReturn (idClient, VERR_INVALID_PARAMETER);
2002 AssertPtrReturn(pv, VERR_INVALID_POINTER);
2003 AssertReturn (cb, VERR_INVALID_PARAMETER);
2004
2005 VBoxShClWriteDataMsg Msg;
2006 RT_ZERO(Msg);
2007
2008 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
2009 VBOX_SHCL_GUEST_FN_DATA_WRITE, 2);
2010
2011 VbglHGCMParmUInt32Set(&Msg.u.v0.format, fFormat);
2012 VbglHGCMParmPtrSet(&Msg.u.v0.ptr, pv, cb);
2013
2014 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg.hdr) + sizeof(Msg.u.v0));
2015
2016 LogFlowFuncLeaveRC(rc);
2017 return rc;
2018}
2019
2020/**
2021 * Sends guest clipboard data to the host.
2022 *
2023 * This is usually called in reply to a VBOX_SHCL_HOST_MSG_READ_DATA message
2024 * from the host.
2025 *
2026 * @returns VBox status code.
2027 * @param pCtx The command context returned by VbglR3ClipboardConnectEx().
2028 * @param pData Clipboard data to send.
2029 */
2030VBGLR3DECL(int) VbglR3ClipboardWriteDataEx(PVBGLR3SHCLCMDCTX pCtx, PSHCLDATABLOCK pData)
2031{
2032 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2033 AssertPtrReturn(pData, VERR_INVALID_POINTER);
2034
2035 int rc;
2036
2037 if (pCtx->uProtocolVer == 0)
2038 {
2039 rc = VbglR3ClipboardWriteData(pCtx->uClientID, pData->uFormat, pData->pvData, pData->cbData);
2040 }
2041 else
2042 {
2043 VBoxShClWriteDataMsg Msg;
2044 RT_ZERO(Msg);
2045
2046 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID,
2047 VBOX_SHCL_GUEST_FN_DATA_WRITE, VBOX_SHCL_CPARMS_WRITE_DATA);
2048
2049 LogFlowFunc(("CID=%RU32\n", pCtx->uContextID));
2050
2051 Msg.u.v1.uContext.SetUInt32(pCtx->uContextID);
2052 Msg.u.v1.uFormat.SetUInt32(pData->uFormat);
2053 Msg.u.v1.cbData.SetUInt32(pData->cbData);
2054 Msg.u.v1.pvData.SetPtr(pData->pvData, pData->cbData);
2055
2056 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
2057 }
2058
2059 LogFlowFuncLeaveRC(rc);
2060 return rc;
2061}
2062
2063/**
2064 * Writes an error to the host.
2065 *
2066 * @returns IPRT status code.
2067 * @param idClient The client id returned by VbglR3ClipboardConnect().
2068 * @param rcErr Error (IPRT-style) to send.
2069 */
2070VBGLR3DECL(int) VbglR3ClipboardWriteError(HGCMCLIENTID idClient, int rcErr)
2071{
2072 AssertReturn(idClient, VERR_INVALID_PARAMETER);
2073
2074 VBoxShClWriteErrorMsg Msg;
2075 RT_ZERO(Msg);
2076
2077 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHCL_GUEST_FN_ERROR, VBOX_SHCL_CPARMS_ERROR);
2078
2079 /** @todo Context ID not used yet. */
2080 Msg.uContext.SetUInt32(0);
2081 Msg.rc.SetUInt32((uint32_t)rcErr); /* uint32_t vs. int. */
2082
2083 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
2084
2085 if (RT_FAILURE(rc))
2086 LogFlowFunc(("Sending error %Rrc failed with rc=%Rrc\n", rcErr, rc));
2087 if (rc == VERR_NOT_SUPPORTED)
2088 rc = VINF_SUCCESS;
2089
2090 if (RT_FAILURE(rc))
2091 LogRel(("Shared Clipboard: Reporting error %Rrc to the host failed with %Rrc\n", rcErr, rc));
2092
2093 LogFlowFuncLeaveRC(rc);
2094 return rc;
2095}
2096
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