VirtualBox

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

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

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