VirtualBox

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

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

Shared Clipboard/VbglR3: Be a bit more (user friendly) verbose in terms of why we couldn't connect to the Shared Clipboard host service.

  • Property svn:eol-style set to native
  • Property svn:keyword set to Id
  • Property svn:keywords set to Author Date Id Revision
File size: 90.5 KB
Line 
1/* $Id: VBoxGuestR3LibClipboard.cpp 84733 2020-06-09 07:17:47Z 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.cbPayload.SetUInt32(0);
820 Msg.pvPayload.SetPtr(NULL, 0);
821
822 Msg.u.TransferStatus.enmStatus.SetUInt32((uint32_t)uStatus);
823
824 LogFlowFunc(("%s\n", ShClTransferStatusToStr(uStatus)));
825
826 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
827
828 LogFlowFuncLeaveRC(rc);
829 return rc;
830}
831
832/**
833 * Receives a host request to read a root list header from the guest.
834 *
835 * @returns VBox status code.
836 * @param pCtx Shared Clipboard command context to use for the connection.
837 * @param pfRoots Where to store the root list header flags to use, requested by the host.
838 */
839VBGLR3DECL(int) VbglR3ClipboardRootListHdrReadReq(PVBGLR3SHCLCMDCTX pCtx, uint32_t *pfRoots)
840{
841 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
842 AssertPtrReturn(pfRoots, VERR_INVALID_POINTER);
843
844 VBoxShClRootListReadReqMsg Msg;
845 RT_ZERO(Msg);
846
847 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
848 VBOX_SHCL_GUEST_FN_MSG_GET, VBOX_SHCL_CPARMS_ROOT_LIST_HDR_READ_REQ);
849
850 Msg.ReqParms.uContext.SetUInt64(VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_HDR_READ);
851 Msg.ReqParms.fRoots.SetUInt32(0);
852
853 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
854 if (RT_SUCCESS(rc))
855 {
856 rc = Msg.ReqParms.uContext.GetUInt64(&pCtx->idContext); AssertRC(rc);
857 if (RT_SUCCESS(rc))
858 rc = Msg.ReqParms.fRoots.GetUInt32(pfRoots); AssertRC(rc);
859 }
860
861 LogFlowFuncLeaveRC(rc);
862 return rc;
863}
864
865/**
866 * Replies to a root list header request.
867 *
868 * @returns VBox status code.
869 * @param pCtx Shared Clipboard command context to use for the connection.
870 * @param pRootListHdr Root lsit header to reply to the host.
871 */
872VBGLR3DECL(int) VbglR3ClipboardRootListHdrReadReply(PVBGLR3SHCLCMDCTX pCtx, PSHCLROOTLISTHDR pRootListHdr)
873{
874 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
875 AssertPtrReturn(pRootListHdr, VERR_INVALID_POINTER);
876
877 VBoxShClRootListHdrMsg Msg;
878 RT_ZERO(Msg);
879
880 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
881 VBOX_SHCL_GUEST_FN_ROOT_LIST_HDR_WRITE, VBOX_SHCL_CPARMS_ROOT_LIST_HDR_WRITE);
882
883 Msg.ReqParms.uContext.SetUInt64(pCtx->idContext);
884 Msg.ReqParms.fRoots.SetUInt32(pRootListHdr->fRoots);
885
886 Msg.cRoots.SetUInt32(pRootListHdr->cRoots);
887
888 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
889
890 LogFlowFuncLeaveRC(rc);
891 return rc;
892}
893
894/**
895 * Receives a host request to read a root list entry from the guest.
896 *
897 * @returns VBox status code.
898 * @param pCtx Shared Clipboard command context to use for the connection.
899 * @param puIndex Where to return the index of the root list entry the host wants to read.
900 * @param pfInfo Where to return the read flags the host wants to use.
901 */
902VBGLR3DECL(int) VbglR3ClipboardRootListEntryReadReq(PVBGLR3SHCLCMDCTX pCtx, uint32_t *puIndex, uint32_t *pfInfo)
903{
904 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
905 AssertPtrReturn(puIndex, VERR_INVALID_POINTER);
906 AssertPtrReturn(pfInfo, VERR_INVALID_POINTER);
907
908 VBoxShClRootListEntryReadReqMsg Msg;
909 RT_ZERO(Msg);
910
911 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
912 VBOX_SHCL_GUEST_FN_MSG_GET, VBOX_SHCL_CPARMS_ROOT_LIST_ENTRY_READ_REQ);
913
914 Msg.Parms.uContext.SetUInt64(VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_ENTRY_READ);
915 Msg.Parms.fInfo.SetUInt32(0);
916 Msg.Parms.uIndex.SetUInt32(0);
917
918 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
919 if (RT_SUCCESS(rc))
920 {
921 rc = Msg.Parms.uContext.GetUInt64(&pCtx->idContext); AssertRC(rc);
922 if (RT_SUCCESS(rc))
923 rc = Msg.Parms.fInfo.GetUInt32(pfInfo); AssertRC(rc);
924 if (RT_SUCCESS(rc))
925 rc = Msg.Parms.uIndex.GetUInt32(puIndex); AssertRC(rc);
926 }
927
928 LogFlowFuncLeaveRC(rc);
929 return rc;
930}
931
932/**
933 * Replies to a root list entry read request from the host.
934 *
935 * @returns VBox status code.
936 * @param pCtx Shared Clipboard command context to use for the connection.
937 * @param uIndex Index of root list entry to reply.
938 * @param pEntry Actual root list entry to reply.
939 */
940VBGLR3DECL(int) VbglR3ClipboardRootListEntryReadReply(PVBGLR3SHCLCMDCTX pCtx, uint32_t uIndex, PSHCLROOTLISTENTRY pEntry)
941{
942 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
943 AssertPtrReturn(pEntry, VERR_INVALID_POINTER);
944
945 VBoxShClRootListEntryMsg Msg;
946 RT_ZERO(Msg);
947
948 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
949 VBOX_SHCL_GUEST_FN_ROOT_LIST_ENTRY_WRITE, VBOX_SHCL_CPARMS_ROOT_LIST_ENTRY_WRITE);
950
951 Msg.Parms.uContext.SetUInt64(pCtx->idContext);
952 Msg.Parms.fInfo.SetUInt32(0);
953 Msg.Parms.uIndex.SetUInt32(uIndex);
954
955 Msg.szName.SetPtr(pEntry->pszName, pEntry->cbName);
956 Msg.cbInfo.SetUInt32(pEntry->cbInfo);
957 Msg.pvInfo.SetPtr(pEntry->pvInfo, pEntry->cbInfo);
958
959 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
960
961 LogFlowFuncLeaveRC(rc);
962 return rc;
963}
964
965/**
966 * Sends a request to open a list handle to the host.
967 *
968 * @returns VBox status code.
969 * @param pCtx Shared Clipboard command context to use for the connection.
970 * @param pOpenParms List open parameters to use for the open request.
971 * @param phList Where to return the list handle received from the host.
972 */
973VBGLR3DECL(int) VbglR3ClipboardListOpenSend(PVBGLR3SHCLCMDCTX pCtx, PSHCLLISTOPENPARMS pOpenParms,
974 PSHCLLISTHANDLE phList)
975{
976 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
977 AssertPtrReturn(pOpenParms, VERR_INVALID_POINTER);
978 AssertPtrReturn(phList, VERR_INVALID_POINTER);
979
980 VBoxShClListOpenMsg Msg;
981 RT_ZERO(Msg);
982
983 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
984 VBOX_SHCL_GUEST_FN_LIST_OPEN, VBOX_SHCL_CPARMS_LIST_OPEN);
985
986 Msg.uContext.SetUInt64(pCtx->idContext);
987 Msg.fList.SetUInt32(0);
988 Msg.cbFilter.SetUInt32(pOpenParms->cbFilter);
989 Msg.pvFilter.SetPtr(pOpenParms->pszFilter, pOpenParms->cbFilter);
990 Msg.cbPath.SetUInt32(pOpenParms->cbPath);
991 Msg.pvPath.SetPtr(pOpenParms->pszPath, pOpenParms->cbPath);
992 Msg.uHandle.SetUInt64(0);
993
994 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
995 if (RT_SUCCESS(rc))
996 {
997 rc = Msg.uHandle.GetUInt64(phList); AssertRC(rc);
998 }
999
1000 LogFlowFuncLeaveRC(rc);
1001 return rc;
1002}
1003
1004/**
1005 * Receives a host request to open a list handle on the guest.
1006 *
1007 * @returns VBox status code.
1008 * @param pCtx Shared Clipboard command context to use for the connection.
1009 * @param pOpenParms Where to store the open parameters the host wants to use for opening the list handle.
1010 */
1011VBGLR3DECL(int) VbglR3ClipboardListOpenRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLLISTOPENPARMS pOpenParms)
1012{
1013 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1014 AssertPtrReturn(pOpenParms, VERR_INVALID_POINTER);
1015
1016 VBoxShClListOpenMsg Msg;
1017 RT_ZERO(Msg);
1018
1019 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1020 VBOX_SHCL_GUEST_FN_MSG_GET, VBOX_SHCL_CPARMS_LIST_OPEN);
1021
1022 Msg.uContext.SetUInt64(VBOX_SHCL_HOST_MSG_TRANSFER_LIST_OPEN);
1023 Msg.fList.SetUInt32(0);
1024 Msg.cbPath.SetUInt32(pOpenParms->cbPath);
1025 Msg.pvPath.SetPtr(pOpenParms->pszPath, pOpenParms->cbPath);
1026 Msg.cbFilter.SetUInt32(pOpenParms->cbFilter);
1027 Msg.pvFilter.SetPtr(pOpenParms->pszFilter, pOpenParms->cbFilter);
1028 Msg.uHandle.SetUInt64(0);
1029
1030 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1031 if (RT_SUCCESS(rc))
1032 {
1033 rc = Msg.uContext.GetUInt64(&pCtx->idContext);
1034 if (RT_SUCCESS(rc))
1035 rc = Msg.fList.GetUInt32(&pOpenParms->fList);
1036 if (RT_SUCCESS(rc))
1037 rc = Msg.cbFilter.GetUInt32(&pOpenParms->cbFilter);
1038 if (RT_SUCCESS(rc))
1039 rc = Msg.cbPath.GetUInt32(&pOpenParms->cbPath);
1040 }
1041
1042 LogFlowFuncLeaveRC(rc);
1043 return rc;
1044}
1045
1046/**
1047 * Replies to a list open request from the host.
1048 *
1049 * @returns VBox status code.
1050 * @param pCtx Shared Clipboard command context to use for the connection.
1051 * @param rcReply Return code to reply to the host.
1052 * @param hList List handle of (guest) list to reply to the host.
1053 */
1054VBGLR3DECL(int) VbglR3ClipboardListOpenReply(PVBGLR3SHCLCMDCTX pCtx, int rcReply, SHCLLISTHANDLE hList)
1055{
1056 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1057
1058 VBoxShClReplyMsg Msg;
1059 RT_ZERO(Msg);
1060
1061 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1062 VBOX_SHCL_GUEST_FN_REPLY, VBOX_SHCL_CPARMS_REPLY_MIN + 1);
1063
1064 Msg.uContext.SetUInt64(pCtx->idContext);
1065 Msg.enmType.SetUInt32(VBOX_SHCL_REPLYMSGTYPE_LIST_OPEN);
1066 Msg.rc.SetUInt32((uint32_t)rcReply); /** int vs. uint32_t */
1067 Msg.cbPayload.SetUInt32(0);
1068 Msg.pvPayload.SetPtr(NULL, 0);
1069
1070 Msg.u.ListOpen.uHandle.SetUInt64(hList);
1071
1072 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1073
1074 LogFlowFuncLeaveRC(rc);
1075 return rc;
1076}
1077
1078/**
1079 * Receives a host request to close a list handle on the guest.
1080 *
1081 * @returns VBox status code.
1082 * @param pCtx Shared Clipboard command context to use for the connection.
1083 * @param phList Where to store the list handle to close, received from the host.
1084 */
1085VBGLR3DECL(int) VbglR3ClipboardListCloseRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLLISTHANDLE phList)
1086{
1087 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1088 AssertPtrReturn(phList, VERR_INVALID_POINTER);
1089
1090 VBoxShClListCloseMsg Msg;
1091 RT_ZERO(Msg);
1092
1093 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1094 VBOX_SHCL_GUEST_FN_MSG_GET, VBOX_SHCL_CPARMS_LIST_CLOSE);
1095
1096 Msg.uContext.SetUInt64(VBOX_SHCL_HOST_MSG_TRANSFER_LIST_CLOSE);
1097 Msg.uHandle.SetUInt64(0);
1098
1099 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1100 if (RT_SUCCESS(rc))
1101 {
1102 rc = Msg.uContext.GetUInt64(&pCtx->idContext);
1103 if (RT_SUCCESS(rc))
1104 rc = Msg.uHandle.GetUInt64(phList); AssertRC(rc);
1105 }
1106
1107 LogFlowFuncLeaveRC(rc);
1108 return rc;
1109}
1110
1111/**
1112 * Replies to a list handle close request from the host.
1113 *
1114 * @returns VBox status code.
1115 * @param pCtx Shared Clipboard command context to use for the connection.
1116 * @param rcReply Return code to reply to the host.
1117 * @param hList List handle the send the close reply for.
1118 */
1119VBGLR3DECL(int) VbglR3ClipboardListCloseReply(PVBGLR3SHCLCMDCTX pCtx, int rcReply, SHCLLISTHANDLE hList)
1120{
1121 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1122
1123 VBoxShClReplyMsg Msg;
1124 RT_ZERO(Msg);
1125
1126 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1127 VBOX_SHCL_GUEST_FN_REPLY, VBOX_SHCL_CPARMS_REPLY_MIN + 1);
1128
1129 Msg.uContext.SetUInt64(pCtx->idContext);
1130 Msg.enmType.SetUInt32(VBOX_SHCL_REPLYMSGTYPE_LIST_CLOSE);
1131 Msg.rc.SetUInt32((uint32_t)rcReply); /** int vs. uint32_t */
1132 Msg.cbPayload.SetUInt32(0);
1133 Msg.pvPayload.SetPtr(NULL, 0);
1134
1135 Msg.u.ListOpen.uHandle.SetUInt64(hList);
1136
1137 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1138
1139 LogFlowFuncLeaveRC(rc);
1140 return rc;
1141}
1142
1143/**
1144 * Sends a request to close a list handle to the host.
1145 *
1146 * @returns VBox status code.
1147 * @param pCtx Shared Clipboard command context to use for the connection.
1148 * @param hList List handle to request for closing on the host.
1149 */
1150VBGLR3DECL(int) VbglR3ClipboardListCloseSend(PVBGLR3SHCLCMDCTX pCtx, SHCLLISTHANDLE hList)
1151{
1152 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1153
1154 VBoxShClListCloseMsg Msg;
1155 RT_ZERO(Msg);
1156
1157 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1158 VBOX_SHCL_GUEST_FN_LIST_CLOSE, VBOX_SHCL_CPARMS_LIST_CLOSE);
1159
1160 Msg.uContext.SetUInt64(pCtx->idContext);
1161 Msg.uHandle.SetUInt64(hList);
1162
1163 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1164
1165 LogFlowFuncLeaveRC(rc);
1166 return rc;
1167}
1168
1169/**
1170 * Sends a request to read a list header to the host.
1171 *
1172 * @returns VBox status code.
1173 * @param pCtx Shared Clipboard command context to use for the connection.
1174 * @param hList List handle to read list header for.
1175 * @param fFlags List header read flags to use.
1176 * @param pListHdr Where to return the list header received from the host.
1177 */
1178VBGLR3DECL(int) VbglR3ClipboardListHdrRead(PVBGLR3SHCLCMDCTX pCtx, SHCLLISTHANDLE hList, uint32_t fFlags,
1179 PSHCLLISTHDR pListHdr)
1180{
1181 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1182 AssertPtrReturn(pListHdr, VERR_INVALID_POINTER);
1183
1184 VBoxShClListHdrMsg Msg;
1185 RT_ZERO(Msg);
1186
1187 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1188 VBOX_SHCL_GUEST_FN_LIST_HDR_READ, VBOX_SHCL_CPARMS_LIST_HDR);
1189
1190 Msg.ReqParms.uContext.SetUInt64(pCtx->idContext);
1191 Msg.ReqParms.uHandle.SetUInt64(hList);
1192 Msg.ReqParms.fFlags.SetUInt32(fFlags);
1193
1194 Msg.fFeatures.SetUInt32(0);
1195 Msg.cbTotalSize.SetUInt32(0);
1196 Msg.cTotalObjects.SetUInt64(0);
1197 Msg.cbTotalSize.SetUInt64(0);
1198
1199 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1200 if (RT_SUCCESS(rc))
1201 {
1202 rc = Msg.fFeatures.GetUInt32(&pListHdr->fFeatures);
1203 if (RT_SUCCESS(rc))
1204 rc = Msg.cTotalObjects.GetUInt64(&pListHdr->cTotalObjects);
1205 if (RT_SUCCESS(rc))
1206 rc = Msg.cbTotalSize.GetUInt64(&pListHdr->cbTotalSize);
1207 }
1208
1209 LogFlowFuncLeaveRC(rc);
1210 return rc;
1211}
1212
1213/**
1214 * Receives a host request to read a list header on the guest.
1215 *
1216 * @returns VBox status code.
1217 * @param pCtx Shared Clipboard command context to use for the connection.
1218 * @param phList Where to return the list handle to read list header for.
1219 * @param pfFlags Where to return the List header read flags to use.
1220 */
1221VBGLR3DECL(int) VbglR3ClipboardListHdrReadRecvReq(PVBGLR3SHCLCMDCTX pCtx, PSHCLLISTHANDLE phList, uint32_t *pfFlags)
1222{
1223 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1224 AssertPtrReturn(phList, VERR_INVALID_POINTER);
1225 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
1226
1227 VBoxShClListHdrReadReqMsg Msg;
1228 RT_ZERO(Msg);
1229
1230 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1231 VBOX_SHCL_GUEST_FN_MSG_GET, VBOX_SHCL_CPARMS_LIST_HDR_READ_REQ);
1232
1233 Msg.ReqParms.uContext.SetUInt64(VBOX_SHCL_HOST_MSG_TRANSFER_LIST_HDR_READ);
1234 Msg.ReqParms.uHandle.SetUInt64(0);
1235 Msg.ReqParms.fFlags.SetUInt32(0);
1236
1237 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1238 if (RT_SUCCESS(rc))
1239 {
1240 rc = Msg.ReqParms.uContext.GetUInt64(&pCtx->idContext);
1241 if (RT_SUCCESS(rc))
1242 rc = Msg.ReqParms.uHandle.GetUInt64(phList);
1243 if (RT_SUCCESS(rc))
1244 rc = Msg.ReqParms.fFlags.GetUInt32(pfFlags);
1245 }
1246
1247 LogFlowFuncLeaveRC(rc);
1248 return rc;
1249}
1250
1251/**
1252 * Sends (writes) a list header to the host.
1253 *
1254 * @returns VBox status code.
1255 * @param pCtx Shared Clipboard command context to use for the connection.
1256 * @param hList List handle to write list header for.
1257 * @param pListHdr List header to write.
1258 */
1259VBGLR3DECL(int) VbglR3ClipboardListHdrWrite(PVBGLR3SHCLCMDCTX pCtx, SHCLLISTHANDLE hList,
1260 PSHCLLISTHDR pListHdr)
1261{
1262 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1263 AssertPtrReturn(pListHdr, VERR_INVALID_POINTER);
1264
1265 VBoxShClListHdrMsg Msg;
1266 RT_ZERO(Msg);
1267
1268 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1269 VBOX_SHCL_GUEST_FN_LIST_HDR_WRITE, VBOX_SHCL_CPARMS_LIST_HDR);
1270
1271 Msg.ReqParms.uContext.SetUInt64(pCtx->idContext);
1272 Msg.ReqParms.uHandle.SetUInt64(hList);
1273 Msg.ReqParms.fFlags.SetUInt32(0);
1274
1275 Msg.fFeatures.SetUInt32(0);
1276 Msg.cbTotalSize.SetUInt32(pListHdr->fFeatures);
1277 Msg.cTotalObjects.SetUInt64(pListHdr->cTotalObjects);
1278 Msg.cbTotalSize.SetUInt64(pListHdr->cbTotalSize);
1279
1280 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1281
1282 LogFlowFuncLeaveRC(rc);
1283 return rc;
1284}
1285
1286/**
1287 * Sends a request to read a list entry from the host.
1288 *
1289 * @returns VBox status code.
1290 * @param pCtx Shared Clipboard command context to use for the connection.
1291 * @param hList List handle to request to read a list entry for.
1292 * @param pListEntry Where to return the list entry read from the host.
1293 */
1294VBGLR3DECL(int) VbglR3ClipboardListEntryRead(PVBGLR3SHCLCMDCTX pCtx, SHCLLISTHANDLE hList,
1295 PSHCLLISTENTRY pListEntry)
1296{
1297 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1298 AssertPtrReturn(pListEntry, VERR_INVALID_POINTER);
1299
1300 VBoxShClListEntryMsg Msg;
1301 RT_ZERO(Msg);
1302
1303 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1304 VBOX_SHCL_GUEST_FN_LIST_ENTRY_READ, VBOX_SHCL_CPARMS_LIST_ENTRY);
1305
1306 Msg.ReqParms.uContext.SetUInt64(pCtx->idContext);
1307 Msg.ReqParms.uHandle.SetUInt64(hList);
1308 Msg.ReqParms.fInfo.SetUInt32(0);
1309
1310 Msg.szName.SetPtr(pListEntry->pszName, pListEntry->cbName);
1311 Msg.cbInfo.SetUInt32(pListEntry->cbInfo);
1312 Msg.pvInfo.SetPtr(pListEntry->pvInfo, pListEntry->cbInfo);
1313
1314 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1315 if (RT_SUCCESS(rc))
1316 {
1317 rc = Msg.cbInfo.GetUInt32(&pListEntry->cbInfo); AssertRC(rc);
1318 }
1319
1320 LogFlowFuncLeaveRC(rc);
1321 return rc;
1322}
1323
1324/**
1325 * Receives a host request to read a list entry from the guest.
1326 *
1327 * @returns VBox status code.
1328 * @param pCtx Shared Clipboard command context to use for the connection.
1329 * @param phList Where to return the list handle to read a list entry for.
1330 * @param pfInfo Where to return the list read flags.
1331 */
1332VBGLR3DECL(int) VbglR3ClipboardListEntryReadRecvReq(PVBGLR3SHCLCMDCTX pCtx, PSHCLLISTHANDLE phList, uint32_t *pfInfo)
1333{
1334 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1335 AssertPtrReturn(phList, VERR_INVALID_POINTER);
1336 AssertPtrReturn(pfInfo, VERR_INVALID_POINTER);
1337
1338 VBoxShClListEntryReadReqMsg Msg;
1339 RT_ZERO(Msg);
1340
1341 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1342 VBOX_SHCL_GUEST_FN_MSG_GET, VBOX_SHCL_CPARMS_LIST_ENTRY_READ);
1343
1344 Msg.ReqParms.uContext.SetUInt64(VBOX_SHCL_HOST_MSG_TRANSFER_LIST_ENTRY_READ);
1345 Msg.ReqParms.uHandle.SetUInt64(0);
1346 Msg.ReqParms.fInfo.SetUInt32(0);
1347
1348 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1349 if (RT_SUCCESS(rc))
1350 {
1351 rc = Msg.ReqParms.uContext.GetUInt64(&pCtx->idContext);
1352 if (RT_SUCCESS(rc))
1353 rc = Msg.ReqParms.uHandle.GetUInt64(phList); AssertRC(rc);
1354 if (RT_SUCCESS(rc))
1355 rc = Msg.ReqParms.fInfo.GetUInt32(pfInfo); AssertRC(rc);
1356 }
1357
1358 LogFlowFuncLeaveRC(rc);
1359 return rc;
1360}
1361
1362/**
1363 * Sends (writes) a list entry to the host.
1364 *
1365 * @returns VBox status code.
1366 * @param pCtx Shared Clipboard command context to use for the connection.
1367 * @param hList List handle to write a list etnry for.
1368 * @param pListEntry List entry to write.
1369 */
1370VBGLR3DECL(int) VbglR3ClipboardListEntryWrite(PVBGLR3SHCLCMDCTX pCtx, SHCLLISTHANDLE hList,
1371 PSHCLLISTENTRY pListEntry)
1372{
1373 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1374 AssertPtrReturn(pListEntry, VERR_INVALID_POINTER);
1375
1376 VBoxShClListEntryMsg Msg;
1377 RT_ZERO(Msg);
1378
1379 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1380 VBOX_SHCL_GUEST_FN_LIST_ENTRY_WRITE, VBOX_SHCL_CPARMS_LIST_ENTRY);
1381
1382 Msg.ReqParms.uContext.SetUInt64(pCtx->idContext);
1383 Msg.ReqParms.uHandle.SetUInt64(hList);
1384 Msg.ReqParms.fInfo.SetUInt32(pListEntry->fInfo);
1385
1386 Msg.szName.SetPtr(pListEntry->pszName, pListEntry->cbName);
1387 Msg.cbInfo.SetUInt32(pListEntry->cbInfo);
1388 Msg.pvInfo.SetPtr(pListEntry->pvInfo, pListEntry->cbInfo);
1389
1390 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1391
1392 LogFlowFuncLeaveRC(rc);
1393 return rc;
1394}
1395
1396/**
1397 * Receives a host request to open an object on the guest.
1398 *
1399 * @returns VBox status code.
1400 * @param pCtx Shared Clipboard command context to use for the connection.
1401 * @param pCreateParms Where to store the object open/create parameters received from the host.
1402 */
1403VBGLR3DECL(int) VbglR3ClipboardObjOpenRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLOBJOPENCREATEPARMS pCreateParms)
1404{
1405 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1406 AssertPtrReturn(pCreateParms, VERR_INVALID_POINTER);
1407
1408 VBoxShClObjOpenMsg Msg;
1409 RT_ZERO(Msg);
1410
1411 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1412 VBOX_SHCL_GUEST_FN_MSG_GET, VBOX_SHCL_CPARMS_OBJ_OPEN);
1413
1414 Msg.uContext.SetUInt64(VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_OPEN);
1415 Msg.uHandle.SetUInt64(0);
1416 Msg.cbPath.SetUInt32(pCreateParms->cbPath);
1417 Msg.szPath.SetPtr(pCreateParms->pszPath, pCreateParms->cbPath);
1418 Msg.fCreate.SetUInt32(0);
1419
1420 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1421 if (RT_SUCCESS(rc))
1422 {
1423 rc = Msg.uContext.GetUInt64(&pCtx->idContext);
1424 if (RT_SUCCESS(rc))
1425 rc = Msg.cbPath.GetUInt32(&pCreateParms->cbPath);
1426 if (RT_SUCCESS(rc))
1427 rc = Msg.fCreate.GetUInt32(&pCreateParms->fCreate);
1428 }
1429
1430 LogFlowFuncLeaveRC(rc);
1431 return rc;
1432}
1433
1434/**
1435 * Replies a host request to open an object.
1436 *
1437 * @returns VBox status code.
1438 * @param pCtx Shared Clipboard command context to use for the connection.
1439 * @param rcReply Return code to reply to the host.
1440 * @param hObj Object handle of opened object to reply to the host.
1441 */
1442VBGLR3DECL(int) VbglR3ClipboardObjOpenReply(PVBGLR3SHCLCMDCTX pCtx, int rcReply, SHCLOBJHANDLE hObj)
1443{
1444 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1445
1446 VBoxShClReplyMsg Msg;
1447 RT_ZERO(Msg);
1448
1449 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1450 VBOX_SHCL_GUEST_FN_REPLY, VBOX_SHCL_CPARMS_REPLY_MIN + 1);
1451
1452 Msg.uContext.SetUInt64(pCtx->idContext);
1453 Msg.enmType.SetUInt32(VBOX_SHCL_REPLYMSGTYPE_OBJ_OPEN);
1454 Msg.rc.SetUInt32((uint32_t)rcReply); /** int vs. uint32_t */
1455 Msg.cbPayload.SetUInt32(0);
1456 Msg.pvPayload.SetPtr(NULL, 0);
1457
1458 Msg.u.ObjOpen.uHandle.SetUInt64(hObj);
1459
1460 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1461
1462 LogFlowFuncLeaveRC(rc);
1463 return rc;
1464}
1465
1466/**
1467 * Sends an object open request to the host.
1468 *
1469 * @returns VBox status code.
1470 * @param pCtx Shared Clipboard command context to use for the connection.
1471 * @param pCreateParms Object open/create parameters to use for opening the object on the host.
1472 * @param phObj Where to return the object handle from the host.
1473 */
1474VBGLR3DECL(int) VbglR3ClipboardObjOpenSend(PVBGLR3SHCLCMDCTX pCtx, PSHCLOBJOPENCREATEPARMS pCreateParms,
1475 PSHCLOBJHANDLE phObj)
1476{
1477 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1478 AssertPtrReturn(pCreateParms, VERR_INVALID_POINTER);
1479 AssertPtrReturn(phObj, VERR_INVALID_POINTER);
1480
1481 VBoxShClObjOpenMsg Msg;
1482 RT_ZERO(Msg);
1483
1484 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1485 VBOX_SHCL_GUEST_FN_OBJ_OPEN, VBOX_SHCL_CPARMS_OBJ_OPEN);
1486
1487 Msg.uContext.SetUInt64(pCtx->idContext);
1488 Msg.uHandle.SetUInt64(0);
1489 Msg.cbPath.SetUInt32(pCreateParms->cbPath);
1490 Msg.szPath.SetPtr((void *)pCreateParms->pszPath, pCreateParms->cbPath);
1491 Msg.fCreate.SetUInt32(pCreateParms->fCreate);
1492
1493 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1494 if (RT_SUCCESS(rc))
1495 {
1496 Msg.uHandle.GetUInt64(phObj);
1497 }
1498
1499 LogFlowFuncLeaveRC(rc);
1500 return rc;
1501}
1502
1503/**
1504 * Receives a host request to close an object on the guest.
1505 *
1506 * @returns VBox status code.
1507 * @param pCtx Shared Clipboard command context to use for the connection.
1508 * @param phObj Where to return the object handle to close from the host.
1509 */
1510VBGLR3DECL(int) VbglR3ClipboardObjCloseRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLOBJHANDLE phObj)
1511{
1512 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1513 AssertPtrReturn(phObj, VERR_INVALID_POINTER);
1514
1515 VBoxShClObjCloseMsg Msg;
1516 RT_ZERO(Msg);
1517
1518 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1519 VBOX_SHCL_GUEST_FN_MSG_GET, VBOX_SHCL_CPARMS_OBJ_CLOSE);
1520
1521 Msg.uContext.SetUInt64(VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_CLOSE);
1522 Msg.uHandle.SetUInt64(0);
1523
1524 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1525 if (RT_SUCCESS(rc))
1526 {
1527 rc = Msg.uContext.GetUInt64(&pCtx->idContext);
1528 if (RT_SUCCESS(rc))
1529 rc = Msg.uHandle.GetUInt64(phObj);
1530 }
1531
1532 LogFlowFuncLeaveRC(rc);
1533 return rc;
1534}
1535
1536/**
1537 * Replies to an object open request from the host.
1538 *
1539 * @returns VBox status code.
1540 * @param pCtx Shared Clipboard command context to use for the connection.
1541 * @param rcReply Return code to reply to the host.
1542 * @param hObj Object handle to reply to the host.
1543 */
1544VBGLR3DECL(int) VbglR3ClipboardObjCloseReply(PVBGLR3SHCLCMDCTX pCtx, int rcReply, SHCLOBJHANDLE hObj)
1545{
1546 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1547
1548 VBoxShClReplyMsg Msg;
1549 RT_ZERO(Msg);
1550
1551 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1552 VBOX_SHCL_GUEST_FN_REPLY, VBOX_SHCL_CPARMS_REPLY_MIN + 1);
1553
1554 Msg.uContext.SetUInt64(pCtx->idContext);
1555 Msg.enmType.SetUInt32(VBOX_SHCL_REPLYMSGTYPE_OBJ_CLOSE);
1556 Msg.rc.SetUInt32((uint32_t)rcReply); /** int vs. uint32_t */
1557 Msg.cbPayload.SetUInt32(0);
1558 Msg.pvPayload.SetPtr(NULL, 0);
1559
1560 Msg.u.ObjClose.uHandle.SetUInt64(hObj);
1561
1562 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1563
1564 LogFlowFuncLeaveRC(rc);
1565 return rc;
1566}
1567
1568/**
1569 * Sends a request to close an object to the host.
1570 *
1571 * @returns VBox status code.
1572 * @param pCtx Shared Clipboard command context to use for the connection.
1573 * @param hObj Object handle to close on the host.
1574 */
1575VBGLR3DECL(int) VbglR3ClipboardObjCloseSend(PVBGLR3SHCLCMDCTX pCtx, SHCLOBJHANDLE hObj)
1576{
1577 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1578
1579 VBoxShClObjCloseMsg Msg;
1580 RT_ZERO(Msg);
1581
1582 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1583 VBOX_SHCL_GUEST_FN_OBJ_CLOSE, VBOX_SHCL_CPARMS_OBJ_CLOSE);
1584
1585 Msg.uContext.SetUInt64(pCtx->idContext);
1586 Msg.uHandle.SetUInt64(hObj);
1587
1588 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1589
1590 LogFlowFuncLeaveRC(rc);
1591 return rc;
1592}
1593
1594/**
1595 * Receives a host request to read from an object on the guest.
1596 *
1597 * @returns VBox status code.
1598 * @param pCtx Shared Clipboard command context to use for the connection.
1599 * @param phObj Where to return the object handle to read from.
1600 * @param pcbToRead Where to return the amount (in bytes) to read.
1601 * @param pfFlags Where to return the read flags.
1602 */
1603VBGLR3DECL(int) VbglR3ClipboardObjReadRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLOBJHANDLE phObj, uint32_t *pcbToRead,
1604 uint32_t *pfFlags)
1605{
1606 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1607 AssertPtrReturn(phObj, VERR_INVALID_POINTER);
1608 AssertPtrReturn(pcbToRead, VERR_INVALID_POINTER);
1609 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
1610
1611 VBoxShClObjReadReqMsg Msg;
1612 RT_ZERO(Msg);
1613
1614 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1615 VBOX_SHCL_GUEST_FN_MSG_GET, VBOX_SHCL_CPARMS_OBJ_READ_REQ);
1616
1617 Msg.ReqParms.uContext.SetUInt64(VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_READ);
1618 Msg.ReqParms.uHandle.SetUInt64(0);
1619 Msg.ReqParms.cbToRead.SetUInt32(0);
1620 Msg.ReqParms.fRead.SetUInt32(0);
1621
1622 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1623 if (RT_SUCCESS(rc))
1624 {
1625 rc = Msg.ReqParms.uContext.GetUInt64(&pCtx->idContext);
1626 if (RT_SUCCESS(rc))
1627 rc = Msg.ReqParms.uHandle.GetUInt64(phObj);
1628 if (RT_SUCCESS(rc))
1629 rc = Msg.ReqParms.cbToRead.GetUInt32(pcbToRead);
1630 if (RT_SUCCESS(rc))
1631 rc = Msg.ReqParms.fRead.GetUInt32(pfFlags);
1632 }
1633
1634 LogFlowFuncLeaveRC(rc);
1635 return rc;
1636}
1637
1638/**
1639 * Sends a request to read from an object to the host.
1640 *
1641 * @returns VBox status code.
1642 * @param pCtx Shared Clipboard command context to use for the connection.
1643 * @param hObj Object handle of object to read from.
1644 * @param pvData Buffer where to store the read object data.
1645 * @param cbData Size (in bytes) of buffer.
1646 * @param pcbRead Where to store the amount (in bytes) read from the object.
1647 */
1648VBGLR3DECL(int) VbglR3ClipboardObjReadSend(PVBGLR3SHCLCMDCTX pCtx, SHCLOBJHANDLE hObj,
1649 void *pvData, uint32_t cbData, uint32_t *pcbRead)
1650{
1651 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1652 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
1653 AssertReturn(cbData, VERR_INVALID_PARAMETER);
1654 /* pcbRead is optional. */
1655
1656 VBoxShClObjReadWriteMsg Msg;
1657 RT_ZERO(Msg);
1658
1659 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1660 VBOX_SHCL_GUEST_FN_OBJ_READ, VBOX_SHCL_CPARMS_OBJ_READ);
1661
1662 Msg.uContext.SetUInt64(pCtx->idContext);
1663 Msg.uHandle.SetUInt64(hObj);
1664 Msg.cbData.SetUInt32(cbData);
1665 Msg.pvData.SetPtr(pvData, cbData);
1666 Msg.cbChecksum.SetUInt32(0);
1667 Msg.pvChecksum.SetPtr(NULL, 0);
1668
1669 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1670 if (RT_SUCCESS(rc))
1671 {
1672 /** @todo Add checksum support. */
1673
1674 if (pcbRead)
1675 {
1676 rc = Msg.cbData.GetUInt32(pcbRead); AssertRC(rc);
1677 AssertReturn(cbData >= *pcbRead, VERR_TOO_MUCH_DATA);
1678 }
1679 }
1680
1681 LogFlowFuncLeaveRC(rc);
1682 return rc;
1683}
1684
1685/**
1686 * Sends a request to write to an object to the host.
1687 *
1688 * @returns VBox status code.
1689 * @param pCtx Shared Clipboard command context to use for the connection.
1690 * @param hObj Object handle of object to write to.
1691 * @param pvData Buffer of data to write to object.
1692 * @param cbData Size (in bytes) of buffer.
1693 * @param pcbWritten Where to store the amount (in bytes) written to the object.
1694 */
1695VBGLR3DECL(int) VbglR3ClipboardObjWriteSend(PVBGLR3SHCLCMDCTX pCtx, SHCLOBJHANDLE hObj,
1696 void *pvData, uint32_t cbData, uint32_t *pcbWritten)
1697{
1698 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1699 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
1700 /* cbData can be 0. */
1701 /* pcbWritten is optional. */
1702
1703 VBoxShClObjReadWriteMsg Msg;
1704 RT_ZERO(Msg);
1705
1706 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
1707 VBOX_SHCL_GUEST_FN_OBJ_WRITE, VBOX_SHCL_CPARMS_OBJ_WRITE);
1708
1709 Msg.uContext.SetUInt64(pCtx->idContext);
1710 Msg.uHandle.SetUInt64(hObj);
1711 Msg.pvData.SetPtr(pvData, cbData);
1712 Msg.cbData.SetUInt32(cbData);
1713 Msg.pvChecksum.SetPtr(NULL, 0);
1714 Msg.cbChecksum.SetUInt32(0);
1715
1716 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1717 if (RT_SUCCESS(rc))
1718 {
1719 /** @todo Add checksum support. */
1720
1721 if (pcbWritten)
1722 *pcbWritten = cbData; /** @todo For now return all as being written. */
1723 }
1724
1725 LogFlowFuncLeaveRC(rc);
1726 return rc;
1727}
1728
1729
1730/*********************************************************************************************************************************
1731* Transfer interface implementations *
1732*********************************************************************************************************************************/
1733
1734static DECLCALLBACK(int) vbglR3ClipboardTransferIfaceGetRoots(PSHCLPROVIDERCTX pCtx, PSHCLROOTLIST *ppRootList)
1735{
1736 LogFlowFuncEnter();
1737
1738 PVBGLR3SHCLCMDCTX pCmdCtx = (PVBGLR3SHCLCMDCTX)pCtx->pvUser;
1739 AssertPtr(pCmdCtx);
1740
1741 int rc = VbglR3ClipboardRootListRead(pCmdCtx, ppRootList);
1742
1743 LogFlowFuncLeaveRC(rc);
1744 return rc;
1745}
1746
1747static DECLCALLBACK(int) vbglR3ClipboardTransferIfaceListOpen(PSHCLPROVIDERCTX pCtx, PSHCLLISTOPENPARMS pOpenParms,
1748 PSHCLLISTHANDLE phList)
1749{
1750 LogFlowFuncEnter();
1751
1752 PVBGLR3SHCLCMDCTX pCmdCtx = (PVBGLR3SHCLCMDCTX)pCtx->pvUser;
1753 AssertPtr(pCmdCtx);
1754
1755 int rc = VbglR3ClipboardListOpenSend(pCmdCtx, pOpenParms, phList);
1756
1757 LogFlowFuncLeaveRC(rc);
1758 return rc;
1759}
1760
1761static DECLCALLBACK(int) vbglR3ClipboardTransferIfaceListClose(PSHCLPROVIDERCTX pCtx, SHCLLISTHANDLE hList)
1762{
1763 LogFlowFuncEnter();
1764
1765 PVBGLR3SHCLCMDCTX pCmdCtx = (PVBGLR3SHCLCMDCTX)pCtx->pvUser;
1766 AssertPtr(pCmdCtx);
1767
1768 int rc = VbglR3ClipboardListCloseSend(pCmdCtx, hList);
1769
1770 LogFlowFuncLeaveRC(rc);
1771 return rc;
1772}
1773
1774static DECLCALLBACK(int) vbglR3ClipboardTransferIfaceListHdrRead(PSHCLPROVIDERCTX pCtx,
1775 SHCLLISTHANDLE hList, PSHCLLISTHDR pListHdr)
1776{
1777 LogFlowFuncEnter();
1778
1779 PVBGLR3SHCLCMDCTX pCmdCtx = (PVBGLR3SHCLCMDCTX)pCtx->pvUser;
1780 AssertPtr(pCmdCtx);
1781
1782 int rc = ShClTransferListHdrInit(pListHdr);
1783 if (RT_SUCCESS(rc))
1784 {
1785 if (RT_SUCCESS(rc))
1786 {
1787 rc = VbglR3ClipboardListHdrRead(pCmdCtx, hList, 0 /* fFlags */, pListHdr);
1788 }
1789 else
1790 ShClTransferListHdrDestroy(pListHdr);
1791 }
1792
1793 LogFlowFuncLeaveRC(rc);
1794 return rc;
1795}
1796
1797static DECLCALLBACK(int) vbglR3ClipboardTransferIfaceListEntryRead(PSHCLPROVIDERCTX pCtx,
1798 SHCLLISTHANDLE hList, PSHCLLISTENTRY pEntry)
1799{
1800 LogFlowFuncEnter();
1801
1802 PVBGLR3SHCLCMDCTX pCmdCtx = (PVBGLR3SHCLCMDCTX)pCtx->pvUser;
1803 AssertPtr(pCmdCtx);
1804
1805 int rc = VbglR3ClipboardListEntryRead(pCmdCtx, hList, pEntry);
1806
1807 LogFlowFuncLeaveRC(rc);
1808 return rc;
1809}
1810
1811static DECLCALLBACK(int) vbglR3ClipboardTransferIfaceObjOpen(PSHCLPROVIDERCTX pCtx,
1812 PSHCLOBJOPENCREATEPARMS pCreateParms, PSHCLOBJHANDLE phObj)
1813{
1814 LogFlowFuncEnter();
1815
1816 PVBGLR3SHCLCMDCTX pCmdCtx = (PVBGLR3SHCLCMDCTX)pCtx->pvUser;
1817 AssertPtr(pCmdCtx);
1818
1819 int rc = VbglR3ClipboardObjOpenSend(pCmdCtx, pCreateParms, phObj);
1820
1821 LogFlowFuncLeaveRC(rc);
1822 return rc;
1823}
1824
1825static DECLCALLBACK(int) vbglR3ClipboardTransferIfaceObjClose(PSHCLPROVIDERCTX pCtx, SHCLOBJHANDLE hObj)
1826{
1827 LogFlowFuncEnter();
1828
1829 PVBGLR3SHCLCMDCTX pCmdCtx = (PVBGLR3SHCLCMDCTX)pCtx->pvUser;
1830 AssertPtr(pCmdCtx);
1831
1832 int rc = VbglR3ClipboardObjCloseSend(pCmdCtx, hObj);
1833
1834 LogFlowFuncLeaveRC(rc);
1835 return rc;
1836}
1837
1838static DECLCALLBACK(int) vbglR3ClipboardTransferIfaceObjRead(PSHCLPROVIDERCTX pCtx,
1839 SHCLOBJHANDLE hObj, void *pvData, uint32_t cbData,
1840 uint32_t fFlags, uint32_t *pcbRead)
1841{
1842 LogFlowFuncEnter();
1843
1844 PVBGLR3SHCLCMDCTX pCmdCtx = (PVBGLR3SHCLCMDCTX)pCtx->pvUser;
1845 AssertPtr(pCmdCtx);
1846
1847 RT_NOREF(fFlags); /* Not used yet. */
1848
1849 int rc = VbglR3ClipboardObjReadSend(pCmdCtx, hObj, pvData, cbData, pcbRead);
1850
1851 LogFlowFuncLeaveRC(rc);
1852 return rc;
1853}
1854
1855/**
1856 * Starts a transfer on the guest side.
1857 *
1858 * @returns VBox status code.
1859 * @param pCmdCtx Command context to use.
1860 * @param pTransferCtx Transfer context to create transfer for.
1861 * @param uTransferID ID to use for transfer to start.
1862 * @param enmDir Direction of transfer to start.
1863 * @param enmSource Source of transfer to start.
1864 * @param ppTransfer Where to return the transfer object on success. Optional.
1865 */
1866static int vbglR3ClipboardTransferStart(PVBGLR3SHCLCMDCTX pCmdCtx, PSHCLTRANSFERCTX pTransferCtx,
1867 SHCLTRANSFERID uTransferID, SHCLTRANSFERDIR enmDir, SHCLSOURCE enmSource,
1868 PSHCLTRANSFER *ppTransfer)
1869{
1870 PSHCLTRANSFER pTransfer;
1871 int rc = ShClTransferCreate(&pTransfer);
1872 if (RT_SUCCESS(rc))
1873 {
1874 ShClTransferSetCallbacks(pTransfer, &pCmdCtx->Callbacks);
1875
1876 rc = ShClTransferCtxTransferRegisterByIndex(pTransferCtx, pTransfer, uTransferID);
1877 if (RT_SUCCESS(rc))
1878 {
1879 rc = ShClTransferInit(pTransfer, uTransferID, enmDir, enmSource);
1880 if (RT_SUCCESS(rc))
1881 {
1882 /* If this is a read transfer (reading data from host), set the interface to use
1883 * our VbglR3 routines here. */
1884 if (enmDir == SHCLTRANSFERDIR_FROM_REMOTE)
1885 {
1886 SHCLPROVIDERCREATIONCTX creationCtx;
1887 RT_ZERO(creationCtx);
1888
1889 creationCtx.Interface.pfnRootsGet = vbglR3ClipboardTransferIfaceGetRoots;
1890
1891 creationCtx.Interface.pfnListOpen = vbglR3ClipboardTransferIfaceListOpen;
1892 creationCtx.Interface.pfnListClose = vbglR3ClipboardTransferIfaceListClose;
1893 creationCtx.Interface.pfnListHdrRead = vbglR3ClipboardTransferIfaceListHdrRead;
1894 creationCtx.Interface.pfnListEntryRead = vbglR3ClipboardTransferIfaceListEntryRead;
1895
1896 creationCtx.Interface.pfnObjOpen = vbglR3ClipboardTransferIfaceObjOpen;
1897 creationCtx.Interface.pfnObjClose = vbglR3ClipboardTransferIfaceObjClose;
1898 creationCtx.Interface.pfnObjRead = vbglR3ClipboardTransferIfaceObjRead;
1899
1900 creationCtx.pvUser = pCmdCtx;
1901
1902 rc = ShClTransferSetInterface(pTransfer, &creationCtx);
1903 }
1904
1905 if (RT_SUCCESS(rc))
1906 rc = ShClTransferStart(pTransfer);
1907 }
1908
1909 if (RT_FAILURE(rc))
1910 ShClTransferCtxTransferUnregister(pTransferCtx, uTransferID);
1911 }
1912 }
1913
1914 if (RT_SUCCESS(rc))
1915 {
1916 if (ppTransfer)
1917 *ppTransfer = pTransfer;
1918
1919 LogRel2(("Shared Clipboard: Transfer ID=%RU16 (%s %s) successfully started\n",
1920 uTransferID,
1921 enmDir == SHCLTRANSFERDIR_FROM_REMOTE ? "reading from" : "writing to",
1922 enmSource == SHCLSOURCE_LOCAL ? "local" : "remote"));
1923 }
1924 else
1925 LogRel(("Shared Clipboard: Unable to start transfer ID=%RU16, rc=%Rrc\n", uTransferID, rc));
1926
1927 /* Send a reply in any case. */
1928 int rc2 = VbglR3ClipboardTransferStatusReply(pCmdCtx, pTransfer,
1929 RT_SUCCESS(rc)
1930 ? SHCLTRANSFERSTATUS_STARTED : SHCLTRANSFERSTATUS_ERROR, rc);
1931 if (RT_SUCCESS(rc))
1932 rc = rc2;
1933
1934 if (RT_FAILURE(rc))
1935 {
1936 ShClTransferDestroy(pTransfer);
1937 pTransfer = NULL;
1938 }
1939
1940 LogFlowFuncLeaveRC(rc);
1941 return rc;
1942}
1943
1944/**
1945 * Stops a transfer on the guest side.
1946 *
1947 * @returns VBox status code, or VERR_NOT_FOUND if transfer has not been found.
1948 * @param pCmdCtx Command context to use.
1949 * @param pTransferCtx Transfer context to stop transfer for.
1950 * @param uTransferID ID of transfer to stop.
1951 */
1952static int vbglR3ClipboardTransferStop(PVBGLR3SHCLCMDCTX pCmdCtx, PSHCLTRANSFERCTX pTransferCtx,
1953 SHCLTRANSFERID uTransferID)
1954{
1955 int rc;
1956
1957 PSHCLTRANSFER pTransfer = ShClTransferCtxGetTransfer(pTransferCtx, uTransferID);
1958 if (pTransfer)
1959 {
1960 rc = ShClTransferClose(pTransfer);
1961 if (RT_SUCCESS(rc))
1962 rc = ShClTransferCtxTransferUnregister(pTransferCtx, uTransferID);
1963
1964 if (RT_SUCCESS(rc))
1965 {
1966 LogRel2(("Shared Clipboard: Transfer ID=%RU16 successfully stopped\n", uTransferID));
1967 }
1968 else
1969 LogRel(("Shared Clipboard: Unable to stop transfer ID=%RU16, rc=%Rrc\n", uTransferID, rc));
1970
1971 /* Send a reply in any case. */
1972 int rc2 = VbglR3ClipboardTransferStatusReply(pCmdCtx, pTransfer,
1973 RT_SUCCESS(rc)
1974 ? SHCLTRANSFERSTATUS_STOPPED : SHCLTRANSFERSTATUS_ERROR, rc);
1975 AssertRC(rc2);
1976 }
1977 else
1978 rc = VERR_NOT_FOUND;
1979
1980 LogFlowFuncLeaveRC(rc);
1981 return rc;
1982}
1983
1984VBGLR3DECL(int) VbglR3ClipboardEventGetNextEx(uint32_t idMsg, uint32_t cParms,
1985 PVBGLR3SHCLCMDCTX pCmdCtx, PSHCLTRANSFERCTX pTransferCtx,
1986 PVBGLR3CLIPBOARDEVENT pEvent)
1987{
1988 AssertPtrReturn(pCmdCtx, VERR_INVALID_POINTER);
1989 AssertPtrReturn(pTransferCtx, VERR_INVALID_POINTER);
1990 AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
1991
1992 LogFunc(("Handling idMsg=%RU32 (%s), cParms=%RU32\n", idMsg, ShClHostMsgToStr(idMsg), cParms));
1993
1994 int rc;
1995 if (!pCmdCtx->fUseLegacyProtocol)
1996 {
1997 bool fErrorSent = false; /* Whether an error has been reported back to the host already. */
1998
1999 switch (idMsg)
2000 {
2001 case VBOX_SHCL_HOST_MSG_TRANSFER_STATUS:
2002 {
2003 SHCLTRANSFERDIR enmDir;
2004 SHCLTRANSFERREPORT transferReport;
2005 rc = VbglR3ClipboarTransferStatusRecv(pCmdCtx, &enmDir, &transferReport);
2006 if (RT_SUCCESS(rc))
2007 {
2008 const SHCLTRANSFERID uTransferID = VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->idContext);
2009
2010 LogFlowFunc(("[Transfer %RU16] enmDir=%RU32, status=%s\n",
2011 uTransferID, enmDir, ShClTransferStatusToStr(transferReport.uStatus)));
2012
2013 switch (transferReport.uStatus)
2014 {
2015 case SHCLTRANSFERSTATUS_INITIALIZED:
2016 RT_FALL_THROUGH();
2017 case SHCLTRANSFERSTATUS_STARTED:
2018 {
2019 SHCLSOURCE enmSource = SHCLSOURCE_INVALID;
2020
2021 /* The host announces the transfer direction from its point of view, so inverse the direction here. */
2022 if (enmDir == SHCLTRANSFERDIR_TO_REMOTE)
2023 {
2024 enmDir = SHCLTRANSFERDIR_FROM_REMOTE;
2025 enmSource = SHCLSOURCE_REMOTE;
2026 }
2027 else if (enmDir == SHCLTRANSFERDIR_FROM_REMOTE)
2028 {
2029 enmDir = SHCLTRANSFERDIR_TO_REMOTE;
2030 enmSource = SHCLSOURCE_LOCAL;
2031 }
2032 else
2033 AssertFailedBreakStmt(rc = VERR_INVALID_PARAMETER);
2034
2035 rc = vbglR3ClipboardTransferStart(pCmdCtx, pTransferCtx, uTransferID,
2036 enmDir, enmSource, NULL /* ppTransfer */);
2037 break;
2038 }
2039
2040 case SHCLTRANSFERSTATUS_STOPPED:
2041 RT_FALL_THROUGH();
2042 case SHCLTRANSFERSTATUS_CANCELED:
2043 RT_FALL_THROUGH();
2044 case SHCLTRANSFERSTATUS_KILLED:
2045 RT_FALL_THROUGH();
2046 case SHCLTRANSFERSTATUS_ERROR:
2047 {
2048 rc = vbglR3ClipboardTransferStop(pCmdCtx, pTransferCtx,
2049 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->idContext));
2050 break;
2051 }
2052
2053 default:
2054 rc = VERR_NOT_SUPPORTED;
2055 break;
2056 }
2057
2058 if (RT_SUCCESS(rc))
2059 {
2060 pEvent->u.TransferStatus.enmDir = enmDir;
2061 pEvent->u.TransferStatus.Report = transferReport;
2062 pEvent->u.TransferStatus.uID = VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->idContext);
2063
2064 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_TRANSFER_STATUS;
2065
2066 LogRel2(("Shared Clipboard: Received status %s (rc=%Rrc) for transfer ID=%RU16\n",
2067 ShClTransferStatusToStr(pEvent->u.TransferStatus.Report.uStatus), pEvent->u.TransferStatus.Report.rc,
2068 pEvent->u.TransferStatus.uID));
2069 }
2070 }
2071 break;
2072 }
2073
2074 case VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_HDR_READ:
2075 {
2076 uint32_t fRoots;
2077 rc = VbglR3ClipboardRootListHdrReadReq(pCmdCtx, &fRoots);
2078
2079 /** @todo Validate / handle fRoots. */
2080
2081 if (RT_SUCCESS(rc))
2082 {
2083 PSHCLTRANSFER pTransfer = ShClTransferCtxGetTransfer(pTransferCtx,
2084 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->idContext));
2085 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND);
2086
2087 SHCLROOTLISTHDR rootListHdr;
2088 RT_ZERO(rootListHdr);
2089
2090 rootListHdr.cRoots = ShClTransferRootsCount(pTransfer);
2091
2092 LogFlowFunc(("cRoots=%RU32\n", rootListHdr.cRoots));
2093
2094 rc = VbglR3ClipboardRootListHdrReadReply(pCmdCtx, &rootListHdr);
2095 }
2096 break;
2097 }
2098
2099 case VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_ENTRY_READ:
2100 {
2101 uint32_t uIndex;
2102 uint32_t fInfo;
2103 rc = VbglR3ClipboardRootListEntryReadReq(pCmdCtx, &uIndex, &fInfo);
2104 if (RT_SUCCESS(rc))
2105 {
2106 PSHCLTRANSFER pTransfer = ShClTransferCtxGetTransfer(pTransferCtx,
2107 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->idContext));
2108 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND);
2109
2110 SHCLROOTLISTENTRY rootListEntry;
2111 rc = ShClTransferRootsEntry(pTransfer, uIndex, &rootListEntry);
2112 if (RT_SUCCESS(rc))
2113 rc = VbglR3ClipboardRootListEntryReadReply(pCmdCtx, uIndex, &rootListEntry);
2114 }
2115 break;
2116 }
2117
2118 case VBOX_SHCL_HOST_MSG_TRANSFER_LIST_OPEN:
2119 {
2120 SHCLLISTOPENPARMS openParmsList;
2121 rc = ShClTransferListOpenParmsInit(&openParmsList);
2122 if (RT_SUCCESS(rc))
2123 {
2124 rc = VbglR3ClipboardListOpenRecv(pCmdCtx, &openParmsList);
2125 if (RT_SUCCESS(rc))
2126 {
2127 PSHCLTRANSFER pTransfer = ShClTransferCtxGetTransfer(pTransferCtx,
2128 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->idContext));
2129 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND);
2130
2131 LogFlowFunc(("pszPath=%s\n", openParmsList.pszPath));
2132
2133 SHCLLISTHANDLE hList = SHCLLISTHANDLE_INVALID;
2134 rc = ShClTransferListOpen(pTransfer, &openParmsList, &hList);
2135
2136 /* Reply in any case. */
2137 int rc2 = VbglR3ClipboardListOpenReply(pCmdCtx, rc, hList);
2138 AssertRC(rc2);
2139 }
2140
2141 ShClTransferListOpenParmsDestroy(&openParmsList);
2142 }
2143
2144 break;
2145 }
2146
2147 case VBOX_SHCL_HOST_MSG_TRANSFER_LIST_CLOSE:
2148 {
2149 SHCLLISTHANDLE hList;
2150 rc = VbglR3ClipboardListCloseRecv(pCmdCtx, &hList);
2151 if (RT_SUCCESS(rc))
2152 {
2153 PSHCLTRANSFER pTransfer = ShClTransferCtxGetTransfer(pTransferCtx,
2154 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->idContext));
2155 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND);
2156
2157 rc = ShClTransferListClose(pTransfer, hList);
2158
2159 /* Reply in any case. */
2160 int rc2 = VbglR3ClipboardListCloseReply(pCmdCtx, rc, hList);
2161 AssertRC(rc2);
2162 }
2163
2164 break;
2165 }
2166
2167 case VBOX_SHCL_HOST_MSG_TRANSFER_LIST_HDR_READ:
2168 {
2169 /** @todo Handle filter + list features. */
2170
2171 SHCLLISTHANDLE hList = SHCLLISTHANDLE_INVALID;
2172 uint32_t fFlags = 0;
2173 rc = VbglR3ClipboardListHdrReadRecvReq(pCmdCtx, &hList, &fFlags);
2174 if (RT_SUCCESS(rc))
2175 {
2176 PSHCLTRANSFER pTransfer = ShClTransferCtxGetTransfer(pTransferCtx,
2177 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->idContext));
2178 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND);
2179
2180 SHCLLISTHDR hdrList;
2181 rc = ShClTransferListGetHeader(pTransfer, hList, &hdrList);
2182 if (RT_SUCCESS(rc))
2183 {
2184 rc = VbglR3ClipboardListHdrWrite(pCmdCtx, hList, &hdrList);
2185
2186 ShClTransferListHdrDestroy(&hdrList);
2187 }
2188 }
2189
2190 break;
2191 }
2192
2193 case VBOX_SHCL_HOST_MSG_TRANSFER_LIST_ENTRY_READ:
2194 {
2195 LogFlowFunc(("VBOX_SHCL_HOST_MSG_TRANSFER_LIST_ENTRY_READ\n"));
2196
2197 SHCLLISTENTRY entryList;
2198 rc = ShClTransferListEntryInit(&entryList);
2199 if (RT_SUCCESS(rc))
2200 {
2201 SHCLLISTHANDLE hList;
2202 uint32_t fInfo;
2203 rc = VbglR3ClipboardListEntryReadRecvReq(pCmdCtx, &hList, &fInfo);
2204 if (RT_SUCCESS(rc))
2205 {
2206 PSHCLTRANSFER pTransfer = ShClTransferCtxGetTransfer(pTransferCtx,
2207 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->idContext));
2208 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND);
2209
2210 rc = ShClTransferListRead(pTransfer, hList, &entryList);
2211 if (RT_SUCCESS(rc))
2212 {
2213 PSHCLFSOBJINFO pObjInfo = (PSHCLFSOBJINFO)entryList.pvInfo;
2214 Assert(entryList.cbInfo == sizeof(SHCLFSOBJINFO));
2215
2216 RT_NOREF(pObjInfo);
2217
2218 LogFlowFunc(("\t%s (%RU64 bytes)\n", entryList.pszName, pObjInfo->cbObject));
2219
2220 rc = VbglR3ClipboardListEntryWrite(pCmdCtx, hList, &entryList);
2221 }
2222 }
2223
2224 ShClTransferListEntryDestroy(&entryList);
2225 }
2226
2227 break;
2228 }
2229
2230 case VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_OPEN:
2231 {
2232 SHCLOBJOPENCREATEPARMS openParms;
2233 rc = ShClTransferObjOpenParmsInit(&openParms);
2234 if (RT_SUCCESS(rc))
2235 {
2236 rc = VbglR3ClipboardObjOpenRecv(pCmdCtx, &openParms);
2237 if (RT_SUCCESS(rc))
2238 {
2239 PSHCLTRANSFER pTransfer = ShClTransferCtxGetTransfer(pTransferCtx,
2240 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->idContext));
2241 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND);
2242
2243 SHCLOBJHANDLE hObj;
2244 rc = ShClTransferObjOpen(pTransfer, &openParms, &hObj);
2245
2246 /* Reply in any case. */
2247 int rc2 = VbglR3ClipboardObjOpenReply(pCmdCtx, rc, hObj);
2248 AssertRC(rc2);
2249 }
2250
2251 ShClTransferObjOpenParmsDestroy(&openParms);
2252 }
2253
2254 break;
2255 }
2256
2257 case VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_CLOSE:
2258 {
2259 SHCLOBJHANDLE hObj;
2260 rc = VbglR3ClipboardObjCloseRecv(pCmdCtx, &hObj);
2261 if (RT_SUCCESS(rc))
2262 {
2263 PSHCLTRANSFER pTransfer = ShClTransferCtxGetTransfer(pTransferCtx,
2264 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->idContext));
2265 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND);
2266
2267 rc = ShClTransferObjClose(pTransfer, hObj);
2268
2269 /* Reply in any case. */
2270 int rc2 = VbglR3ClipboardObjCloseReply(pCmdCtx, rc, hObj);
2271 AssertRC(rc2);
2272 }
2273
2274 break;
2275 }
2276
2277 case VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_READ:
2278 {
2279 SHCLOBJHANDLE hObj;
2280 uint32_t cbBuf;
2281 uint32_t fFlags;
2282 rc = VbglR3ClipboardObjReadRecv(pCmdCtx, &hObj, &cbBuf, &fFlags);
2283 if (RT_SUCCESS(rc))
2284 {
2285 PSHCLTRANSFER pTransfer = ShClTransferCtxGetTransfer(pTransferCtx,
2286 VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->idContext));
2287 AssertPtrBreakStmt(pTransfer, rc = VERR_NOT_FOUND);
2288
2289 AssertBreakStmt(pCmdCtx->cbChunkSize, rc = VERR_INVALID_PARAMETER);
2290
2291 const uint32_t cbToRead = RT_MIN(cbBuf, pCmdCtx->cbChunkSize);
2292
2293 LogFlowFunc(("hObj=%RU64, cbBuf=%RU32, fFlags=0x%x -> cbChunkSize=%RU32, cbToRead=%RU32\n",
2294 hObj, cbBuf, fFlags, pCmdCtx->cbChunkSize, cbToRead));
2295
2296 void *pvBuf = RTMemAlloc(cbToRead);
2297 if (pvBuf)
2298 {
2299 uint32_t cbRead;
2300 rc = ShClTransferObjRead(pTransfer, hObj, pvBuf, cbToRead, &cbRead, fFlags);
2301 if (RT_SUCCESS(rc))
2302 rc = VbglR3ClipboardObjWriteSend(pCmdCtx, hObj, pvBuf, cbRead, NULL /* pcbWritten */);
2303
2304 RTMemFree(pvBuf);
2305 }
2306 else
2307 rc = VERR_NO_MEMORY;
2308 }
2309
2310 break;
2311 }
2312
2313 default:
2314 {
2315 rc = VbglR3ClipboardEventGetNext(idMsg, cParms, pCmdCtx, pEvent);
2316 if (RT_FAILURE(rc))
2317 fErrorSent = true;
2318 break;
2319 }
2320 }
2321
2322 if ( !fErrorSent
2323 && RT_FAILURE(rc))
2324 {
2325 /* Report error back to the host. */
2326 int rc2 = VbglR3ClipboardWriteError(pCmdCtx->idClient, rc);
2327 AssertRC(rc2);
2328 }
2329 }
2330 else
2331 {
2332 /*
2333 * This builds on what we did in VbglR3ClipboardMsgPeekWait, so
2334 * !HACK ALERT! cParms is the format flag or flags.
2335 */
2336 rc = VINF_SUCCESS;
2337 switch (idMsg)
2338 {
2339 case VBOX_SHCL_HOST_MSG_FORMATS_REPORT:
2340 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_REPORT_FORMATS;
2341 pEvent->u.fReportedFormats = cParms;
2342 break;
2343
2344 case VBOX_SHCL_HOST_MSG_READ_DATA:
2345 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_READ_DATA;
2346 pEvent->u.fReadData = cParms;
2347 break;
2348
2349 case VBOX_SHCL_HOST_MSG_QUIT:
2350 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_QUIT;
2351 break;
2352
2353 default:
2354 AssertMsgFailed(("%u (%#x)\n", idMsg, idMsg));
2355 rc = VERR_NOT_SUPPORTED;
2356 break;
2357 }
2358 }
2359
2360 LogFlowFuncLeaveRC(rc);
2361 return rc;
2362}
2363
2364#endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
2365
2366VBGLR3DECL(int) VbglR3ClipboardEventGetNext(uint32_t idMsg, uint32_t cParms, PVBGLR3SHCLCMDCTX pCtx, PVBGLR3CLIPBOARDEVENT pEvent)
2367{
2368 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2369 AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
2370
2371 RT_NOREF(cParms);
2372
2373 int rc;
2374 if (!pCtx->fUseLegacyProtocol)
2375 {
2376 LogFunc(("Handling idMsg=%RU32 (%s)\n", idMsg, ShClHostMsgToStr(idMsg)));
2377 switch (idMsg)
2378 {
2379 case VBOX_SHCL_HOST_MSG_FORMATS_REPORT:
2380 {
2381 rc = vbglR3ClipboardFormatsReportRecv(pCtx, &pEvent->u.fReportedFormats);
2382 if (RT_SUCCESS(rc))
2383 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_REPORT_FORMATS;
2384 break;
2385 }
2386
2387 case VBOX_SHCL_HOST_MSG_READ_DATA_CID:
2388 {
2389 rc = vbglR3ClipboardFetchReadDataCid(pCtx, &pEvent->u.fReadData);
2390 if (RT_SUCCESS(rc))
2391 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_READ_DATA;
2392 break;
2393 }
2394
2395 case VBOX_SHCL_HOST_MSG_READ_DATA:
2396 {
2397 rc = vbglR3ClipboardFetchReadData(pCtx, &pEvent->u.fReadData);
2398 if (RT_SUCCESS(rc))
2399 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_READ_DATA;
2400 break;
2401 }
2402
2403 case VBOX_SHCL_HOST_MSG_QUIT:
2404 {
2405 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_QUIT;
2406 rc = VINF_SUCCESS;
2407 break;
2408 }
2409
2410 default:
2411 {
2412 /** @todo r=bird: BUGBUG - need a skip command here! */
2413 rc = VERR_NOT_SUPPORTED;
2414 break;
2415 }
2416 }
2417
2418 if (RT_SUCCESS(rc))
2419 {
2420 /* Copy over our command context to the event. */
2421 pEvent->cmdCtx = *pCtx;
2422 }
2423 else
2424 {
2425 /* Report error back to the host. */
2426 int rc2 = VbglR3ClipboardWriteError(pCtx->idClient, rc);
2427 AssertRC(rc2);
2428 }
2429 }
2430 else
2431 {
2432 /*
2433 * This builds on what we did in VbglR3ClipboardMsgPeekWait, so
2434 * !HACK ALERT! cParms is the format flag or flags.
2435 */
2436 rc = VINF_SUCCESS;
2437 switch (idMsg)
2438 {
2439 case VBOX_SHCL_HOST_MSG_FORMATS_REPORT:
2440 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_REPORT_FORMATS;
2441 pEvent->u.fReportedFormats = cParms;
2442 break;
2443
2444 case VBOX_SHCL_HOST_MSG_READ_DATA:
2445 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_READ_DATA;
2446 pEvent->u.fReadData = cParms;
2447 break;
2448
2449 case VBOX_SHCL_HOST_MSG_QUIT:
2450 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_QUIT;
2451 break;
2452
2453 default:
2454 AssertMsgFailed(("%u (%#x)\n", idMsg, idMsg));
2455 rc = VERR_NOT_SUPPORTED;
2456 break;
2457 }
2458 pEvent->cmdCtx = *pCtx;
2459 }
2460
2461 LogFlowFuncLeaveRC(rc);
2462 return rc;
2463}
2464
2465/**
2466 * Frees (destroys) a formerly allocated Shared Clipboard event.
2467 *
2468 * @returns IPRT status code.
2469 * @param pEvent Event to free (destroy).
2470 */
2471VBGLR3DECL(void) VbglR3ClipboardEventFree(PVBGLR3CLIPBOARDEVENT pEvent)
2472{
2473 if (!pEvent)
2474 return;
2475
2476 /* Some messages require additional cleanup. */
2477 switch (pEvent->enmType)
2478 {
2479 default:
2480 break;
2481 }
2482
2483 RTMemFree(pEvent);
2484 pEvent = NULL;
2485}
2486
2487/**
2488 * Reports (advertises) guest clipboard formats to the host.
2489 *
2490 * Legacy function, do not use anymore.
2491 *
2492 * @returns VBox status code.
2493 * @param idClient The client id returned by VbglR3ClipboardConnect().
2494 * @param fFormats The formats to report.
2495 */
2496VBGLR3DECL(int) VbglR3ClipboardReportFormats(HGCMCLIENTID idClient, uint32_t fFormats)
2497{
2498 struct
2499 {
2500 VBGLIOCHGCMCALL Hdr;
2501 VBoxShClParmReportFormats Parms;
2502 } Msg;
2503
2504 VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, VBOX_SHCL_GUEST_FN_REPORT_FORMATS, VBOX_SHCL_CPARMS_REPORT_FORMATS);
2505 VbglHGCMParmUInt32Set(&Msg.Parms.f32Formats, fFormats);
2506
2507 int rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
2508
2509 LogFlowFuncLeaveRC(rc);
2510 return rc;
2511}
2512
2513/**
2514 * Sends guest clipboard data to the host.
2515 *
2516 * Legacy function kept for compatibility, do not use anymore.
2517 *
2518 * This is usually called in reply to a VBOX_SHCL_HOST_MSG_READ_DATA message
2519 * from the host.
2520 *
2521 * @returns VBox status code.
2522 * @param idClient The client id returned by VbglR3ClipboardConnect().
2523 * @param fFormat The format of the data.
2524 * @param pv The data.
2525 * @param cb The size of the data.
2526 */
2527VBGLR3DECL(int) VbglR3ClipboardWriteData(HGCMCLIENTID idClient, uint32_t fFormat, void *pv, uint32_t cb)
2528{
2529 LogFlowFuncEnter();
2530
2531 struct
2532 {
2533 VBGLIOCHGCMCALL Hdr;
2534 VBoxShClParmDataWriteOld Parms;
2535 } Msg;
2536
2537 VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, VBOX_SHCL_GUEST_FN_DATA_WRITE, VBOX_SHCL_CPARMS_DATA_WRITE_OLD);
2538 VbglHGCMParmUInt32Set(&Msg.Parms.f32Format, fFormat);
2539 VbglHGCMParmPtrSet(&Msg.Parms.pData, pv, cb);
2540
2541 int rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
2542
2543 LogFlowFuncLeaveRC(rc);
2544 return rc;
2545}
2546
2547/**
2548 * Sends guest clipboard data to the host.
2549 *
2550 * This is usually called in reply to a VBOX_SHCL_HOST_MSG_READ_DATA message
2551 * from the host.
2552 *
2553 * @returns VBox status code.
2554 * @param pCtx The command context returned by VbglR3ClipboardConnectEx().
2555 * @param uFormat Clipboard format to send.
2556 * @param pvData Pointer to data to send.
2557 * @param cbData Size (in bytes) of data to send.
2558 */
2559VBGLR3DECL(int) VbglR3ClipboardWriteDataEx(PVBGLR3SHCLCMDCTX pCtx, SHCLFORMAT uFormat, void *pvData, uint32_t cbData)
2560{
2561 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2562 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
2563
2564 int rc;
2565
2566 LogFlowFuncEnter();
2567
2568 if (pCtx->fUseLegacyProtocol)
2569 {
2570 rc = VbglR3ClipboardWriteData(pCtx->idClient, uFormat, pvData, cbData);
2571 }
2572 else
2573 {
2574 struct
2575 {
2576 VBGLIOCHGCMCALL Hdr;
2577 VBoxShClParmDataWrite Parms;
2578 } Msg;
2579
2580 VBGL_HGCM_HDR_INIT(&Msg.Hdr, pCtx->idClient, VBOX_SHCL_GUEST_FN_DATA_WRITE, VBOX_SHCL_CPARMS_DATA_WRITE);
2581 Msg.Parms.id64Context.SetUInt64(pCtx->idContext);
2582 Msg.Parms.f32Format.SetUInt32(uFormat);
2583 Msg.Parms.pData.SetPtr(pvData, cbData);
2584
2585 LogFlowFunc(("CID=%RU32\n", pCtx->idContext));
2586
2587 rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
2588 }
2589
2590 LogFlowFuncLeaveRC(rc);
2591 return rc;
2592}
2593
2594/**
2595 * Writes an error to the host.
2596 *
2597 * @returns IPRT status code.
2598 * @param idClient The client id returned by VbglR3ClipboardConnect().
2599 * @param rcErr Error (IPRT-style) to send.
2600 */
2601VBGLR3DECL(int) VbglR3ClipboardWriteError(HGCMCLIENTID idClient, int rcErr)
2602{
2603 AssertReturn(idClient, VERR_INVALID_PARAMETER);
2604
2605 VBoxShClWriteErrorMsg Msg;
2606 RT_ZERO(Msg);
2607
2608 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHCL_GUEST_FN_ERROR, VBOX_SHCL_CPARMS_ERROR);
2609
2610 /** @todo Context ID not used yet. */
2611 Msg.uContext.SetUInt64(0);
2612 Msg.rc.SetUInt32((uint32_t)rcErr); /* uint32_t vs. int. */
2613
2614 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
2615
2616 if (RT_FAILURE(rc))
2617 LogFlowFunc(("Sending error %Rrc failed with rc=%Rrc\n", rcErr, rc));
2618 if (rc == VERR_NOT_SUPPORTED)
2619 rc = VINF_SUCCESS;
2620
2621 if (RT_FAILURE(rc))
2622 LogRel(("Shared Clipboard: Reporting error %Rrc to the host failed with %Rrc\n", rcErr, rc));
2623
2624 LogFlowFuncLeaveRC(rc);
2625 return rc;
2626}
2627
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