VirtualBox

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

最後變更 在這個檔案從91740是 91740,由 vboxsync 提交於 3 年 前

VbglR3ClipboardWriteDataEx: Don't validate pvData when cbData == 0, as it's perferectly valid to write a zero byte reply to a host's request. bugref:10094

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

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