VirtualBox

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

Last change on this file since 85271 was 84997, checked in by vboxsync, 4 years ago

Shared Clipboard/VbglR3: Don't use RT_ZERO on non-POD types.

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette