VirtualBox

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

Last change on this file since 94184 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

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