VirtualBox

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

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

Vbgl: clipboard fixes. bugref:9437

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