VirtualBox

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

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

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette