VirtualBox

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

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

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

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