VirtualBox

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

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

SharedClipboard: Eliminated SHCLFORMATDATA and did some minor darwin cleanups. bugref:9620

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