VirtualBox

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

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

Shared Clipboard/Transfers: Cleaned up guest feature flag handling in VbglR3ClipboardConnectEx().

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