VirtualBox

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

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

Shared Clipboard/Transfers: Added VbglR3ClipboardTransferSetCallbacks(). ​bugref:9437

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