VirtualBox

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

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

Shared Clipboard/Transfers: Removed some superfluous HGCM parameters. Untested.

  • Property svn:eol-style set to native
  • Property svn:keyword set to Id
  • Property svn:keywords set to Author Date Id Revision
File size: 89.7 KB
Line 
1/* $Id: VBoxGuestR3LibClipboard.cpp 84996 2020-06-29 16:21:34Z vboxsync $ */
2/** @file
3 * VBoxGuestR3Lib - Ring-3 Support Library for VirtualBox guest additions, Shared Clipboard.
4 */
5
6/*
7 * Copyright (C) 2007-2020 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#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 (RT_FAILURE(rc))
75 {
76 if (rc == VERR_HGCM_SERVICE_NOT_FOUND)
77 LogRel(("Shared Clipboard: Unabled to connect, as host service was not found, skipping\n"));
78 else
79 LogRel(("Shared Clipboard: Unabled to connect to host service, rc=%Rrc\n", rc));
80 }
81 LogFlowFuncLeaveRC(rc);
82 return rc;
83}
84
85
86/**
87 * Connects to the Shared Clipboard service, extended version.
88 *
89 * @returns VBox status code.
90 * @param pCtx Command context. This will be initialized by this
91 * call.
92 * @param fGuestFeatures The guest features supported by this client,
93 * VBOX_SHCL_GF_0_XXX.
94 */
95VBGLR3DECL(int) VbglR3ClipboardConnectEx(PVBGLR3SHCLCMDCTX pCtx, uint64_t fGuestFeatures)
96{
97 /*
98 * Intialize the context structure.
99 */
100 pCtx->idClient = 0;
101 pCtx->fHostFeatures = 0;
102 pCtx->fGuestFeatures = 0;
103 pCtx->fUseLegacyProtocol = true;
104 pCtx->cParmsRecived = 0;
105 pCtx->idContext = 0;
106
107#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
108 pCtx->fGuestFeatures |= VBOX_SHCL_GF_0_TRANSFERS;
109 pCtx->cbChunkSize = VBOX_SHCL_DEFAULT_CHUNK_SIZE; /** @todo Make this configurable. */
110 pCtx->cbMaxChunkSize = VBOX_SHCL_MAX_CHUNK_SIZE; /** @todo Ditto. */
111#endif
112
113 /*
114 * First step is connecting to the HGCM service.
115 */
116 int rc = VbglR3ClipboardConnect(&pCtx->idClient);
117 if (RT_SUCCESS(rc))
118 {
119 /*
120 * Next is reporting our features. If this fails, assume older host.
121 */
122 rc = VbglR3ClipboardReportFeatures(pCtx->idClient, fGuestFeatures, &pCtx->fHostFeatures);
123 if (RT_SUCCESS(rc))
124 {
125 pCtx->fGuestFeatures = fGuestFeatures;
126
127 LogRel2(("Shared Clipboard: Guest features: %#RX64 - Host features: %#RX64\n",
128 pCtx->fGuestFeatures, pCtx->fHostFeatures));
129
130 if ( (pCtx->fHostFeatures & VBOX_SHCL_HF_0_CONTEXT_ID)
131 && (pCtx->fGuestFeatures & VBOX_SHCL_GF_0_CONTEXT_ID) )
132 {
133 pCtx->fUseLegacyProtocol = false;
134
135#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
136 if ( (pCtx->fHostFeatures & VBOX_SHCL_HF_0_TRANSFERS)
137 && (pCtx->fGuestFeatures & VBOX_SHCL_GF_0_TRANSFERS) )
138 {
139 VBoxShClParmNegotiateChunkSize MsgChunkSize;
140 do
141 {
142 VBGL_HGCM_HDR_INIT(&MsgChunkSize.hdr, pCtx->idClient, VBOX_SHCL_GUEST_FN_NEGOTIATE_CHUNK_SIZE,
143 VBOX_SHCL_CPARMS_NEGOTIATE_CHUNK_SIZE);
144 MsgChunkSize.cb32MaxChunkSize.SetUInt32(pCtx->cbMaxChunkSize);
145 MsgChunkSize.cb32ChunkSize.SetUInt32(0); /* If set to 0, let the host choose. */
146 rc = VbglR3HGCMCall(&MsgChunkSize.hdr, sizeof(MsgChunkSize));
147 } while (rc == VERR_INTERRUPTED);
148 if (RT_SUCCESS(rc))
149 {
150 Assert(MsgChunkSize.cb32ChunkSize.type == VMMDevHGCMParmType_32bit);
151 pCtx->cbChunkSize = RT_MIN(MsgChunkSize.cb32ChunkSize.u.value32, pCtx->cbChunkSize);
152 Assert(MsgChunkSize.cb32MaxChunkSize.type == VMMDevHGCMParmType_32bit);
153 pCtx->cbMaxChunkSize = RT_MIN(MsgChunkSize.cb32MaxChunkSize.u.value32, pCtx->cbMaxChunkSize);
154
155 LogRel2(("Shared Clipboard: Using chunk size %RU32 (maximum is %RU32)\n",
156 pCtx->cbChunkSize, pCtx->cbMaxChunkSize));
157 }
158 }
159 else
160 {
161 if (!(pCtx->fHostFeatures & VBOX_SHCL_HF_0_TRANSFERS))
162 LogRel2(("Shared Clipboard: Host does not support transfers\n"));
163 }
164#endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
165 }
166 else
167 {
168 if (!(pCtx->fHostFeatures & VBOX_SHCL_HF_0_CONTEXT_ID))
169 LogRel(("Shared Clipboard: Host does not support context IDs, using legacy protocol\n"));
170
171 pCtx->fUseLegacyProtocol = true;
172 }
173 }
174 else
175 {
176 AssertLogRelMsg(rc == VERR_NOT_SUPPORTED || rc == VERR_NOT_IMPLEMENTED,
177 ("Reporting features failed: %Rrc\n", rc));
178 pCtx->fUseLegacyProtocol = true;
179 }
180 }
181
182 LogFlowFuncLeaveRC(rc);
183 return rc;
184}
185
186
187/**
188 * Reports features to the host and retrieve host feature set.
189 *
190 * @returns VBox status code.
191 * @param idClient The client ID returned by VbglR3ClipboardConnect().
192 * @param fGuestFeatures Features to report, VBOX_SHCL_GF_XXX.
193 * @param pfHostFeatures Where to store the features VBOX_SHCL_HF_XXX.
194 */
195VBGLR3DECL(int) VbglR3ClipboardReportFeatures(uint32_t idClient, uint64_t fGuestFeatures, uint64_t *pfHostFeatures)
196{
197 int rc;
198 do
199 {
200 struct
201 {
202 VBGLIOCHGCMCALL Hdr;
203 HGCMFunctionParameter f64Features0;
204 HGCMFunctionParameter f64Features1;
205 } Msg;
206 VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, VBOX_SHCL_GUEST_FN_REPORT_FEATURES, 2);
207 VbglHGCMParmUInt64Set(&Msg.f64Features0, fGuestFeatures);
208 VbglHGCMParmUInt64Set(&Msg.f64Features1, VBOX_SHCL_GF_1_MUST_BE_ONE);
209
210 rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
211 if (RT_SUCCESS(rc))
212 {
213 Assert(Msg.f64Features0.type == VMMDevHGCMParmType_64bit);
214 Assert(Msg.f64Features1.type == VMMDevHGCMParmType_64bit);
215 if (Msg.f64Features1.u.value64 & VBOX_SHCL_GF_1_MUST_BE_ONE)
216 rc = VERR_NOT_SUPPORTED;
217 else if (pfHostFeatures)
218 *pfHostFeatures = Msg.f64Features0.u.value64;
219 break;
220 }
221 } while (rc == VERR_INTERRUPTED);
222 return rc;
223
224}
225
226
227/**
228 * Disconnects from the Shared Clipboard service, legacy version, do not use anymore.
229 *
230 * @returns VBox status code.
231 * @param idClient The client id returned by VbglR3ClipboardConnect().
232 */
233VBGLR3DECL(int) VbglR3ClipboardDisconnect(HGCMCLIENTID idClient)
234{
235 return VbglR3HGCMDisconnect(idClient);
236}
237
238
239/**
240 * Disconnects from the Shared Clipboard service, extended version.
241 *
242 * @returns VBox status code.
243 * @param pCtx Shared Clipboard command context to use for the connection.
244 */
245VBGLR3DECL(int) VbglR3ClipboardDisconnectEx(PVBGLR3SHCLCMDCTX pCtx)
246{
247 int rc = VbglR3ClipboardDisconnect(pCtx->idClient);
248 if (RT_SUCCESS(rc))
249 {
250 pCtx->idClient = 0;
251 }
252
253 LogFlowFuncLeaveRC(rc);
254 return rc;
255}
256
257
258/**
259 * Receives reported formats from the host.
260 *
261 * @returns VBox status code.
262 * @param pCtx Shared Clipboard command context to use for the
263 * connection.
264 * @param pfFormats Where to store the received formats from the host.
265 */
266static int vbglR3ClipboardFormatsReportRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLFORMATS pfFormats)
267{
268 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
269 AssertPtrReturn(pfFormats, VERR_INVALID_POINTER);
270
271 *pfFormats = 0;
272
273 struct
274 {
275 VBGLIOCHGCMCALL Hdr;
276 HGCMFunctionParameter id64Context;
277 HGCMFunctionParameter f32Formats;
278 } Msg;
279
280 VBGL_HGCM_HDR_INIT(&Msg.Hdr, pCtx->idClient, VBOX_SHCL_GUEST_FN_MSG_GET, 2);
281 Msg.id64Context.SetUInt32(VBOX_SHCL_HOST_MSG_FORMATS_REPORT);
282 Msg.f32Formats.SetUInt32(0);
283
284 int rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
285 if (RT_SUCCESS(rc))
286 {
287 rc = Msg.f32Formats.GetUInt32(pfFormats);
288 AssertRC(rc);
289 }
290
291 LogFlowFuncLeaveRC(rc);
292 return rc;
293}
294
295
296/**
297 * Fetches a VBOX_SHCL_HOST_MSG_READ_DATA_CID message.
298 *
299 * @returns VBox status code.
300 * @param pCtx Shared Clipboard command context to use for the connection.
301 * @param pfFormat Where to return the requested format.
302 */
303static int vbglR3ClipboardFetchReadDataCid(PVBGLR3SHCLCMDCTX pCtx, PSHCLFORMAT pfFormat)
304{
305 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
306 AssertPtrReturn(pfFormat, VERR_INVALID_POINTER);
307
308 struct
309 {
310 VBGLIOCHGCMCALL Hdr;
311 HGCMFunctionParameter id64Context;
312 HGCMFunctionParameter f32Format;
313 } Msg;
314
315 VBGL_HGCM_HDR_INIT(&Msg.Hdr, pCtx->idClient, VBOX_SHCL_GUEST_FN_MSG_GET, 2);
316 Msg.id64Context.SetUInt64(VBOX_SHCL_HOST_MSG_READ_DATA_CID);
317 Msg.f32Format.SetUInt32(0);
318
319 int rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
320 if (RT_SUCCESS(rc))
321 {
322 rc = Msg.id64Context.GetUInt64(&pCtx->idContext);
323 AssertRC(rc);
324 int rc2 = Msg.f32Format.GetUInt32(pfFormat);
325 AssertRCStmt(rc2, rc = rc2);
326 }
327
328 LogFlowFuncLeaveRC(rc);
329 return rc;
330}
331
332
333/**
334 * Fetches a VBOX_SHCL_HOST_MSG_READ_DATA message.
335 *
336 * @returns VBox status code.
337 * @param pCtx Shared Clipboard command context to use for the connection.
338 * @param pfFormat Where to return the requested format.
339 */
340static int vbglR3ClipboardFetchReadData(PVBGLR3SHCLCMDCTX pCtx, PSHCLFORMAT pfFormat)
341{
342 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
343 AssertPtrReturn(pfFormat, VERR_INVALID_POINTER);
344
345 struct
346 {
347 VBGLIOCHGCMCALL Hdr;
348 HGCMFunctionParameter id32Msg;
349 HGCMFunctionParameter f32Format;
350 } Msg;
351
352 VBGL_HGCM_HDR_INIT(&Msg.Hdr, pCtx->idClient, VBOX_SHCL_GUEST_FN_MSG_GET, 2);
353 Msg.id32Msg.SetUInt32(VBOX_SHCL_HOST_MSG_READ_DATA);
354 Msg.f32Format.SetUInt32(0);
355
356 int rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
357 if (RT_SUCCESS(rc))
358 {
359 rc = Msg.f32Format.GetUInt32(pfFormat);
360 AssertRC(rc);
361 }
362
363 LogFlowFuncLeaveRC(rc);
364 return rc;
365}
366
367
368/**
369 * Get a host message, legacy version (which does not have VBOX_SHCL_GUEST_FN_MSG_GET). Do not use anymore.
370 *
371 * Note: This is the old message which still is being used for the non-URI Shared Clipboard transfers,
372 * to not break compatibility with older additions / VBox versions.
373 *
374 * This will block until a message becomes available.
375 *
376 * @returns VBox status code.
377 * @param idClient The client id returned by VbglR3ClipboardConnect().
378 * @param pidMsg Where to store the message id.
379 * @param pfFormats Where to store the format(s) the message applies to.
380 */
381VBGLR3DECL(int) VbglR3ClipboardGetHostMsgOld(HGCMCLIENTID idClient, uint32_t *pidMsg, uint32_t *pfFormats)
382{
383 VBoxShClGetHostMsgOld Msg;
384
385 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT, VBOX_SHCL_CPARMS_GET_HOST_MSG_OLD);
386 VbglHGCMParmUInt32Set(&Msg.msg, 0);
387 VbglHGCMParmUInt32Set(&Msg.formats, 0);
388
389 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
390 if (RT_SUCCESS(rc))
391 {
392 int rc2 = VbglHGCMParmUInt32Get(&Msg.msg, pidMsg);
393 if (RT_SUCCESS(rc))
394 {
395 rc2 = VbglHGCMParmUInt32Get(&Msg.formats, pfFormats);
396 if (RT_SUCCESS(rc2))
397 return rc;
398 }
399 rc = rc2;
400 }
401 *pidMsg = UINT32_MAX - 1;
402 *pfFormats = UINT32_MAX;
403 return rc;
404}
405
406
407/**
408 * Reads data from the host clipboard.
409 *
410 * Legacy function, do not use anymore.
411 *
412 * @returns VBox status code.
413 * @retval VINF_BUFFER_OVERFLOW If there is more data available than the caller provided buffer space for.
414 *
415 * @param idClient The client id returned by VbglR3ClipboardConnect().
416 * @param fFormat The format we're requesting the data in.
417 * @param pvData Where to store the data.
418 * @param cbData The size of the buffer pointed to by \a pvData.
419 * @param pcbRead The actual size of the host clipboard data. May be larger than \a cbData.
420 */
421VBGLR3DECL(int) VbglR3ClipboardReadData(HGCMCLIENTID idClient, uint32_t fFormat, void *pvData, uint32_t cbData,
422 uint32_t *pcbRead)
423{
424 LogFlowFuncEnter();
425
426 struct
427 {
428 VBGLIOCHGCMCALL Hdr;
429 VBoxShClParmDataRead Parms;
430 } Msg;
431
432 VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, VBOX_SHCL_GUEST_FN_DATA_READ, VBOX_SHCL_CPARMS_DATA_READ);
433 VbglHGCMParmUInt32Set(&Msg.Parms.f32Format, fFormat);
434 VbglHGCMParmPtrSet( &Msg.Parms.pData, pvData, cbData);
435 VbglHGCMParmUInt32Set(&Msg.Parms.cb32Needed, 0);
436
437 int rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
438 if (RT_SUCCESS(rc))
439 {
440 uint32_t cbRead;
441 rc = VbglHGCMParmUInt32Get(&Msg.Parms.cb32Needed, &cbRead);
442 if (RT_SUCCESS(rc))
443 {
444 LogFlowFunc(("cbRead=%RU32\n", cbRead));
445
446 if (cbRead > cbData)
447 rc = VINF_BUFFER_OVERFLOW;
448
449 *pcbRead = cbRead;
450 }
451 }
452
453 LogFlowFuncLeaveRC(rc);
454 return rc;
455}
456
457
458/**
459 * Reads clipboard data from the host clipboard.
460 *
461 * @returns VBox status code.
462 * @retval VINF_BUFFER_OVERFLOW If there is more data available than the caller provided buffer space for.
463 *
464 * @param pCtx The command context returned by VbglR3ClipboardConnectEx().
465 * @param uFormat Clipboard format of clipboard data to be read.
466 * @param pvData Buffer where to store the read data.
467 * @param cbData Size (in bytes) of data buffer where to store the read data.
468 * @param pcbRead The actual size of the host clipboard data.
469 */
470VBGLR3DECL(int) VbglR3ClipboardReadDataEx(PVBGLR3SHCLCMDCTX pCtx,
471 SHCLFORMAT uFormat, void *pvData, uint32_t cbData, uint32_t *pcbRead)
472{
473 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
474 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
475 return VbglR3ClipboardReadData(pCtx->idClient, uFormat, pvData, cbData, pcbRead);
476}
477
478
479/**
480 * Query the host features.
481 *
482 * @returns VBox status code.
483 * @param idClient The client ID returned by VbglR3ClipboardConnect().
484 * @param pfHostFeatures Where to store the host feature, VBOX_SHCL_HF_XXX.
485 */
486VBGLR3DECL(int) VbglR3ClipboardQueryFeatures(uint32_t idClient, uint64_t *pfHostFeatures)
487{
488 int rc;
489 do
490 {
491 struct
492 {
493 VBGLIOCHGCMCALL Hdr;
494 HGCMFunctionParameter f64Features0;
495 HGCMFunctionParameter f64Features1;
496 } Msg;
497 VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, VBOX_SHCL_GUEST_FN_QUERY_FEATURES, 2);
498 VbglHGCMParmUInt64Set(&Msg.f64Features0, 0);
499 VbglHGCMParmUInt64Set(&Msg.f64Features1, RT_BIT_64(63));
500
501 rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
502 if (RT_SUCCESS(rc))
503 {
504 Assert(Msg.f64Features0.type == VMMDevHGCMParmType_64bit);
505 Assert(Msg.f64Features1.type == VMMDevHGCMParmType_64bit);
506 if (Msg.f64Features1.u.value64 & RT_BIT_64(63))
507 rc = VERR_NOT_SUPPORTED;
508 else if (pfHostFeatures)
509 *pfHostFeatures = Msg.f64Features0.u.value64;
510 break;
511 }
512 } while (rc == VERR_INTERRUPTED);
513 return rc;
514
515}
516
517/**
518 * Peeks at the next host message, waiting for one to turn up.
519 *
520 * This glosses over the difference between new (6.1) and old (1.3.2) host
521 * service versions, however it does so by abusing @a pcParameters, so don't use
522 * it directly when in legacy mode, always pass it on to
523 * VbglR3ClipboardEventGetNext() or VbglR3ClipboardEventGetNextEx().
524 *
525 * @returns VBox status code.
526 * @retval VERR_INTERRUPTED if interrupted. Does the necessary cleanup, so
527 * caller just have to repeat this call.
528 * @retval VERR_VM_RESTORED if the VM has been restored (idRestoreCheck).
529 *
530 * @param pCtx Shared Clipboard command context to use for the connection.
531 * @param pidMsg Where to store the message id.
532 * @param pcParameters Where to store the number of parameters which will
533 * be received in a second call to the host.
534 * @param pidRestoreCheck Pointer to the VbglR3GetSessionId() variable to use
535 * for the VM restore check. Optional.
536 *
537 * @note Restore check is only performed optimally with a 6.0 host.
538 */
539VBGLR3DECL(int) VbglR3ClipboardMsgPeekWait(PVBGLR3SHCLCMDCTX pCtx, uint32_t *pidMsg,
540 uint32_t *pcParameters, uint64_t *pidRestoreCheck)
541{
542 AssertPtrReturn(pidMsg, VERR_INVALID_POINTER);
543 AssertPtrReturn(pcParameters, VERR_INVALID_POINTER);
544
545 struct
546 {
547 VBGLIOCHGCMCALL Hdr;
548 HGCMFunctionParameter idMsg; /* Doubles as restore check on input. */
549 HGCMFunctionParameter cParameters;
550 } Msg;
551 int rc;
552 if (!pCtx->fUseLegacyProtocol)
553 {
554 VBGL_HGCM_HDR_INIT(&Msg.Hdr, pCtx->idClient, VBOX_SHCL_GUEST_FN_MSG_PEEK_WAIT, 2);
555 VbglHGCMParmUInt64Set(&Msg.idMsg, pidRestoreCheck ? *pidRestoreCheck : 0);
556 VbglHGCMParmUInt32Set(&Msg.cParameters, 0);
557 rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
558 LogFlowFunc(("VbglR3HGCMCall -> %Rrc\n", rc));
559 if (RT_SUCCESS(rc))
560 {
561 AssertMsgReturn( Msg.idMsg.type == VMMDevHGCMParmType_64bit
562 && Msg.cParameters.type == VMMDevHGCMParmType_32bit,
563 ("msg.type=%d num_parms.type=%d\n", Msg.idMsg.type, Msg.cParameters.type),
564 VERR_INTERNAL_ERROR_3);
565
566 *pidMsg = (uint32_t)Msg.idMsg.u.value64;
567 *pcParameters = Msg.cParameters.u.value32;
568 return rc;
569 }
570
571 /*
572 * If restored, update pidRestoreCheck.
573 */
574 if (rc == VERR_VM_RESTORED && pidRestoreCheck)
575 *pidRestoreCheck = Msg.idMsg.u.value64;
576 }
577 else
578 {
579 /*
580 * We do some crude stuff here by putting the 2nd parameter (foramts) in the parameter count,
581 * however it's supposed to be passed directly to VbglR3ClipboardEventGetNext or
582 * VbglR3ClipboardEventGetNextEx, so that's fine...
583 */
584 rc = VbglR3ClipboardGetHostMsgOld(pCtx->idClient, pidMsg, pcParameters);
585 if (RT_SUCCESS(rc))
586 return rc;
587 }
588
589 /*
590 * If interrupted we must cancel the call so it doesn't prevent us from making another one.
591 */
592 if (rc == VERR_INTERRUPTED)
593 {
594 VBGL_HGCM_HDR_INIT(&Msg.Hdr, pCtx->idClient, VBOX_SHCL_GUEST_FN_MSG_CANCEL, 0);
595 int rc2 = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg.Hdr));
596 AssertRC(rc2);
597 }
598
599 *pidMsg = UINT32_MAX - 1;
600 *pcParameters = UINT32_MAX - 2;
601 return rc;
602}
603
604#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
605
606/**
607 * Reads a root list header from the host.
608 *
609 * @returns VBox status code.
610 * @param pCtx Shared Clipboard command context to use for the connection.
611 * @param pRootListHdr Where to store the received root list header.
612 */
613static int vbglR3ClipboardRootListHdrRead(PVBGLR3SHCLCMDCTX pCtx, PSHCLROOTLISTHDR pRootListHdr)
614{
615 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
616 AssertPtrReturn(pRootListHdr, VERR_INVALID_POINTER);
617
618 VBoxShClRootListHdrMsg Msg;
619 RT_ZERO(Msg);
620
621 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
622 VBOX_SHCL_GUEST_FN_ROOT_LIST_HDR_READ, VBOX_SHCL_CPARMS_ROOT_LIST_HDR_READ);
623
624 Msg.ReqParms.uContext.SetUInt64(pCtx->idContext);
625 Msg.ReqParms.fRoots.SetUInt32(0);
626
627 Msg.cRoots.SetUInt32(0);
628
629 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
630 if (RT_SUCCESS(rc))
631 {
632 rc = Msg.ReqParms.fRoots.GetUInt32(&pRootListHdr->fRoots); AssertRC(rc);
633 if (RT_SUCCESS(rc))
634 rc = Msg.cRoots.GetUInt32(&pRootListHdr->cRoots); AssertRC(rc);
635 }
636
637 LogFlowFuncLeaveRC(rc);
638 return rc;
639}
640
641/**
642 * Reads a root list entry from the host.
643 *
644 * @returns VBox status code.
645 * @param pCtx Shared Clipboard command context to use for the connection.
646 * @param uIndex Index of root list entry to read.
647 * @param pRootListEntry Where to store the root list entry read from the host.
648 */
649static int vbglR3ClipboardRootListEntryRead(PVBGLR3SHCLCMDCTX pCtx, uint32_t uIndex, PSHCLROOTLISTENTRY pRootListEntry)
650{
651 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
652 AssertPtrReturn(pRootListEntry, VERR_INVALID_POINTER);
653
654 VBoxShClRootListEntryMsg Msg;
655 RT_ZERO(Msg);
656
657 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
658 VBOX_SHCL_GUEST_FN_ROOT_LIST_ENTRY_READ, VBOX_SHCL_CPARMS_ROOT_LIST_ENTRY_READ);
659
660 Msg.Parms.uContext.SetUInt64(pCtx->idContext);
661 Msg.Parms.fInfo.SetUInt32(pRootListEntry->fInfo);
662 Msg.Parms.uIndex.SetUInt32(uIndex);
663
664 Msg.szName.SetPtr(pRootListEntry->pszName, pRootListEntry->cbName);
665 Msg.cbInfo.SetUInt32(pRootListEntry->cbInfo);
666 Msg.pvInfo.SetPtr(pRootListEntry->pvInfo, pRootListEntry->cbInfo);
667
668 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
669 if (RT_SUCCESS(rc))
670 {
671 rc = Msg.Parms.fInfo.GetUInt32(&pRootListEntry->fInfo); AssertRC(rc);
672 if (RT_SUCCESS(rc))
673 {
674 uint32_t cbInfo = 0;
675 rc = Msg.cbInfo.GetUInt32(&cbInfo); AssertRC(rc);
676 if (pRootListEntry->cbInfo != cbInfo)
677 rc = VERR_INVALID_PARAMETER;
678 }
679 }
680
681 LogFlowFuncLeaveRC(rc);
682 return rc;
683}
684
685/**
686 * Reads the root list from the host.
687 *
688 * @returns VBox status code.
689 * @param pCtx Shared Clipboard command context to use for the connection.
690 * @param ppRootList Where to store the (allocated) root list. Must be free'd by the caller with
691 * SharedClipboardTransferRootListFree().
692 */
693VBGLR3DECL(int) VbglR3ClipboardRootListRead(PVBGLR3SHCLCMDCTX pCtx, PSHCLROOTLIST *ppRootList)
694{
695 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
696 AssertPtrReturn(ppRootList, VERR_INVALID_POINTER);
697
698 int rc;
699
700 PSHCLROOTLIST pRootList = ShClTransferRootListAlloc();
701 if (pRootList)
702 {
703 SHCLROOTLISTHDR srcRootListHdr;
704 rc = vbglR3ClipboardRootListHdrRead(pCtx, &srcRootListHdr);
705 if (RT_SUCCESS(rc))
706 {
707 pRootList->Hdr.cRoots = srcRootListHdr.cRoots;
708 pRootList->Hdr.fRoots = 0; /** @todo Implement this. */
709
710 if (srcRootListHdr.cRoots)
711 {
712 pRootList->paEntries =
713 (PSHCLROOTLISTENTRY)RTMemAllocZ(srcRootListHdr.cRoots * sizeof(SHCLROOTLISTENTRY));
714 if (pRootList->paEntries)
715 {
716 for (uint32_t i = 0; i < srcRootListHdr.cRoots; i++)
717 {
718 SHCLROOTLISTENTRY *pEntry = &pRootList->paEntries[i];
719 AssertPtr(pEntry);
720
721 rc = ShClTransferRootListEntryInit(pEntry);
722 if (RT_SUCCESS(rc))
723 rc = vbglR3ClipboardRootListEntryRead(pCtx, i, pEntry);
724
725 if (RT_FAILURE(rc))
726 break;
727 }
728 }
729 else
730 rc = VERR_NO_MEMORY;
731 }
732 }
733
734 if (RT_SUCCESS(rc))
735 {
736 *ppRootList = pRootList;
737 }
738 else
739 ShClTransferRootListFree(pRootList);
740 }
741 else
742 rc = VERR_NO_MEMORY;
743
744 LogFlowFuncLeaveRC(rc);
745 return rc;
746}
747
748/**
749 * Receives a transfer status from the host.
750 *
751 * @returns VBox status code.
752 * @param pCtx Shared Clipboard command context to use for the connection.
753 * @param pEnmDir Where to store the transfer direction for the reported transfer.
754 * @param pReport Where to store the transfer (status) report.
755 */
756VBGLR3DECL(int) VbglR3ClipboarTransferStatusRecv(PVBGLR3SHCLCMDCTX pCtx,
757 PSHCLTRANSFERDIR pEnmDir, PSHCLTRANSFERREPORT pReport)
758{
759 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
760 AssertPtrReturn(pReport, VERR_INVALID_POINTER);
761 AssertPtrReturn(pEnmDir, VERR_INVALID_POINTER);
762
763 VBoxShClTransferStatusMsg Msg;
764 RT_ZERO(Msg);
765
766 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
767 VBOX_SHCL_GUEST_FN_MSG_GET, VBOX_SHCL_CPARMS_TRANSFER_STATUS);
768
769 Msg.uContext.SetUInt64(VBOX_SHCL_HOST_MSG_TRANSFER_STATUS);
770 Msg.enmDir.SetUInt32(0);
771 Msg.enmStatus.SetUInt32(0);
772 Msg.rc.SetUInt32(0);
773 Msg.fFlags.SetUInt32(0);
774
775 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
776 if (RT_SUCCESS(rc))
777 {
778 rc = Msg.uContext.GetUInt64(&pCtx->idContext); AssertRC(rc);
779 if (RT_SUCCESS(rc))
780 rc = Msg.enmDir.GetUInt32((uint32_t *)pEnmDir); AssertRC(rc);
781 if (RT_SUCCESS(rc))
782 rc = Msg.enmStatus.GetUInt32(&pReport->uStatus); AssertRC(rc);
783 if (RT_SUCCESS(rc))
784 rc = Msg.rc.GetUInt32((uint32_t *)&pReport->rc); AssertRC(rc);
785 if (RT_SUCCESS(rc))
786 rc = Msg.fFlags.GetUInt32(&pReport->fFlags); AssertRC(rc);
787 }
788
789 LogFlowFuncLeaveRC(rc);
790 return rc;
791}
792
793/**
794 * Replies to a transfer report from the host.
795 *
796 * @returns VBox status code.
797 * @param pCtx Shared Clipboard command context to use for the connection.
798 * @param pTransfer Transfer of report to reply to.
799 * @param uStatus Tranfer status to reply.
800 * @param rcTransfer Result code (rc) to reply.
801 */
802VBGLR3DECL(int) VbglR3ClipboardTransferStatusReply(PVBGLR3SHCLCMDCTX pCtx, PSHCLTRANSFER pTransfer,
803 SHCLTRANSFERSTATUS uStatus, int rcTransfer)
804{
805 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
806 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
807
808 RT_NOREF(pTransfer);
809
810 VBoxShClReplyMsg Msg;
811 RT_ZERO(Msg);
812
813 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
814 VBOX_SHCL_GUEST_FN_REPLY, VBOX_SHCL_CPARMS_REPLY_MIN + 1);
815
816 Msg.uContext.SetUInt64(pCtx->idContext);
817 Msg.enmType.SetUInt32(VBOX_SHCL_REPLYMSGTYPE_TRANSFER_STATUS);
818 Msg.rc.SetUInt32((uint32_t )rcTransfer); /* int vs. uint32_t */
819 Msg.pvPayload.SetPtr(NULL, 0);
820
821 Msg.u.TransferStatus.enmStatus.SetUInt32((uint32_t)uStatus);
822
823 LogFlowFunc(("%s\n", ShClTransferStatusToStr(uStatus)));
824
825 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
826
827 LogFlowFuncLeaveRC(rc);
828 return rc;
829}
830
831/**
832 * Receives a host request to read a root list header from the guest.
833 *
834 * @returns VBox status code.
835 * @param pCtx Shared Clipboard command context to use for the connection.
836 * @param pfRoots Where to store the root list header flags to use, requested by the host.
837 */
838VBGLR3DECL(int) VbglR3ClipboardRootListHdrReadReq(PVBGLR3SHCLCMDCTX pCtx, uint32_t *pfRoots)
839{
840 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
841 AssertPtrReturn(pfRoots, VERR_INVALID_POINTER);
842
843 VBoxShClRootListReadReqMsg Msg;
844 RT_ZERO(Msg);
845
846 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
847 VBOX_SHCL_GUEST_FN_MSG_GET, VBOX_SHCL_CPARMS_ROOT_LIST_HDR_READ_REQ);
848
849 Msg.ReqParms.uContext.SetUInt64(VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_HDR_READ);
850 Msg.ReqParms.fRoots.SetUInt32(0);
851
852 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
853 if (RT_SUCCESS(rc))
854 {
855 rc = Msg.ReqParms.uContext.GetUInt64(&pCtx->idContext); AssertRC(rc);
856 if (RT_SUCCESS(rc))
857 rc = Msg.ReqParms.fRoots.GetUInt32(pfRoots); AssertRC(rc);
858 }
859
860 LogFlowFuncLeaveRC(rc);
861 return rc;
862}
863
864/**
865 * Replies to a root list header request.
866 *
867 * @returns VBox status code.
868 * @param pCtx Shared Clipboard command context to use for the connection.
869 * @param pRootListHdr Root lsit header to reply to the host.
870 */
871VBGLR3DECL(int) VbglR3ClipboardRootListHdrReadReply(PVBGLR3SHCLCMDCTX pCtx, PSHCLROOTLISTHDR pRootListHdr)
872{
873 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
874 AssertPtrReturn(pRootListHdr, VERR_INVALID_POINTER);
875
876 VBoxShClRootListHdrMsg Msg;
877 RT_ZERO(Msg);
878
879 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
880 VBOX_SHCL_GUEST_FN_ROOT_LIST_HDR_WRITE, VBOX_SHCL_CPARMS_ROOT_LIST_HDR_WRITE);
881
882 Msg.ReqParms.uContext.SetUInt64(pCtx->idContext);
883 Msg.ReqParms.fRoots.SetUInt32(pRootListHdr->fRoots);
884
885 Msg.cRoots.SetUInt32(pRootListHdr->cRoots);
886
887 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
888
889 LogFlowFuncLeaveRC(rc);
890 return rc;
891}
892
893/**
894 * Receives a host request to read a root list entry from the guest.
895 *
896 * @returns VBox status code.
897 * @param pCtx Shared Clipboard command context to use for the connection.
898 * @param puIndex Where to return the index of the root list entry the host wants to read.
899 * @param pfInfo Where to return the read flags the host wants to use.
900 */
901VBGLR3DECL(int) VbglR3ClipboardRootListEntryReadReq(PVBGLR3SHCLCMDCTX pCtx, uint32_t *puIndex, uint32_t *pfInfo)
902{
903 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
904 AssertPtrReturn(puIndex, VERR_INVALID_POINTER);
905 AssertPtrReturn(pfInfo, VERR_INVALID_POINTER);
906
907 VBoxShClRootListEntryReadReqMsg Msg;
908 RT_ZERO(Msg);
909
910 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
911 VBOX_SHCL_GUEST_FN_MSG_GET, VBOX_SHCL_CPARMS_ROOT_LIST_ENTRY_READ_REQ);
912
913 Msg.Parms.uContext.SetUInt64(VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_ENTRY_READ);
914 Msg.Parms.fInfo.SetUInt32(0);
915 Msg.Parms.uIndex.SetUInt32(0);
916
917 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
918 if (RT_SUCCESS(rc))
919 {
920 rc = Msg.Parms.uContext.GetUInt64(&pCtx->idContext); AssertRC(rc);
921 if (RT_SUCCESS(rc))
922 rc = Msg.Parms.fInfo.GetUInt32(pfInfo); AssertRC(rc);
923 if (RT_SUCCESS(rc))
924 rc = Msg.Parms.uIndex.GetUInt32(puIndex); AssertRC(rc);
925 }
926
927 LogFlowFuncLeaveRC(rc);
928 return rc;
929}
930
931/**
932 * Replies to a root list entry read request from the host.
933 *
934 * @returns VBox status code.
935 * @param pCtx Shared Clipboard command context to use for the connection.
936 * @param uIndex Index of root list entry to reply.
937 * @param pEntry Actual root list entry to reply.
938 */
939VBGLR3DECL(int) VbglR3ClipboardRootListEntryReadReply(PVBGLR3SHCLCMDCTX pCtx, uint32_t uIndex, PSHCLROOTLISTENTRY pEntry)
940{
941 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
942 AssertPtrReturn(pEntry, VERR_INVALID_POINTER);
943
944 VBoxShClRootListEntryMsg Msg;
945 RT_ZERO(Msg);
946
947 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
948 VBOX_SHCL_GUEST_FN_ROOT_LIST_ENTRY_WRITE, VBOX_SHCL_CPARMS_ROOT_LIST_ENTRY_WRITE);
949
950 Msg.Parms.uContext.SetUInt64(pCtx->idContext);
951 Msg.Parms.fInfo.SetUInt32(0);
952 Msg.Parms.uIndex.SetUInt32(uIndex);
953
954 Msg.szName.SetPtr(pEntry->pszName, pEntry->cbName);
955 Msg.cbInfo.SetUInt32(pEntry->cbInfo);
956 Msg.pvInfo.SetPtr(pEntry->pvInfo, pEntry->cbInfo);
957
958 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
959
960 LogFlowFuncLeaveRC(rc);
961 return rc;
962}
963
964/**
965 * Sends a request to open a list handle to the host.
966 *
967 * @returns VBox status code.
968 * @param pCtx Shared Clipboard command context to use for the connection.
969 * @param pOpenParms List open parameters to use for the open request.
970 * @param phList Where to return the list handle received from the host.
971 */
972VBGLR3DECL(int) VbglR3ClipboardListOpenSend(PVBGLR3SHCLCMDCTX pCtx, PSHCLLISTOPENPARMS pOpenParms,
973 PSHCLLISTHANDLE phList)
974{
975 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
976 AssertPtrReturn(pOpenParms, VERR_INVALID_POINTER);
977 AssertPtrReturn(phList, VERR_INVALID_POINTER);
978
979 VBoxShClListOpenMsg Msg;
980 RT_ZERO(Msg);
981
982 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
983 VBOX_SHCL_GUEST_FN_LIST_OPEN, VBOX_SHCL_CPARMS_LIST_OPEN);
984
985 Msg.uContext.SetUInt64(pCtx->idContext);
986 Msg.fList.SetUInt32(0);
987 Msg.pvFilter.SetPtr(pOpenParms->pszFilter, pOpenParms->cbFilter);
988 Msg.pvPath.SetPtr(pOpenParms->pszPath, pOpenParms->cbPath);
989 Msg.uHandle.SetUInt64(0);
990
991 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
992 if (RT_SUCCESS(rc))
993 {
994 rc = Msg.uHandle.GetUInt64(phList); AssertRC(rc);
995 }
996
997 LogFlowFuncLeaveRC(rc);
998 return rc;
999}
1000
1001/**
1002 * Receives a host request to open a list handle on the guest.
1003 *
1004 * @returns VBox status code.
1005 * @param pCtx Shared Clipboard command context to use for the connection.
1006 * @param pOpenParms Where to store the open parameters the host wants to use for opening the list handle.
1007 */
1008VBGLR3DECL(int) VbglR3ClipboardListOpenRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLLISTOPENPARMS pOpenParms)
1009{
1010 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1011 AssertPtrReturn(pOpenParms, VERR_INVALID_POINTER);
1012
1013 VBoxShClListOpenMsg Msg;
1014 RT_ZERO(Msg);
1015
1016 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1017 VBOX_SHCL_GUEST_FN_MSG_GET, VBOX_SHCL_CPARMS_LIST_OPEN);
1018
1019 Msg.uContext.SetUInt64(VBOX_SHCL_HOST_MSG_TRANSFER_LIST_OPEN);
1020 Msg.fList.SetUInt32(0);
1021 Msg.pvPath.SetPtr(pOpenParms->pszPath, pOpenParms->cbPath);
1022 Msg.pvFilter.SetPtr(pOpenParms->pszFilter, pOpenParms->cbFilter);
1023 Msg.uHandle.SetUInt64(0);
1024
1025 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1026 if (RT_SUCCESS(rc))
1027 {
1028 rc = Msg.uContext.GetUInt64(&pCtx->idContext);
1029 if (RT_SUCCESS(rc))
1030 rc = Msg.fList.GetUInt32(&pOpenParms->fList);
1031 }
1032
1033 LogFlowFuncLeaveRC(rc);
1034 return rc;
1035}
1036
1037/**
1038 * Replies to a list open request from the host.
1039 *
1040 * @returns VBox status code.
1041 * @param pCtx Shared Clipboard command context to use for the connection.
1042 * @param rcReply Return code to reply to the host.
1043 * @param hList List handle of (guest) list to reply to the host.
1044 */
1045VBGLR3DECL(int) VbglR3ClipboardListOpenReply(PVBGLR3SHCLCMDCTX pCtx, int rcReply, SHCLLISTHANDLE hList)
1046{
1047 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1048
1049 VBoxShClReplyMsg Msg;
1050 RT_ZERO(Msg);
1051
1052 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1053 VBOX_SHCL_GUEST_FN_REPLY, VBOX_SHCL_CPARMS_REPLY_MIN + 1);
1054
1055 Msg.uContext.SetUInt64(pCtx->idContext);
1056 Msg.enmType.SetUInt32(VBOX_SHCL_REPLYMSGTYPE_LIST_OPEN);
1057 Msg.rc.SetUInt32((uint32_t)rcReply); /** int vs. uint32_t */
1058 Msg.pvPayload.SetPtr(NULL, 0);
1059
1060 Msg.u.ListOpen.uHandle.SetUInt64(hList);
1061
1062 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1063
1064 LogFlowFuncLeaveRC(rc);
1065 return rc;
1066}
1067
1068/**
1069 * Receives a host request to close a list handle on the guest.
1070 *
1071 * @returns VBox status code.
1072 * @param pCtx Shared Clipboard command context to use for the connection.
1073 * @param phList Where to store the list handle to close, received from the host.
1074 */
1075VBGLR3DECL(int) VbglR3ClipboardListCloseRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLLISTHANDLE phList)
1076{
1077 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1078 AssertPtrReturn(phList, VERR_INVALID_POINTER);
1079
1080 VBoxShClListCloseMsg Msg;
1081 RT_ZERO(Msg);
1082
1083 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1084 VBOX_SHCL_GUEST_FN_MSG_GET, VBOX_SHCL_CPARMS_LIST_CLOSE);
1085
1086 Msg.uContext.SetUInt64(VBOX_SHCL_HOST_MSG_TRANSFER_LIST_CLOSE);
1087 Msg.uHandle.SetUInt64(0);
1088
1089 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1090 if (RT_SUCCESS(rc))
1091 {
1092 rc = Msg.uContext.GetUInt64(&pCtx->idContext);
1093 if (RT_SUCCESS(rc))
1094 rc = Msg.uHandle.GetUInt64(phList); AssertRC(rc);
1095 }
1096
1097 LogFlowFuncLeaveRC(rc);
1098 return rc;
1099}
1100
1101/**
1102 * Replies to a list handle close request from the host.
1103 *
1104 * @returns VBox status code.
1105 * @param pCtx Shared Clipboard command context to use for the connection.
1106 * @param rcReply Return code to reply to the host.
1107 * @param hList List handle the send the close reply for.
1108 */
1109VBGLR3DECL(int) VbglR3ClipboardListCloseReply(PVBGLR3SHCLCMDCTX pCtx, int rcReply, SHCLLISTHANDLE hList)
1110{
1111 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1112
1113 VBoxShClReplyMsg Msg;
1114 RT_ZERO(Msg);
1115
1116 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1117 VBOX_SHCL_GUEST_FN_REPLY, VBOX_SHCL_CPARMS_REPLY_MIN + 1);
1118
1119 Msg.uContext.SetUInt64(pCtx->idContext);
1120 Msg.enmType.SetUInt32(VBOX_SHCL_REPLYMSGTYPE_LIST_CLOSE);
1121 Msg.rc.SetUInt32((uint32_t)rcReply); /** int vs. uint32_t */
1122 Msg.pvPayload.SetPtr(NULL, 0);
1123
1124 Msg.u.ListOpen.uHandle.SetUInt64(hList);
1125
1126 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1127
1128 LogFlowFuncLeaveRC(rc);
1129 return rc;
1130}
1131
1132/**
1133 * Sends a request to close a list handle to the host.
1134 *
1135 * @returns VBox status code.
1136 * @param pCtx Shared Clipboard command context to use for the connection.
1137 * @param hList List handle to request for closing on the host.
1138 */
1139VBGLR3DECL(int) VbglR3ClipboardListCloseSend(PVBGLR3SHCLCMDCTX pCtx, SHCLLISTHANDLE hList)
1140{
1141 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1142
1143 VBoxShClListCloseMsg Msg;
1144 RT_ZERO(Msg);
1145
1146 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1147 VBOX_SHCL_GUEST_FN_LIST_CLOSE, VBOX_SHCL_CPARMS_LIST_CLOSE);
1148
1149 Msg.uContext.SetUInt64(pCtx->idContext);
1150 Msg.uHandle.SetUInt64(hList);
1151
1152 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1153
1154 LogFlowFuncLeaveRC(rc);
1155 return rc;
1156}
1157
1158/**
1159 * Sends a request to read a list header to the host.
1160 *
1161 * @returns VBox status code.
1162 * @param pCtx Shared Clipboard command context to use for the connection.
1163 * @param hList List handle to read list header for.
1164 * @param fFlags List header read flags to use.
1165 * @param pListHdr Where to return the list header received from the host.
1166 */
1167VBGLR3DECL(int) VbglR3ClipboardListHdrRead(PVBGLR3SHCLCMDCTX pCtx, SHCLLISTHANDLE hList, uint32_t fFlags,
1168 PSHCLLISTHDR pListHdr)
1169{
1170 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1171 AssertPtrReturn(pListHdr, VERR_INVALID_POINTER);
1172
1173 VBoxShClListHdrMsg Msg;
1174 RT_ZERO(Msg);
1175
1176 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1177 VBOX_SHCL_GUEST_FN_LIST_HDR_READ, VBOX_SHCL_CPARMS_LIST_HDR);
1178
1179 Msg.ReqParms.uContext.SetUInt64(pCtx->idContext);
1180 Msg.ReqParms.uHandle.SetUInt64(hList);
1181 Msg.ReqParms.fFlags.SetUInt32(fFlags);
1182
1183 Msg.fFeatures.SetUInt32(0);
1184 Msg.cbTotalSize.SetUInt32(0);
1185 Msg.cTotalObjects.SetUInt64(0);
1186 Msg.cbTotalSize.SetUInt64(0);
1187
1188 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1189 if (RT_SUCCESS(rc))
1190 {
1191 rc = Msg.fFeatures.GetUInt32(&pListHdr->fFeatures);
1192 if (RT_SUCCESS(rc))
1193 rc = Msg.cTotalObjects.GetUInt64(&pListHdr->cTotalObjects);
1194 if (RT_SUCCESS(rc))
1195 rc = Msg.cbTotalSize.GetUInt64(&pListHdr->cbTotalSize);
1196 }
1197
1198 LogFlowFuncLeaveRC(rc);
1199 return rc;
1200}
1201
1202/**
1203 * Receives a host request to read a list header on the guest.
1204 *
1205 * @returns VBox status code.
1206 * @param pCtx Shared Clipboard command context to use for the connection.
1207 * @param phList Where to return the list handle to read list header for.
1208 * @param pfFlags Where to return the List header read flags to use.
1209 */
1210VBGLR3DECL(int) VbglR3ClipboardListHdrReadRecvReq(PVBGLR3SHCLCMDCTX pCtx, PSHCLLISTHANDLE phList, uint32_t *pfFlags)
1211{
1212 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1213 AssertPtrReturn(phList, VERR_INVALID_POINTER);
1214 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
1215
1216 VBoxShClListHdrReadReqMsg Msg;
1217 RT_ZERO(Msg);
1218
1219 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1220 VBOX_SHCL_GUEST_FN_MSG_GET, VBOX_SHCL_CPARMS_LIST_HDR_READ_REQ);
1221
1222 Msg.ReqParms.uContext.SetUInt64(VBOX_SHCL_HOST_MSG_TRANSFER_LIST_HDR_READ);
1223 Msg.ReqParms.uHandle.SetUInt64(0);
1224 Msg.ReqParms.fFlags.SetUInt32(0);
1225
1226 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1227 if (RT_SUCCESS(rc))
1228 {
1229 rc = Msg.ReqParms.uContext.GetUInt64(&pCtx->idContext);
1230 if (RT_SUCCESS(rc))
1231 rc = Msg.ReqParms.uHandle.GetUInt64(phList);
1232 if (RT_SUCCESS(rc))
1233 rc = Msg.ReqParms.fFlags.GetUInt32(pfFlags);
1234 }
1235
1236 LogFlowFuncLeaveRC(rc);
1237 return rc;
1238}
1239
1240/**
1241 * Sends (writes) a list header to the host.
1242 *
1243 * @returns VBox status code.
1244 * @param pCtx Shared Clipboard command context to use for the connection.
1245 * @param hList List handle to write list header for.
1246 * @param pListHdr List header to write.
1247 */
1248VBGLR3DECL(int) VbglR3ClipboardListHdrWrite(PVBGLR3SHCLCMDCTX pCtx, SHCLLISTHANDLE hList,
1249 PSHCLLISTHDR pListHdr)
1250{
1251 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1252 AssertPtrReturn(pListHdr, VERR_INVALID_POINTER);
1253
1254 VBoxShClListHdrMsg Msg;
1255 RT_ZERO(Msg);
1256
1257 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1258 VBOX_SHCL_GUEST_FN_LIST_HDR_WRITE, VBOX_SHCL_CPARMS_LIST_HDR);
1259
1260 Msg.ReqParms.uContext.SetUInt64(pCtx->idContext);
1261 Msg.ReqParms.uHandle.SetUInt64(hList);
1262 Msg.ReqParms.fFlags.SetUInt32(0);
1263
1264 Msg.fFeatures.SetUInt32(0);
1265 Msg.cbTotalSize.SetUInt32(pListHdr->fFeatures);
1266 Msg.cTotalObjects.SetUInt64(pListHdr->cTotalObjects);
1267 Msg.cbTotalSize.SetUInt64(pListHdr->cbTotalSize);
1268
1269 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1270
1271 LogFlowFuncLeaveRC(rc);
1272 return rc;
1273}
1274
1275/**
1276 * Sends a request to read a list entry from the host.
1277 *
1278 * @returns VBox status code.
1279 * @param pCtx Shared Clipboard command context to use for the connection.
1280 * @param hList List handle to request to read a list entry for.
1281 * @param pListEntry Where to return the list entry read from the host.
1282 */
1283VBGLR3DECL(int) VbglR3ClipboardListEntryRead(PVBGLR3SHCLCMDCTX pCtx, SHCLLISTHANDLE hList,
1284 PSHCLLISTENTRY pListEntry)
1285{
1286 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1287 AssertPtrReturn(pListEntry, VERR_INVALID_POINTER);
1288
1289 VBoxShClListEntryMsg Msg;
1290 RT_ZERO(Msg);
1291
1292 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1293 VBOX_SHCL_GUEST_FN_LIST_ENTRY_READ, VBOX_SHCL_CPARMS_LIST_ENTRY);
1294
1295 Msg.ReqParms.uContext.SetUInt64(pCtx->idContext);
1296 Msg.ReqParms.uHandle.SetUInt64(hList);
1297 Msg.ReqParms.fInfo.SetUInt32(0);
1298
1299 Msg.szName.SetPtr(pListEntry->pszName, pListEntry->cbName);
1300 Msg.cbInfo.SetUInt32(pListEntry->cbInfo);
1301 Msg.pvInfo.SetPtr(pListEntry->pvInfo, pListEntry->cbInfo);
1302
1303 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1304 if (RT_SUCCESS(rc))
1305 {
1306 rc = Msg.cbInfo.GetUInt32(&pListEntry->cbInfo); AssertRC(rc);
1307 }
1308
1309 LogFlowFuncLeaveRC(rc);
1310 return rc;
1311}
1312
1313/**
1314 * Receives a host request to read a list entry from the guest.
1315 *
1316 * @returns VBox status code.
1317 * @param pCtx Shared Clipboard command context to use for the connection.
1318 * @param phList Where to return the list handle to read a list entry for.
1319 * @param pfInfo Where to return the list read flags.
1320 */
1321VBGLR3DECL(int) VbglR3ClipboardListEntryReadRecvReq(PVBGLR3SHCLCMDCTX pCtx, PSHCLLISTHANDLE phList, uint32_t *pfInfo)
1322{
1323 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1324 AssertPtrReturn(phList, VERR_INVALID_POINTER);
1325 AssertPtrReturn(pfInfo, VERR_INVALID_POINTER);
1326
1327 VBoxShClListEntryReadReqMsg Msg;
1328 RT_ZERO(Msg);
1329
1330 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1331 VBOX_SHCL_GUEST_FN_MSG_GET, VBOX_SHCL_CPARMS_LIST_ENTRY_READ);
1332
1333 Msg.ReqParms.uContext.SetUInt64(VBOX_SHCL_HOST_MSG_TRANSFER_LIST_ENTRY_READ);
1334 Msg.ReqParms.uHandle.SetUInt64(0);
1335 Msg.ReqParms.fInfo.SetUInt32(0);
1336
1337 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1338 if (RT_SUCCESS(rc))
1339 {
1340 rc = Msg.ReqParms.uContext.GetUInt64(&pCtx->idContext);
1341 if (RT_SUCCESS(rc))
1342 rc = Msg.ReqParms.uHandle.GetUInt64(phList); AssertRC(rc);
1343 if (RT_SUCCESS(rc))
1344 rc = Msg.ReqParms.fInfo.GetUInt32(pfInfo); AssertRC(rc);
1345 }
1346
1347 LogFlowFuncLeaveRC(rc);
1348 return rc;
1349}
1350
1351/**
1352 * Sends (writes) a list entry to the host.
1353 *
1354 * @returns VBox status code.
1355 * @param pCtx Shared Clipboard command context to use for the connection.
1356 * @param hList List handle to write a list etnry for.
1357 * @param pListEntry List entry to write.
1358 */
1359VBGLR3DECL(int) VbglR3ClipboardListEntryWrite(PVBGLR3SHCLCMDCTX pCtx, SHCLLISTHANDLE hList,
1360 PSHCLLISTENTRY pListEntry)
1361{
1362 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1363 AssertPtrReturn(pListEntry, VERR_INVALID_POINTER);
1364
1365 VBoxShClListEntryMsg Msg;
1366 RT_ZERO(Msg);
1367
1368 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1369 VBOX_SHCL_GUEST_FN_LIST_ENTRY_WRITE, VBOX_SHCL_CPARMS_LIST_ENTRY);
1370
1371 Msg.ReqParms.uContext.SetUInt64(pCtx->idContext);
1372 Msg.ReqParms.uHandle.SetUInt64(hList);
1373 Msg.ReqParms.fInfo.SetUInt32(pListEntry->fInfo);
1374
1375 Msg.szName.SetPtr(pListEntry->pszName, pListEntry->cbName);
1376 Msg.cbInfo.SetUInt32(pListEntry->cbInfo);
1377 Msg.pvInfo.SetPtr(pListEntry->pvInfo, pListEntry->cbInfo);
1378
1379 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1380
1381 LogFlowFuncLeaveRC(rc);
1382 return rc;
1383}
1384
1385/**
1386 * Receives a host request to open an object on the guest.
1387 *
1388 * @returns VBox status code.
1389 * @param pCtx Shared Clipboard command context to use for the connection.
1390 * @param pCreateParms Where to store the object open/create parameters received from the host.
1391 */
1392VBGLR3DECL(int) VbglR3ClipboardObjOpenRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLOBJOPENCREATEPARMS pCreateParms)
1393{
1394 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1395 AssertPtrReturn(pCreateParms, VERR_INVALID_POINTER);
1396
1397 VBoxShClObjOpenMsg Msg;
1398 RT_ZERO(Msg);
1399
1400 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1401 VBOX_SHCL_GUEST_FN_MSG_GET, VBOX_SHCL_CPARMS_OBJ_OPEN);
1402
1403 Msg.uContext.SetUInt64(VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_OPEN);
1404 Msg.uHandle.SetUInt64(0);
1405 Msg.szPath.SetPtr(pCreateParms->pszPath, pCreateParms->cbPath);
1406 Msg.fCreate.SetUInt32(0);
1407
1408 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1409 if (RT_SUCCESS(rc))
1410 {
1411 rc = Msg.uContext.GetUInt64(&pCtx->idContext);
1412 if (RT_SUCCESS(rc))
1413 rc = Msg.fCreate.GetUInt32(&pCreateParms->fCreate);
1414 }
1415
1416 LogFlowFuncLeaveRC(rc);
1417 return rc;
1418}
1419
1420/**
1421 * Replies a host request to open an object.
1422 *
1423 * @returns VBox status code.
1424 * @param pCtx Shared Clipboard command context to use for the connection.
1425 * @param rcReply Return code to reply to the host.
1426 * @param hObj Object handle of opened object to reply to the host.
1427 */
1428VBGLR3DECL(int) VbglR3ClipboardObjOpenReply(PVBGLR3SHCLCMDCTX pCtx, int rcReply, SHCLOBJHANDLE hObj)
1429{
1430 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1431
1432 VBoxShClReplyMsg Msg;
1433 RT_ZERO(Msg);
1434
1435 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1436 VBOX_SHCL_GUEST_FN_REPLY, VBOX_SHCL_CPARMS_REPLY_MIN + 1);
1437
1438 Msg.uContext.SetUInt64(pCtx->idContext);
1439 Msg.enmType.SetUInt32(VBOX_SHCL_REPLYMSGTYPE_OBJ_OPEN);
1440 Msg.rc.SetUInt32((uint32_t)rcReply); /** int vs. uint32_t */
1441 Msg.pvPayload.SetPtr(NULL, 0);
1442
1443 Msg.u.ObjOpen.uHandle.SetUInt64(hObj);
1444
1445 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1446
1447 LogFlowFuncLeaveRC(rc);
1448 return rc;
1449}
1450
1451/**
1452 * Sends an object open request to the host.
1453 *
1454 * @returns VBox status code.
1455 * @param pCtx Shared Clipboard command context to use for the connection.
1456 * @param pCreateParms Object open/create parameters to use for opening the object on the host.
1457 * @param phObj Where to return the object handle from the host.
1458 */
1459VBGLR3DECL(int) VbglR3ClipboardObjOpenSend(PVBGLR3SHCLCMDCTX pCtx, PSHCLOBJOPENCREATEPARMS pCreateParms,
1460 PSHCLOBJHANDLE phObj)
1461{
1462 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1463 AssertPtrReturn(pCreateParms, VERR_INVALID_POINTER);
1464 AssertPtrReturn(phObj, VERR_INVALID_POINTER);
1465
1466 VBoxShClObjOpenMsg Msg;
1467 RT_ZERO(Msg);
1468
1469 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1470 VBOX_SHCL_GUEST_FN_OBJ_OPEN, VBOX_SHCL_CPARMS_OBJ_OPEN);
1471
1472 Msg.uContext.SetUInt64(pCtx->idContext);
1473 Msg.uHandle.SetUInt64(0);
1474 Msg.szPath.SetPtr((void *)pCreateParms->pszPath, pCreateParms->cbPath);
1475 Msg.fCreate.SetUInt32(pCreateParms->fCreate);
1476
1477 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1478 if (RT_SUCCESS(rc))
1479 {
1480 Msg.uHandle.GetUInt64(phObj);
1481 }
1482
1483 LogFlowFuncLeaveRC(rc);
1484 return rc;
1485}
1486
1487/**
1488 * Receives a host request to close an object on the guest.
1489 *
1490 * @returns VBox status code.
1491 * @param pCtx Shared Clipboard command context to use for the connection.
1492 * @param phObj Where to return the object handle to close from the host.
1493 */
1494VBGLR3DECL(int) VbglR3ClipboardObjCloseRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLOBJHANDLE phObj)
1495{
1496 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1497 AssertPtrReturn(phObj, VERR_INVALID_POINTER);
1498
1499 VBoxShClObjCloseMsg Msg;
1500 RT_ZERO(Msg);
1501
1502 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1503 VBOX_SHCL_GUEST_FN_MSG_GET, VBOX_SHCL_CPARMS_OBJ_CLOSE);
1504
1505 Msg.uContext.SetUInt64(VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_CLOSE);
1506 Msg.uHandle.SetUInt64(0);
1507
1508 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1509 if (RT_SUCCESS(rc))
1510 {
1511 rc = Msg.uContext.GetUInt64(&pCtx->idContext);
1512 if (RT_SUCCESS(rc))
1513 rc = Msg.uHandle.GetUInt64(phObj);
1514 }
1515
1516 LogFlowFuncLeaveRC(rc);
1517 return rc;
1518}
1519
1520/**
1521 * Replies to an object open request from the host.
1522 *
1523 * @returns VBox status code.
1524 * @param pCtx Shared Clipboard command context to use for the connection.
1525 * @param rcReply Return code to reply to the host.
1526 * @param hObj Object handle to reply to the host.
1527 */
1528VBGLR3DECL(int) VbglR3ClipboardObjCloseReply(PVBGLR3SHCLCMDCTX pCtx, int rcReply, SHCLOBJHANDLE hObj)
1529{
1530 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1531
1532 VBoxShClReplyMsg Msg;
1533 RT_ZERO(Msg);
1534
1535 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1536 VBOX_SHCL_GUEST_FN_REPLY, VBOX_SHCL_CPARMS_REPLY_MIN + 1);
1537
1538 Msg.uContext.SetUInt64(pCtx->idContext);
1539 Msg.enmType.SetUInt32(VBOX_SHCL_REPLYMSGTYPE_OBJ_CLOSE);
1540 Msg.rc.SetUInt32((uint32_t)rcReply); /** int vs. uint32_t */
1541 Msg.pvPayload.SetPtr(NULL, 0);
1542
1543 Msg.u.ObjClose.uHandle.SetUInt64(hObj);
1544
1545 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1546
1547 LogFlowFuncLeaveRC(rc);
1548 return rc;
1549}
1550
1551/**
1552 * Sends a request to close an object to the host.
1553 *
1554 * @returns VBox status code.
1555 * @param pCtx Shared Clipboard command context to use for the connection.
1556 * @param hObj Object handle to close on the host.
1557 */
1558VBGLR3DECL(int) VbglR3ClipboardObjCloseSend(PVBGLR3SHCLCMDCTX pCtx, SHCLOBJHANDLE hObj)
1559{
1560 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1561
1562 VBoxShClObjCloseMsg Msg;
1563 RT_ZERO(Msg);
1564
1565 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1566 VBOX_SHCL_GUEST_FN_OBJ_CLOSE, VBOX_SHCL_CPARMS_OBJ_CLOSE);
1567
1568 Msg.uContext.SetUInt64(pCtx->idContext);
1569 Msg.uHandle.SetUInt64(hObj);
1570
1571 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1572
1573 LogFlowFuncLeaveRC(rc);
1574 return rc;
1575}
1576
1577/**
1578 * Receives a host request to read from an object on the guest.
1579 *
1580 * @returns VBox status code.
1581 * @param pCtx Shared Clipboard command context to use for the connection.
1582 * @param phObj Where to return the object handle to read from.
1583 * @param pcbToRead Where to return the amount (in bytes) to read.
1584 * @param pfFlags Where to return the read flags.
1585 */
1586VBGLR3DECL(int) VbglR3ClipboardObjReadRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLOBJHANDLE phObj, uint32_t *pcbToRead,
1587 uint32_t *pfFlags)
1588{
1589 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1590 AssertPtrReturn(phObj, VERR_INVALID_POINTER);
1591 AssertPtrReturn(pcbToRead, VERR_INVALID_POINTER);
1592 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
1593
1594 VBoxShClObjReadReqMsg Msg;
1595 RT_ZERO(Msg);
1596
1597 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1598 VBOX_SHCL_GUEST_FN_MSG_GET, VBOX_SHCL_CPARMS_OBJ_READ_REQ);
1599
1600 Msg.ReqParms.uContext.SetUInt64(VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_READ);
1601 Msg.ReqParms.uHandle.SetUInt64(0);
1602 Msg.ReqParms.cbToRead.SetUInt32(0);
1603 Msg.ReqParms.fRead.SetUInt32(0);
1604
1605 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1606 if (RT_SUCCESS(rc))
1607 {
1608 rc = Msg.ReqParms.uContext.GetUInt64(&pCtx->idContext);
1609 if (RT_SUCCESS(rc))
1610 rc = Msg.ReqParms.uHandle.GetUInt64(phObj);
1611 if (RT_SUCCESS(rc))
1612 rc = Msg.ReqParms.cbToRead.GetUInt32(pcbToRead);
1613 if (RT_SUCCESS(rc))
1614 rc = Msg.ReqParms.fRead.GetUInt32(pfFlags);
1615 }
1616
1617 LogFlowFuncLeaveRC(rc);
1618 return rc;
1619}
1620
1621/**
1622 * Sends a request to read from an object to the host.
1623 *
1624 * @returns VBox status code.
1625 * @param pCtx Shared Clipboard command context to use for the connection.
1626 * @param hObj Object handle of object to read from.
1627 * @param pvData Buffer where to store the read object data.
1628 * @param cbData Size (in bytes) of buffer.
1629 * @param pcbRead Where to store the amount (in bytes) read from the object.
1630 */
1631VBGLR3DECL(int) VbglR3ClipboardObjReadSend(PVBGLR3SHCLCMDCTX pCtx, SHCLOBJHANDLE hObj,
1632 void *pvData, uint32_t cbData, uint32_t *pcbRead)
1633{
1634 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1635 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
1636 AssertReturn(cbData, VERR_INVALID_PARAMETER);
1637 /* pcbRead is optional. */
1638
1639 VBoxShClObjReadWriteMsg Msg;
1640 RT_ZERO(Msg);
1641
1642 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1643 VBOX_SHCL_GUEST_FN_OBJ_READ, VBOX_SHCL_CPARMS_OBJ_READ);
1644
1645 Msg.uContext.SetUInt64(pCtx->idContext);
1646 Msg.uHandle.SetUInt64(hObj);
1647 Msg.cbData.SetUInt32(cbData);
1648 Msg.pvData.SetPtr(pvData, cbData);
1649 Msg.cbChecksum.SetUInt32(0);
1650 Msg.pvChecksum.SetPtr(NULL, 0);
1651
1652 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1653 if (RT_SUCCESS(rc))
1654 {
1655 /** @todo Add checksum support. */
1656
1657 if (pcbRead)
1658 {
1659 rc = Msg.cbData.GetUInt32(pcbRead); AssertRC(rc);
1660 AssertReturn(cbData >= *pcbRead, VERR_TOO_MUCH_DATA);
1661 }
1662 }
1663
1664 LogFlowFuncLeaveRC(rc);
1665 return rc;
1666}
1667
1668/**
1669 * Sends a request to write to an object to the host.
1670 *
1671 * @returns VBox status code.
1672 * @param pCtx Shared Clipboard command context to use for the connection.
1673 * @param hObj Object handle of object to write to.
1674 * @param pvData Buffer of data to write to object.
1675 * @param cbData Size (in bytes) of buffer.
1676 * @param pcbWritten Where to store the amount (in bytes) written to the object.
1677 */
1678VBGLR3DECL(int) VbglR3ClipboardObjWriteSend(PVBGLR3SHCLCMDCTX pCtx, SHCLOBJHANDLE hObj,
1679 void *pvData, uint32_t cbData, uint32_t *pcbWritten)
1680{
1681 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1682 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
1683 /* cbData can be 0. */
1684 /* pcbWritten is optional. */
1685
1686 VBoxShClObjReadWriteMsg Msg;
1687 RT_ZERO(Msg);
1688
1689 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1690 VBOX_SHCL_GUEST_FN_OBJ_WRITE, VBOX_SHCL_CPARMS_OBJ_WRITE);
1691
1692 Msg.uContext.SetUInt64(pCtx->idContext);
1693 Msg.uHandle.SetUInt64(hObj);
1694 Msg.pvData.SetPtr(pvData, cbData);
1695 Msg.pvChecksum.SetPtr(NULL, 0);
1696
1697 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1698 if (RT_SUCCESS(rc))
1699 {
1700 /** @todo Add checksum support. */
1701
1702 if (pcbWritten)
1703 *pcbWritten = cbData; /** @todo For now return all as being written. */
1704 }
1705
1706 LogFlowFuncLeaveRC(rc);
1707 return rc;
1708}
1709
1710
1711/*********************************************************************************************************************************
1712* Transfer interface implementations *
1713*********************************************************************************************************************************/
1714
1715static DECLCALLBACK(int) vbglR3ClipboardTransferIfaceGetRoots(PSHCLPROVIDERCTX pCtx, PSHCLROOTLIST *ppRootList)
1716{
1717 LogFlowFuncEnter();
1718
1719 PVBGLR3SHCLCMDCTX pCmdCtx = (PVBGLR3SHCLCMDCTX)pCtx->pvUser;
1720 AssertPtr(pCmdCtx);
1721
1722 int rc = VbglR3ClipboardRootListRead(pCmdCtx, ppRootList);
1723
1724 LogFlowFuncLeaveRC(rc);
1725 return rc;
1726}
1727
1728static DECLCALLBACK(int) vbglR3ClipboardTransferIfaceListOpen(PSHCLPROVIDERCTX pCtx, PSHCLLISTOPENPARMS pOpenParms,
1729 PSHCLLISTHANDLE phList)
1730{
1731 LogFlowFuncEnter();
1732
1733 PVBGLR3SHCLCMDCTX pCmdCtx = (PVBGLR3SHCLCMDCTX)pCtx->pvUser;
1734 AssertPtr(pCmdCtx);
1735
1736 int rc = VbglR3ClipboardListOpenSend(pCmdCtx, pOpenParms, phList);
1737
1738 LogFlowFuncLeaveRC(rc);
1739 return rc;
1740}
1741
1742static DECLCALLBACK(int) vbglR3ClipboardTransferIfaceListClose(PSHCLPROVIDERCTX pCtx, SHCLLISTHANDLE hList)
1743{
1744 LogFlowFuncEnter();
1745
1746 PVBGLR3SHCLCMDCTX pCmdCtx = (PVBGLR3SHCLCMDCTX)pCtx->pvUser;
1747 AssertPtr(pCmdCtx);
1748
1749 int rc = VbglR3ClipboardListCloseSend(pCmdCtx, hList);
1750
1751 LogFlowFuncLeaveRC(rc);
1752 return rc;
1753}
1754
1755static DECLCALLBACK(int) vbglR3ClipboardTransferIfaceListHdrRead(PSHCLPROVIDERCTX pCtx,
1756 SHCLLISTHANDLE hList, PSHCLLISTHDR pListHdr)
1757{
1758 LogFlowFuncEnter();
1759
1760 PVBGLR3SHCLCMDCTX pCmdCtx = (PVBGLR3SHCLCMDCTX)pCtx->pvUser;
1761 AssertPtr(pCmdCtx);
1762
1763 int rc = ShClTransferListHdrInit(pListHdr);
1764 if (RT_SUCCESS(rc))
1765 {
1766 if (RT_SUCCESS(rc))
1767 {
1768 rc = VbglR3ClipboardListHdrRead(pCmdCtx, hList, 0 /* fFlags */, pListHdr);
1769 }
1770 else
1771 ShClTransferListHdrDestroy(pListHdr);
1772 }
1773
1774 LogFlowFuncLeaveRC(rc);
1775 return rc;
1776}
1777
1778static DECLCALLBACK(int) vbglR3ClipboardTransferIfaceListEntryRead(PSHCLPROVIDERCTX pCtx,
1779 SHCLLISTHANDLE hList, PSHCLLISTENTRY pEntry)
1780{
1781 LogFlowFuncEnter();
1782
1783 PVBGLR3SHCLCMDCTX pCmdCtx = (PVBGLR3SHCLCMDCTX)pCtx->pvUser;
1784 AssertPtr(pCmdCtx);
1785
1786 int rc = VbglR3ClipboardListEntryRead(pCmdCtx, hList, pEntry);
1787
1788 LogFlowFuncLeaveRC(rc);
1789 return rc;
1790}
1791
1792static DECLCALLBACK(int) vbglR3ClipboardTransferIfaceObjOpen(PSHCLPROVIDERCTX pCtx,
1793 PSHCLOBJOPENCREATEPARMS pCreateParms, PSHCLOBJHANDLE phObj)
1794{
1795 LogFlowFuncEnter();
1796
1797 PVBGLR3SHCLCMDCTX pCmdCtx = (PVBGLR3SHCLCMDCTX)pCtx->pvUser;
1798 AssertPtr(pCmdCtx);
1799
1800 int rc = VbglR3ClipboardObjOpenSend(pCmdCtx, pCreateParms, phObj);
1801
1802 LogFlowFuncLeaveRC(rc);
1803 return rc;
1804}
1805
1806static DECLCALLBACK(int) vbglR3ClipboardTransferIfaceObjClose(PSHCLPROVIDERCTX pCtx, SHCLOBJHANDLE hObj)
1807{
1808 LogFlowFuncEnter();
1809
1810 PVBGLR3SHCLCMDCTX pCmdCtx = (PVBGLR3SHCLCMDCTX)pCtx->pvUser;
1811 AssertPtr(pCmdCtx);
1812
1813 int rc = VbglR3ClipboardObjCloseSend(pCmdCtx, hObj);
1814
1815 LogFlowFuncLeaveRC(rc);
1816 return rc;
1817}
1818
1819static DECLCALLBACK(int) vbglR3ClipboardTransferIfaceObjRead(PSHCLPROVIDERCTX pCtx,
1820 SHCLOBJHANDLE hObj, void *pvData, uint32_t cbData,
1821 uint32_t fFlags, uint32_t *pcbRead)
1822{
1823 LogFlowFuncEnter();
1824
1825 PVBGLR3SHCLCMDCTX pCmdCtx = (PVBGLR3SHCLCMDCTX)pCtx->pvUser;
1826 AssertPtr(pCmdCtx);
1827
1828 RT_NOREF(fFlags); /* Not used yet. */
1829
1830 int rc = VbglR3ClipboardObjReadSend(pCmdCtx, hObj, pvData, cbData, pcbRead);
1831
1832 LogFlowFuncLeaveRC(rc);
1833 return rc;
1834}
1835
1836/**
1837 * Starts a transfer on the guest side.
1838 *
1839 * @returns VBox status code.
1840 * @param pCmdCtx Command context to use.
1841 * @param pTransferCtx Transfer context to create transfer for.
1842 * @param uTransferID ID to use for transfer to start.
1843 * @param enmDir Direction of transfer to start.
1844 * @param enmSource Source of transfer to start.
1845 * @param ppTransfer Where to return the transfer object on success. Optional.
1846 */
1847static int vbglR3ClipboardTransferStart(PVBGLR3SHCLCMDCTX pCmdCtx, PSHCLTRANSFERCTX pTransferCtx,
1848 SHCLTRANSFERID uTransferID, SHCLTRANSFERDIR enmDir, SHCLSOURCE enmSource,
1849 PSHCLTRANSFER *ppTransfer)
1850{
1851 PSHCLTRANSFER pTransfer;
1852 int rc = ShClTransferCreate(&pTransfer);
1853 if (RT_SUCCESS(rc))
1854 {
1855 ShClTransferSetCallbacks(pTransfer, &pCmdCtx->Callbacks);
1856
1857 rc = ShClTransferCtxTransferRegisterByIndex(pTransferCtx, pTransfer, uTransferID);
1858 if (RT_SUCCESS(rc))
1859 {
1860 rc = ShClTransferInit(pTransfer, uTransferID, enmDir, enmSource);
1861 if (RT_SUCCESS(rc))
1862 {
1863 /* If this is a read transfer (reading data from host), set the interface to use
1864 * our VbglR3 routines here. */
1865 if (enmDir == SHCLTRANSFERDIR_FROM_REMOTE)
1866 {
1867 SHCLPROVIDERCREATIONCTX creationCtx;
1868 RT_ZERO(creationCtx);
1869
1870 creationCtx.Interface.pfnRootsGet = vbglR3ClipboardTransferIfaceGetRoots;
1871
1872 creationCtx.Interface.pfnListOpen = vbglR3ClipboardTransferIfaceListOpen;
1873 creationCtx.Interface.pfnListClose = vbglR3ClipboardTransferIfaceListClose;
1874 creationCtx.Interface.pfnListHdrRead = vbglR3ClipboardTransferIfaceListHdrRead;
1875 creationCtx.Interface.pfnListEntryRead = vbglR3ClipboardTransferIfaceListEntryRead;
1876
1877 creationCtx.Interface.pfnObjOpen = vbglR3ClipboardTransferIfaceObjOpen;
1878 creationCtx.Interface.pfnObjClose = vbglR3ClipboardTransferIfaceObjClose;
1879 creationCtx.Interface.pfnObjRead = vbglR3ClipboardTransferIfaceObjRead;
1880
1881 creationCtx.pvUser = pCmdCtx;
1882
1883 rc = ShClTransferSetInterface(pTransfer, &creationCtx);
1884 }
1885
1886 if (RT_SUCCESS(rc))
1887 rc = ShClTransferStart(pTransfer);
1888 }
1889
1890 if (RT_FAILURE(rc))
1891 ShClTransferCtxTransferUnregister(pTransferCtx, uTransferID);
1892 }
1893 }
1894
1895 if (RT_SUCCESS(rc))
1896 {
1897 if (ppTransfer)
1898 *ppTransfer = pTransfer;
1899
1900 LogRel2(("Shared Clipboard: Transfer ID=%RU16 (%s %s) successfully started\n",
1901 uTransferID,
1902 enmDir == SHCLTRANSFERDIR_FROM_REMOTE ? "reading from" : "writing to",
1903 enmSource == SHCLSOURCE_LOCAL ? "local" : "remote"));
1904 }
1905 else
1906 LogRel(("Shared Clipboard: Unable to start transfer ID=%RU16, rc=%Rrc\n", uTransferID, rc));
1907
1908 /* Send a reply in any case. */
1909 int rc2 = VbglR3ClipboardTransferStatusReply(pCmdCtx, pTransfer,
1910 RT_SUCCESS(rc)
1911 ? SHCLTRANSFERSTATUS_STARTED : SHCLTRANSFERSTATUS_ERROR, rc);
1912 if (RT_SUCCESS(rc))
1913 rc = rc2;
1914
1915 if (RT_FAILURE(rc))
1916 {
1917 ShClTransferDestroy(pTransfer);
1918 pTransfer = NULL;
1919 }
1920
1921 LogFlowFuncLeaveRC(rc);
1922 return rc;
1923}
1924
1925/**
1926 * Stops a transfer on the guest side.
1927 *
1928 * @returns VBox status code, or VERR_NOT_FOUND if transfer has not been found.
1929 * @param pCmdCtx Command context to use.
1930 * @param pTransferCtx Transfer context to stop transfer for.
1931 * @param uTransferID ID of transfer to stop.
1932 */
1933static int vbglR3ClipboardTransferStop(PVBGLR3SHCLCMDCTX pCmdCtx, PSHCLTRANSFERCTX pTransferCtx,
1934 SHCLTRANSFERID uTransferID)
1935{
1936 int rc;
1937
1938 PSHCLTRANSFER pTransfer = ShClTransferCtxGetTransfer(pTransferCtx, uTransferID);
1939 if (pTransfer)
1940 {
1941 rc = ShClTransferClose(pTransfer);
1942 if (RT_SUCCESS(rc))
1943 rc = ShClTransferCtxTransferUnregister(pTransferCtx, uTransferID);
1944
1945 if (RT_SUCCESS(rc))
1946 {
1947 LogRel2(("Shared Clipboard: Transfer ID=%RU16 successfully stopped\n", uTransferID));
1948 }
1949 else
1950 LogRel(("Shared Clipboard: Unable to stop transfer ID=%RU16, rc=%Rrc\n", uTransferID, rc));
1951
1952 /* Send a reply in any case. */
1953 int rc2 = VbglR3ClipboardTransferStatusReply(pCmdCtx, pTransfer,
1954 RT_SUCCESS(rc)
1955 ? SHCLTRANSFERSTATUS_STOPPED : SHCLTRANSFERSTATUS_ERROR, rc);
1956 AssertRC(rc2);
1957 }
1958 else
1959 rc = VERR_NOT_FOUND;
1960
1961 LogFlowFuncLeaveRC(rc);
1962 return rc;
1963}
1964
1965VBGLR3DECL(int) VbglR3ClipboardEventGetNextEx(uint32_t idMsg, uint32_t cParms,
1966 PVBGLR3SHCLCMDCTX pCmdCtx, PSHCLTRANSFERCTX pTransferCtx,
1967 PVBGLR3CLIPBOARDEVENT pEvent)
1968{
1969 AssertPtrReturn(pCmdCtx, VERR_INVALID_POINTER);
1970 AssertPtrReturn(pTransferCtx, VERR_INVALID_POINTER);
1971 AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
1972
1973 LogFunc(("Handling idMsg=%RU32 (%s), cParms=%RU32\n", idMsg, ShClHostMsgToStr(idMsg), cParms));
1974
1975 int rc;
1976 if (!pCmdCtx->fUseLegacyProtocol)
1977 {
1978 bool fErrorSent = false; /* Whether an error has been reported back to the host already. */
1979
1980 switch (idMsg)
1981 {
1982 case VBOX_SHCL_HOST_MSG_TRANSFER_STATUS:
1983 {
1984 SHCLTRANSFERDIR enmDir;
1985 SHCLTRANSFERREPORT transferReport;
1986 rc = VbglR3ClipboarTransferStatusRecv(pCmdCtx, &enmDir, &transferReport);
1987 if (RT_SUCCESS(rc))
1988 {
1989 const SHCLTRANSFERID uTransferID = VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->idContext);
1990
1991 LogFlowFunc(("[Transfer %RU16] enmDir=%RU32, status=%s\n",
1992 uTransferID, enmDir, ShClTransferStatusToStr(transferReport.uStatus)));
1993
1994 switch (transferReport.uStatus)
1995 {
1996 case SHCLTRANSFERSTATUS_INITIALIZED:
1997 RT_FALL_THROUGH();
1998 case SHCLTRANSFERSTATUS_STARTED:
1999 {
2000 SHCLSOURCE enmSource = SHCLSOURCE_INVALID;
2001
2002 /* The host announces the transfer direction from its point of view, so inverse the direction here. */
2003 if (enmDir == SHCLTRANSFERDIR_TO_REMOTE)
2004 {
2005 enmDir = SHCLTRANSFERDIR_FROM_REMOTE;
2006 enmSource = SHCLSOURCE_REMOTE;
2007 }
2008 else if (enmDir == SHCLTRANSFERDIR_FROM_REMOTE)
2009 {
2010 enmDir = SHCLTRANSFERDIR_TO_REMOTE;
2011 enmSource = SHCLSOURCE_LOCAL;
2012 }
2013 else
2014 AssertFailedBreakStmt(rc = VERR_INVALID_PARAMETER);
2015
2016 rc = vbglR3ClipboardTransferStart(pCmdCtx, pTransferCtx, uTransferID,
2017 enmDir, enmSource, NULL /* ppTransfer */);
2018 break;
2019 }
2020
2021 case SHCLTRANSFERSTATUS_STOPPED:
2022 RT_FALL_THROUGH();
2023 case SHCLTRANSFERSTATUS_CANCELED:
2024 RT_FALL_THROUGH();
2025 case SHCLTRANSFERSTATUS_KILLED:
2026 RT_FALL_THROUGH();
2027 case SHCLTRANSFERSTATUS_ERROR:
2028 {
2029 rc = vbglR3ClipboardTransferStop(pCmdCtx, pTransferCtx,
2030 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->idContext));
2031 break;
2032 }
2033
2034 default:
2035 rc = VERR_NOT_SUPPORTED;
2036 break;
2037 }
2038
2039 if (RT_SUCCESS(rc))
2040 {
2041 pEvent->u.TransferStatus.enmDir = enmDir;
2042 pEvent->u.TransferStatus.Report = transferReport;
2043 pEvent->u.TransferStatus.uID = VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->idContext);
2044
2045 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_TRANSFER_STATUS;
2046
2047 LogRel2(("Shared Clipboard: Received status %s (rc=%Rrc) for transfer ID=%RU16\n",
2048 ShClTransferStatusToStr(pEvent->u.TransferStatus.Report.uStatus), pEvent->u.TransferStatus.Report.rc,
2049 pEvent->u.TransferStatus.uID));
2050 }
2051 }
2052 break;
2053 }
2054
2055 case VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_HDR_READ:
2056 {
2057 uint32_t fRoots;
2058 rc = VbglR3ClipboardRootListHdrReadReq(pCmdCtx, &fRoots);
2059
2060 /** @todo Validate / handle fRoots. */
2061
2062 if (RT_SUCCESS(rc))
2063 {
2064 PSHCLTRANSFER pTransfer = ShClTransferCtxGetTransfer(pTransferCtx,
2065 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->idContext));
2066 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND);
2067
2068 SHCLROOTLISTHDR rootListHdr;
2069 RT_ZERO(rootListHdr);
2070
2071 rootListHdr.cRoots = ShClTransferRootsCount(pTransfer);
2072
2073 LogFlowFunc(("cRoots=%RU32\n", rootListHdr.cRoots));
2074
2075 rc = VbglR3ClipboardRootListHdrReadReply(pCmdCtx, &rootListHdr);
2076 }
2077 break;
2078 }
2079
2080 case VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_ENTRY_READ:
2081 {
2082 uint32_t uIndex;
2083 uint32_t fInfo;
2084 rc = VbglR3ClipboardRootListEntryReadReq(pCmdCtx, &uIndex, &fInfo);
2085 if (RT_SUCCESS(rc))
2086 {
2087 PSHCLTRANSFER pTransfer = ShClTransferCtxGetTransfer(pTransferCtx,
2088 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->idContext));
2089 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND);
2090
2091 SHCLROOTLISTENTRY rootListEntry;
2092 rc = ShClTransferRootsEntry(pTransfer, uIndex, &rootListEntry);
2093 if (RT_SUCCESS(rc))
2094 rc = VbglR3ClipboardRootListEntryReadReply(pCmdCtx, uIndex, &rootListEntry);
2095 }
2096 break;
2097 }
2098
2099 case VBOX_SHCL_HOST_MSG_TRANSFER_LIST_OPEN:
2100 {
2101 SHCLLISTOPENPARMS openParmsList;
2102 rc = ShClTransferListOpenParmsInit(&openParmsList);
2103 if (RT_SUCCESS(rc))
2104 {
2105 rc = VbglR3ClipboardListOpenRecv(pCmdCtx, &openParmsList);
2106 if (RT_SUCCESS(rc))
2107 {
2108 PSHCLTRANSFER pTransfer = ShClTransferCtxGetTransfer(pTransferCtx,
2109 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->idContext));
2110 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND);
2111
2112 LogFlowFunc(("pszPath=%s\n", openParmsList.pszPath));
2113
2114 SHCLLISTHANDLE hList = SHCLLISTHANDLE_INVALID;
2115 rc = ShClTransferListOpen(pTransfer, &openParmsList, &hList);
2116
2117 /* Reply in any case. */
2118 int rc2 = VbglR3ClipboardListOpenReply(pCmdCtx, rc, hList);
2119 AssertRC(rc2);
2120 }
2121
2122 ShClTransferListOpenParmsDestroy(&openParmsList);
2123 }
2124
2125 break;
2126 }
2127
2128 case VBOX_SHCL_HOST_MSG_TRANSFER_LIST_CLOSE:
2129 {
2130 SHCLLISTHANDLE hList;
2131 rc = VbglR3ClipboardListCloseRecv(pCmdCtx, &hList);
2132 if (RT_SUCCESS(rc))
2133 {
2134 PSHCLTRANSFER pTransfer = ShClTransferCtxGetTransfer(pTransferCtx,
2135 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->idContext));
2136 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND);
2137
2138 rc = ShClTransferListClose(pTransfer, hList);
2139
2140 /* Reply in any case. */
2141 int rc2 = VbglR3ClipboardListCloseReply(pCmdCtx, rc, hList);
2142 AssertRC(rc2);
2143 }
2144
2145 break;
2146 }
2147
2148 case VBOX_SHCL_HOST_MSG_TRANSFER_LIST_HDR_READ:
2149 {
2150 /** @todo Handle filter + list features. */
2151
2152 SHCLLISTHANDLE hList = SHCLLISTHANDLE_INVALID;
2153 uint32_t fFlags = 0;
2154 rc = VbglR3ClipboardListHdrReadRecvReq(pCmdCtx, &hList, &fFlags);
2155 if (RT_SUCCESS(rc))
2156 {
2157 PSHCLTRANSFER pTransfer = ShClTransferCtxGetTransfer(pTransferCtx,
2158 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->idContext));
2159 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND);
2160
2161 SHCLLISTHDR hdrList;
2162 rc = ShClTransferListGetHeader(pTransfer, hList, &hdrList);
2163 if (RT_SUCCESS(rc))
2164 {
2165 rc = VbglR3ClipboardListHdrWrite(pCmdCtx, hList, &hdrList);
2166
2167 ShClTransferListHdrDestroy(&hdrList);
2168 }
2169 }
2170
2171 break;
2172 }
2173
2174 case VBOX_SHCL_HOST_MSG_TRANSFER_LIST_ENTRY_READ:
2175 {
2176 LogFlowFunc(("VBOX_SHCL_HOST_MSG_TRANSFER_LIST_ENTRY_READ\n"));
2177
2178 SHCLLISTENTRY entryList;
2179 rc = ShClTransferListEntryInit(&entryList);
2180 if (RT_SUCCESS(rc))
2181 {
2182 SHCLLISTHANDLE hList;
2183 uint32_t fInfo;
2184 rc = VbglR3ClipboardListEntryReadRecvReq(pCmdCtx, &hList, &fInfo);
2185 if (RT_SUCCESS(rc))
2186 {
2187 PSHCLTRANSFER pTransfer = ShClTransferCtxGetTransfer(pTransferCtx,
2188 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->idContext));
2189 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND);
2190
2191 rc = ShClTransferListRead(pTransfer, hList, &entryList);
2192 if (RT_SUCCESS(rc))
2193 {
2194 PSHCLFSOBJINFO pObjInfo = (PSHCLFSOBJINFO)entryList.pvInfo;
2195 Assert(entryList.cbInfo == sizeof(SHCLFSOBJINFO));
2196
2197 RT_NOREF(pObjInfo);
2198
2199 LogFlowFunc(("\t%s (%RU64 bytes)\n", entryList.pszName, pObjInfo->cbObject));
2200
2201 rc = VbglR3ClipboardListEntryWrite(pCmdCtx, hList, &entryList);
2202 }
2203 }
2204
2205 ShClTransferListEntryDestroy(&entryList);
2206 }
2207
2208 break;
2209 }
2210
2211 case VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_OPEN:
2212 {
2213 SHCLOBJOPENCREATEPARMS openParms;
2214 rc = ShClTransferObjOpenParmsInit(&openParms);
2215 if (RT_SUCCESS(rc))
2216 {
2217 rc = VbglR3ClipboardObjOpenRecv(pCmdCtx, &openParms);
2218 if (RT_SUCCESS(rc))
2219 {
2220 PSHCLTRANSFER pTransfer = ShClTransferCtxGetTransfer(pTransferCtx,
2221 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->idContext));
2222 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND);
2223
2224 SHCLOBJHANDLE hObj;
2225 rc = ShClTransferObjOpen(pTransfer, &openParms, &hObj);
2226
2227 /* Reply in any case. */
2228 int rc2 = VbglR3ClipboardObjOpenReply(pCmdCtx, rc, hObj);
2229 AssertRC(rc2);
2230 }
2231
2232 ShClTransferObjOpenParmsDestroy(&openParms);
2233 }
2234
2235 break;
2236 }
2237
2238 case VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_CLOSE:
2239 {
2240 SHCLOBJHANDLE hObj;
2241 rc = VbglR3ClipboardObjCloseRecv(pCmdCtx, &hObj);
2242 if (RT_SUCCESS(rc))
2243 {
2244 PSHCLTRANSFER pTransfer = ShClTransferCtxGetTransfer(pTransferCtx,
2245 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->idContext));
2246 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND);
2247
2248 rc = ShClTransferObjClose(pTransfer, hObj);
2249
2250 /* Reply in any case. */
2251 int rc2 = VbglR3ClipboardObjCloseReply(pCmdCtx, rc, hObj);
2252 AssertRC(rc2);
2253 }
2254
2255 break;
2256 }
2257
2258 case VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_READ:
2259 {
2260 SHCLOBJHANDLE hObj;
2261 uint32_t cbBuf;
2262 uint32_t fFlags;
2263 rc = VbglR3ClipboardObjReadRecv(pCmdCtx, &hObj, &cbBuf, &fFlags);
2264 if (RT_SUCCESS(rc))
2265 {
2266 PSHCLTRANSFER pTransfer = ShClTransferCtxGetTransfer(pTransferCtx,
2267 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->idContext));
2268 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND);
2269
2270 AssertBreakStmt(pCmdCtx->cbChunkSize, rc = VERR_INVALID_PARAMETER);
2271
2272 const uint32_t cbToRead = RT_MIN(cbBuf, pCmdCtx->cbChunkSize);
2273
2274 LogFlowFunc(("hObj=%RU64, cbBuf=%RU32, fFlags=0x%x -> cbChunkSize=%RU32, cbToRead=%RU32\n",
2275 hObj, cbBuf, fFlags, pCmdCtx->cbChunkSize, cbToRead));
2276
2277 void *pvBuf = RTMemAlloc(cbToRead);
2278 if (pvBuf)
2279 {
2280 uint32_t cbRead;
2281 rc = ShClTransferObjRead(pTransfer, hObj, pvBuf, cbToRead, &cbRead, fFlags);
2282 if (RT_SUCCESS(rc))
2283 rc = VbglR3ClipboardObjWriteSend(pCmdCtx, hObj, pvBuf, cbRead, NULL /* pcbWritten */);
2284
2285 RTMemFree(pvBuf);
2286 }
2287 else
2288 rc = VERR_NO_MEMORY;
2289 }
2290
2291 break;
2292 }
2293
2294 default:
2295 {
2296 rc = VbglR3ClipboardEventGetNext(idMsg, cParms, pCmdCtx, pEvent);
2297 if (RT_FAILURE(rc))
2298 fErrorSent = true;
2299 break;
2300 }
2301 }
2302
2303 if ( !fErrorSent
2304 && RT_FAILURE(rc))
2305 {
2306 /* Report error back to the host. */
2307 int rc2 = VbglR3ClipboardWriteError(pCmdCtx->idClient, rc);
2308 AssertRC(rc2);
2309 }
2310 }
2311 else
2312 {
2313 /*
2314 * This builds on what we did in VbglR3ClipboardMsgPeekWait, so
2315 * !HACK ALERT! cParms is the format flag or flags.
2316 */
2317 rc = VINF_SUCCESS;
2318 switch (idMsg)
2319 {
2320 case VBOX_SHCL_HOST_MSG_FORMATS_REPORT:
2321 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_REPORT_FORMATS;
2322 pEvent->u.fReportedFormats = cParms;
2323 break;
2324
2325 case VBOX_SHCL_HOST_MSG_READ_DATA:
2326 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_READ_DATA;
2327 pEvent->u.fReadData = cParms;
2328 break;
2329
2330 case VBOX_SHCL_HOST_MSG_QUIT:
2331 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_QUIT;
2332 break;
2333
2334 default:
2335 AssertMsgFailed(("%u (%#x)\n", idMsg, idMsg));
2336 rc = VERR_NOT_SUPPORTED;
2337 break;
2338 }
2339 }
2340
2341 LogFlowFuncLeaveRC(rc);
2342 return rc;
2343}
2344
2345#endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
2346
2347VBGLR3DECL(int) VbglR3ClipboardEventGetNext(uint32_t idMsg, uint32_t cParms, PVBGLR3SHCLCMDCTX pCtx, PVBGLR3CLIPBOARDEVENT pEvent)
2348{
2349 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2350 AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
2351
2352 RT_NOREF(cParms);
2353
2354 int rc;
2355 if (!pCtx->fUseLegacyProtocol)
2356 {
2357 LogFunc(("Handling idMsg=%RU32 (%s)\n", idMsg, ShClHostMsgToStr(idMsg)));
2358 switch (idMsg)
2359 {
2360 case VBOX_SHCL_HOST_MSG_FORMATS_REPORT:
2361 {
2362 rc = vbglR3ClipboardFormatsReportRecv(pCtx, &pEvent->u.fReportedFormats);
2363 if (RT_SUCCESS(rc))
2364 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_REPORT_FORMATS;
2365 break;
2366 }
2367
2368 case VBOX_SHCL_HOST_MSG_READ_DATA_CID:
2369 {
2370 rc = vbglR3ClipboardFetchReadDataCid(pCtx, &pEvent->u.fReadData);
2371 if (RT_SUCCESS(rc))
2372 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_READ_DATA;
2373 break;
2374 }
2375
2376 case VBOX_SHCL_HOST_MSG_READ_DATA:
2377 {
2378 rc = vbglR3ClipboardFetchReadData(pCtx, &pEvent->u.fReadData);
2379 if (RT_SUCCESS(rc))
2380 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_READ_DATA;
2381 break;
2382 }
2383
2384 case VBOX_SHCL_HOST_MSG_QUIT:
2385 {
2386 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_QUIT;
2387 rc = VINF_SUCCESS;
2388 break;
2389 }
2390
2391 default:
2392 {
2393 /** @todo r=bird: BUGBUG - need a skip command here! */
2394 rc = VERR_NOT_SUPPORTED;
2395 break;
2396 }
2397 }
2398
2399 if (RT_SUCCESS(rc))
2400 {
2401 /* Copy over our command context to the event. */
2402 pEvent->cmdCtx = *pCtx;
2403 }
2404 else
2405 {
2406 /* Report error back to the host. */
2407 int rc2 = VbglR3ClipboardWriteError(pCtx->idClient, rc);
2408 AssertRC(rc2);
2409 }
2410 }
2411 else
2412 {
2413 /*
2414 * This builds on what we did in VbglR3ClipboardMsgPeekWait, so
2415 * !HACK ALERT! cParms is the format flag or flags.
2416 */
2417 rc = VINF_SUCCESS;
2418 switch (idMsg)
2419 {
2420 case VBOX_SHCL_HOST_MSG_FORMATS_REPORT:
2421 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_REPORT_FORMATS;
2422 pEvent->u.fReportedFormats = cParms;
2423 break;
2424
2425 case VBOX_SHCL_HOST_MSG_READ_DATA:
2426 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_READ_DATA;
2427 pEvent->u.fReadData = cParms;
2428 break;
2429
2430 case VBOX_SHCL_HOST_MSG_QUIT:
2431 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_QUIT;
2432 break;
2433
2434 default:
2435 AssertMsgFailed(("%u (%#x)\n", idMsg, idMsg));
2436 rc = VERR_NOT_SUPPORTED;
2437 break;
2438 }
2439 pEvent->cmdCtx = *pCtx;
2440 }
2441
2442 LogFlowFuncLeaveRC(rc);
2443 return rc;
2444}
2445
2446/**
2447 * Frees (destroys) a formerly allocated Shared Clipboard event.
2448 *
2449 * @returns IPRT status code.
2450 * @param pEvent Event to free (destroy).
2451 */
2452VBGLR3DECL(void) VbglR3ClipboardEventFree(PVBGLR3CLIPBOARDEVENT pEvent)
2453{
2454 if (!pEvent)
2455 return;
2456
2457 /* Some messages require additional cleanup. */
2458 switch (pEvent->enmType)
2459 {
2460 default:
2461 break;
2462 }
2463
2464 RTMemFree(pEvent);
2465 pEvent = NULL;
2466}
2467
2468/**
2469 * Reports (advertises) guest clipboard formats to the host.
2470 *
2471 * Legacy function, do not use anymore.
2472 *
2473 * @returns VBox status code.
2474 * @param idClient The client id returned by VbglR3ClipboardConnect().
2475 * @param fFormats The formats to report.
2476 */
2477VBGLR3DECL(int) VbglR3ClipboardReportFormats(HGCMCLIENTID idClient, uint32_t fFormats)
2478{
2479 struct
2480 {
2481 VBGLIOCHGCMCALL Hdr;
2482 VBoxShClParmReportFormats Parms;
2483 } Msg;
2484
2485 VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, VBOX_SHCL_GUEST_FN_REPORT_FORMATS, VBOX_SHCL_CPARMS_REPORT_FORMATS);
2486 VbglHGCMParmUInt32Set(&Msg.Parms.f32Formats, fFormats);
2487
2488 int rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
2489
2490 LogFlowFuncLeaveRC(rc);
2491 return rc;
2492}
2493
2494/**
2495 * Sends guest clipboard data to the host.
2496 *
2497 * Legacy function kept for compatibility, do not use anymore.
2498 *
2499 * This is usually called in reply to a VBOX_SHCL_HOST_MSG_READ_DATA message
2500 * from the host.
2501 *
2502 * @returns VBox status code.
2503 * @param idClient The client id returned by VbglR3ClipboardConnect().
2504 * @param fFormat The format of the data.
2505 * @param pv The data.
2506 * @param cb The size of the data.
2507 */
2508VBGLR3DECL(int) VbglR3ClipboardWriteData(HGCMCLIENTID idClient, uint32_t fFormat, void *pv, uint32_t cb)
2509{
2510 LogFlowFuncEnter();
2511
2512 struct
2513 {
2514 VBGLIOCHGCMCALL Hdr;
2515 VBoxShClParmDataWriteOld Parms;
2516 } Msg;
2517
2518 VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, VBOX_SHCL_GUEST_FN_DATA_WRITE, VBOX_SHCL_CPARMS_DATA_WRITE_OLD);
2519 VbglHGCMParmUInt32Set(&Msg.Parms.f32Format, fFormat);
2520 VbglHGCMParmPtrSet(&Msg.Parms.pData, pv, cb);
2521
2522 int rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
2523
2524 LogFlowFuncLeaveRC(rc);
2525 return rc;
2526}
2527
2528/**
2529 * Sends guest clipboard data to the host.
2530 *
2531 * This is usually called in reply to a VBOX_SHCL_HOST_MSG_READ_DATA message
2532 * from the host.
2533 *
2534 * @returns VBox status code.
2535 * @param pCtx The command context returned by VbglR3ClipboardConnectEx().
2536 * @param uFormat Clipboard format to send.
2537 * @param pvData Pointer to data to send.
2538 * @param cbData Size (in bytes) of data to send.
2539 */
2540VBGLR3DECL(int) VbglR3ClipboardWriteDataEx(PVBGLR3SHCLCMDCTX pCtx, SHCLFORMAT uFormat, void *pvData, uint32_t cbData)
2541{
2542 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2543 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
2544
2545 int rc;
2546
2547 LogFlowFuncEnter();
2548
2549 if (pCtx->fUseLegacyProtocol)
2550 {
2551 rc = VbglR3ClipboardWriteData(pCtx->idClient, uFormat, pvData, cbData);
2552 }
2553 else
2554 {
2555 struct
2556 {
2557 VBGLIOCHGCMCALL Hdr;
2558 VBoxShClParmDataWrite Parms;
2559 } Msg;
2560
2561 VBGL_HGCM_HDR_INIT(&Msg.Hdr, pCtx->idClient, VBOX_SHCL_GUEST_FN_DATA_WRITE, VBOX_SHCL_CPARMS_DATA_WRITE);
2562 Msg.Parms.id64Context.SetUInt64(pCtx->idContext);
2563 Msg.Parms.f32Format.SetUInt32(uFormat);
2564 Msg.Parms.pData.SetPtr(pvData, cbData);
2565
2566 LogFlowFunc(("CID=%RU32\n", pCtx->idContext));
2567
2568 rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
2569 }
2570
2571 LogFlowFuncLeaveRC(rc);
2572 return rc;
2573}
2574
2575/**
2576 * Writes an error to the host.
2577 *
2578 * @returns IPRT status code.
2579 * @param idClient The client id returned by VbglR3ClipboardConnect().
2580 * @param rcErr Error (IPRT-style) to send.
2581 */
2582VBGLR3DECL(int) VbglR3ClipboardWriteError(HGCMCLIENTID idClient, int rcErr)
2583{
2584 AssertReturn(idClient, VERR_INVALID_PARAMETER);
2585
2586 VBoxShClWriteErrorMsg Msg;
2587 RT_ZERO(Msg);
2588
2589 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHCL_GUEST_FN_ERROR, VBOX_SHCL_CPARMS_ERROR);
2590
2591 /** @todo Context ID not used yet. */
2592 Msg.uContext.SetUInt64(0);
2593 Msg.rc.SetUInt32((uint32_t)rcErr); /* uint32_t vs. int. */
2594
2595 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
2596
2597 if (RT_FAILURE(rc))
2598 LogFlowFunc(("Sending error %Rrc failed with rc=%Rrc\n", rcErr, rc));
2599 if (rc == VERR_NOT_SUPPORTED)
2600 rc = VINF_SUCCESS;
2601
2602 if (RT_FAILURE(rc))
2603 LogRel(("Shared Clipboard: Reporting error %Rrc to the host failed with %Rrc\n", rcErr, rc));
2604
2605 LogFlowFuncLeaveRC(rc);
2606 return rc;
2607}
2608
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