VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-uri.cpp@ 79366

Last change on this file since 79366 was 79366, checked in by vboxsync, 6 years ago

Shared Clipboard/URI: Update.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 40.6 KB
Line 
1/* $Id: VBoxSharedClipboardSvc-uri.cpp 79366 2019-06-26 15:59:30Z vboxsync $ */
2/** @file
3 * Shared Clipboard Service - Internal code for URI (list) handling.
4 */
5
6/*
7 * Copyright (C) 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
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_SHARED_CLIPBOARD
23#include <VBox/log.h>
24
25#include <VBox/err.h>
26
27#include <VBox/HostServices/VBoxClipboardSvc.h>
28#include <VBox/HostServices/VBoxClipboardExt.h>
29
30#include <iprt/dir.h>
31#include <iprt/file.h>
32#include <iprt/path.h>
33
34#include "VBoxSharedClipboardSvc-internal.h"
35#include "VBoxSharedClipboardSvc-uri.h"
36
37
38/*********************************************************************************************************************************
39* Externals *
40*********************************************************************************************************************************/
41extern PFNHGCMSVCEXT g_pfnExtension;
42extern void *g_pvExtension;
43
44
45/*********************************************************************************************************************************
46* Provider implementation *
47*********************************************************************************************************************************/
48
49int VBoxSvcClipboardProviderImplURIReadDataHdr(PSHAREDCLIPBOARDPROVIDERCTX pCtx, PVBOXCLIPBOARDDATAHDR *ppDataHdr)
50{
51 LogFlowFuncEnter();
52
53 PVBOXCLIPBOARDCLIENTDATA pClientData = (PVBOXCLIPBOARDCLIENTDATA)pCtx->pvUser;
54 AssertPtr(pClientData);
55
56 PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
57 int rc = SharedClipboardURITransferEventWait(pCtx->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_METADATA_HDR,
58 30 * 1000 /* Timeout in ms */, &pPayload);
59 if (RT_SUCCESS(rc))
60 {
61 Assert(pPayload->cbData == sizeof(VBOXCLIPBOARDDATAHDR));
62 *ppDataHdr = (PVBOXCLIPBOARDDATAHDR)pPayload->pvData;
63
64 RTMemFree(pPayload);
65 }
66
67 LogFlowFuncLeaveRC(rc);
68 return rc;
69}
70
71int VBoxSvcClipboardProviderImplURIWriteDataHdr(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const PVBOXCLIPBOARDDATAHDR pDataHdr)
72{
73 RT_NOREF(pCtx, pDataHdr);
74
75 LogFlowFuncEnter();
76
77 return VERR_NOT_IMPLEMENTED;
78}
79
80int VBoxSvcClipboardProviderImplURIReadDataChunk(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const PVBOXCLIPBOARDDATAHDR pDataHdr,
81 void *pvChunk, uint32_t cbChunk, uint32_t fFlags, uint32_t *pcbRead)
82{
83 RT_NOREF(pDataHdr, fFlags);
84
85 LogFlowFuncEnter();
86
87 PVBOXCLIPBOARDCLIENTDATA pClientData = (PVBOXCLIPBOARDCLIENTDATA)pCtx->pvUser;
88 AssertPtr(pClientData);
89
90 PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
91 int rc = SharedClipboardURITransferEventWait(pCtx->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_METADATA_CHUNK,
92 30 * 1000 /* Timeout in ms */, &pPayload);
93 if (RT_SUCCESS(rc))
94 {
95 Assert(pPayload->cbData == sizeof(VBOXCLIPBOARDDATACHUNK));
96
97 const uint32_t cbToRead = RT_MIN(cbChunk, pPayload->cbData);
98
99 memcpy(pvChunk, pPayload->pvData, cbToRead);
100
101 SharedClipboardURITransferPayloadFree(pPayload);
102
103 if (pcbRead)
104 *pcbRead = cbToRead;
105 }
106
107 LogFlowFuncLeaveRC(rc);
108 return rc;
109}
110
111int VBoxSvcClipboardProviderImplURIWriteDataChunk(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const PVBOXCLIPBOARDDATAHDR pDataHdr,
112 const void *pvChunk, uint32_t cbChunk, uint32_t fFlags, uint32_t *pcbWritten)
113{
114 RT_NOREF(pCtx, pDataHdr, pvChunk, cbChunk, fFlags, pcbWritten);
115
116 LogFlowFuncEnter();
117
118 return VERR_NOT_IMPLEMENTED;
119}
120
121int VBoxSvcClipboardProviderImplURIReadDir(PSHAREDCLIPBOARDPROVIDERCTX pCtx, PVBOXCLIPBOARDDIRDATA *ppDirData)
122{
123 RT_NOREF(pCtx, ppDirData);
124
125 LogFlowFuncEnter();
126
127 return VERR_NOT_IMPLEMENTED;
128}
129
130int VBoxSvcClipboardProviderImplURIWriteDir(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const PVBOXCLIPBOARDDIRDATA pDirData)
131{
132 RT_NOREF(pCtx, pDirData);
133
134 LogFlowFuncEnter();
135
136 return VERR_NOT_IMPLEMENTED;
137}
138
139int VBoxSvcClipboardProviderImplURIReadFileHdr(PSHAREDCLIPBOARDPROVIDERCTX pCtx, PVBOXCLIPBOARDFILEHDR *ppFileHdr)
140{
141 RT_NOREF(pCtx, ppFileHdr);
142
143 LogFlowFuncEnter();
144
145 return VERR_NOT_IMPLEMENTED;
146}
147
148int VBoxSvcClipboardProviderImplURIWriteFileHdr(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const PVBOXCLIPBOARDFILEHDR pFileHdr)
149{
150 RT_NOREF(pCtx, pFileHdr);
151
152 LogFlowFuncEnter();
153
154 return VERR_NOT_IMPLEMENTED;
155}
156
157int VBoxSvcClipboardProviderImplURIReadFileData(PSHAREDCLIPBOARDPROVIDERCTX pCtx, void *pvData, uint32_t cbData, uint32_t fFlags,
158 uint32_t *pcbRead)
159{
160 RT_NOREF(pCtx, pvData, cbData, fFlags, pcbRead);
161
162 LogFlowFuncEnter();
163
164 return VERR_NOT_IMPLEMENTED;
165}
166
167int VBoxSvcClipboardProviderImplURIWriteFileData(PSHAREDCLIPBOARDPROVIDERCTX pCtx, void *pvData, uint32_t cbData, uint32_t fFlags,
168 uint32_t *pcbWritten)
169{
170 RT_NOREF(pCtx, pvData, cbData, fFlags, pcbWritten);
171
172 LogFlowFuncEnter();
173
174 return VERR_NOT_IMPLEMENTED;
175}
176
177/*********************************************************************************************************************************
178* URI callbacks *
179*********************************************************************************************************************************/
180
181DECLCALLBACK(void) VBoxSvcClipboardURITransferPrepareCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData)
182{
183 LogFlowFuncEnter();
184
185 LogFlowFuncEnter();
186
187 AssertPtrReturnVoid(pData);
188
189 PVBOXCLIPBOARDCLIENTDATA pClientData = (PVBOXCLIPBOARDCLIENTDATA)pData->pvUser;
190 AssertPtrReturnVoid(pClientData);
191
192 /* Tell the guest that it can start sending URI data. */
193 int rc2 = vboxSvcClipboardReportMsg(pClientData, VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA,
194 VBOX_SHARED_CLIPBOARD_FMT_URI_LIST);
195 AssertRC(rc2);
196
197 rc2 = SharedClipboardURITransferEventRegister(pData->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_METADATA_HDR);
198 AssertRC(rc2);
199 rc2 = SharedClipboardURITransferEventRegister(pData->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_METADATA_CHUNK);
200 AssertRC(rc2);
201}
202
203DECLCALLBACK(void) VBoxSvcClipboardURIDataHeaderCompleteCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData)
204{
205 LogFlowFuncEnter();
206
207 RT_NOREF(pData);
208}
209
210DECLCALLBACK(void) VBoxSvcClipboardURIDataCompleteCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData)
211{
212 LogFlowFuncEnter();
213
214 VBoxClipboardSvcImplURIOnDataHeaderComplete(pData);
215}
216
217DECLCALLBACK(void) VBoxSvcClipboardURITransferCompleteCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData, int rc)
218{
219 LogFlowFuncEnter();
220
221 RT_NOREF(pData, rc);
222
223 LogRel2(("Shared Clipboard: Transfer complete\n"));
224}
225
226DECLCALLBACK(void) VBoxSvcClipboardURITransferCanceledCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData)
227{
228 LogFlowFuncEnter();
229
230 RT_NOREF(pData);
231
232 LogRel2(("Shared Clipboard: Transfer canceled\n"));
233}
234
235DECLCALLBACK(void) VBoxSvcClipboardURITransferErrorCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData, int rc)
236{
237 LogFlowFuncEnter();
238
239 RT_NOREF(pData, rc);
240
241 LogRel(("Shared Clipboard: Transfer failed with %Rrc\n", rc));
242}
243
244/**
245 * Gets an URI data header from HGCM service parameters.
246 *
247 * @returns VBox status code.
248 * @param cParms Number of HGCM parameters supplied in \a paParms.
249 * @param paParms Array of HGCM parameters.
250 * @param pDataHdr Where to store the result.
251 */
252int VBoxSvcClipboardURIGetDataHdr(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDDATAHDR pDataHdr)
253{
254 int rc;
255
256 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_DATA_HDR)
257 {
258 /* Note: Context ID (paParms[0]) not used yet. */
259 rc = HGCMSvcGetU32(&paParms[1], &pDataHdr->uFlags);
260 if (RT_SUCCESS(rc))
261 rc = HGCMSvcGetU32(&paParms[2], &pDataHdr->uScreenId);
262 if (RT_SUCCESS(rc))
263 rc = HGCMSvcGetU64(&paParms[3], &pDataHdr->cbTotal);
264 if (RT_SUCCESS(rc))
265 rc = HGCMSvcGetU32(&paParms[4], &pDataHdr->cbMeta);
266 if (RT_SUCCESS(rc))
267 rc = HGCMSvcGetU32(&paParms[5], &pDataHdr->cbMetaFmt);
268 if (RT_SUCCESS(rc))
269 rc = HGCMSvcGetPv(&paParms[6], &pDataHdr->pvMetaFmt, &pDataHdr->cbMetaFmt);
270 if (RT_SUCCESS(rc))
271 rc = HGCMSvcGetU64(&paParms[7], &pDataHdr->cObjects);
272 if (RT_SUCCESS(rc))
273 rc = HGCMSvcGetU32(&paParms[8], &pDataHdr->enmCompression);
274 if (RT_SUCCESS(rc))
275 rc = HGCMSvcGetU32(&paParms[9], (uint32_t *)&pDataHdr->enmChecksumType);
276 if (RT_SUCCESS(rc))
277 rc = HGCMSvcGetU32(&paParms[10], &pDataHdr->cbChecksum);
278 if (RT_SUCCESS(rc))
279 rc = HGCMSvcGetPv(&paParms[11], &pDataHdr->pvChecksum, &pDataHdr->cbChecksum);
280
281 LogFlowFunc(("fFlags=0x%x, cbMeta=%RU32, cbTotalSize=%RU64, cObj=%RU64\n",
282 pDataHdr->uFlags, pDataHdr->cbMeta, pDataHdr->cbTotal, pDataHdr->cObjects));
283
284 if (RT_SUCCESS(rc))
285 {
286 /** @todo Validate pvMetaFmt + cbMetaFmt. */
287 /** @todo Validate header checksum. */
288 }
289 }
290 else
291 rc = VERR_INVALID_PARAMETER;
292
293 LogFlowFuncLeaveRC(rc);
294 return rc;
295}
296
297/**
298 * Sets an URI data header to HGCM service parameters.
299 *
300 * @returns VBox status code.
301 * @param cParms Number of HGCM parameters supplied in \a paParms.
302 * @param paParms Array of HGCM parameters.
303 * @param pDataHdr Pointer to data to set to the HGCM parameters.
304 */
305int VBoxSvcClipboardURISetDataHdr(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDDATAHDR pDataHdr)
306{
307 int rc;
308
309 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_READ_DATA_HDR)
310 {
311 /** @todo Set pvMetaFmt + cbMetaFmt. */
312 /** @todo Calculate header checksum. */
313
314 /* Note: Context ID (paParms[0]) not used yet. */
315 HGCMSvcSetU32(&paParms[1], pDataHdr->uFlags);
316 HGCMSvcSetU32(&paParms[2], pDataHdr->uScreenId);
317 HGCMSvcSetU64(&paParms[3], pDataHdr->cbTotal);
318 HGCMSvcSetU32(&paParms[4], pDataHdr->cbMeta);
319 HGCMSvcSetU32(&paParms[5], pDataHdr->cbMetaFmt);
320 HGCMSvcSetPv (&paParms[6], pDataHdr->pvMetaFmt, pDataHdr->cbMetaFmt);
321 HGCMSvcSetU64(&paParms[7], pDataHdr->cObjects);
322 HGCMSvcSetU32(&paParms[8], pDataHdr->enmCompression);
323 HGCMSvcSetU32(&paParms[9], (uint32_t)pDataHdr->enmChecksumType);
324 HGCMSvcSetU32(&paParms[10], pDataHdr->cbChecksum);
325 HGCMSvcSetPv (&paParms[11], pDataHdr->pvChecksum, pDataHdr->cbChecksum);
326
327 LogFlowFunc(("fFlags=0x%x, cbMeta=%RU32, cbTotalSize=%RU64, cObj=%RU64\n",
328 pDataHdr->uFlags, pDataHdr->cbMeta, pDataHdr->cbTotal, pDataHdr->cObjects));
329
330 rc = VINF_SUCCESS;
331 }
332 else
333 rc = VERR_INVALID_PARAMETER;
334
335 LogFlowFuncLeaveRC(rc);
336 return rc;
337}
338
339/**
340 * Gets an URI data chunk from HGCM service parameters.
341 *
342 * @returns VBox status code.
343 * @param cParms Number of HGCM parameters supplied in \a paParms.
344 * @param paParms Array of HGCM parameters.
345 * @param pDataChunk Where to store the result.
346 */
347int VBoxSvcClipboardURIGetDataChunk(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDDATACHUNK pDataChunk)
348{
349 int rc;
350
351 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_DATA_CHUNK)
352 {
353 /* Note: Context ID (paParms[0]) not used yet. */
354 rc = HGCMSvcGetU32(&paParms[1], &pDataChunk->cbData);
355 if (RT_SUCCESS(rc))
356 rc = HGCMSvcGetPv(&paParms[2], &pDataChunk->pvData, &pDataChunk->cbData);
357 if (RT_SUCCESS(rc))
358 rc = HGCMSvcGetU32(&paParms[3], &pDataChunk->cbChecksum);
359 if (RT_SUCCESS(rc))
360 rc = HGCMSvcGetPv(&paParms[4], &pDataChunk->pvChecksum, &pDataChunk->cbChecksum);
361
362 if (RT_SUCCESS(rc))
363 {
364 if (!SharedClipboardURIDataChunkIsValid(pDataChunk))
365 rc = VERR_INVALID_PARAMETER;
366 }
367 }
368 else
369 rc = VERR_INVALID_PARAMETER;
370
371 LogFlowFuncLeaveRC(rc);
372 return rc;
373}
374
375/**
376 * Sets an URI data chunk to HGCM service parameters.
377 *
378 * @returns VBox status code.
379 * @param cParms Number of HGCM parameters supplied in \a paParms.
380 * @param paParms Array of HGCM parameters.
381 * @param pDataChunk Pointer to data to set to the HGCM parameters.
382 */
383int VBoxSvcClipboardURISetDataChunk(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDDATACHUNK pDataChunk)
384{
385 int rc;
386
387 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_READ_DATA_CHUNK)
388 {
389 /** @todo Calculate chunk checksum. */
390
391 /* Note: Context ID (paParms[0]) not used yet. */
392 HGCMSvcSetU32(&paParms[1], pDataChunk->cbData);
393 HGCMSvcSetPv (&paParms[2], pDataChunk->pvData, pDataChunk->cbData);
394 HGCMSvcSetU32(&paParms[3], pDataChunk->cbChecksum);
395 HGCMSvcSetPv (&paParms[4], pDataChunk->pvChecksum, pDataChunk->cbChecksum);
396
397 rc = VINF_SUCCESS;
398 }
399 else
400 rc = VERR_INVALID_PARAMETER;
401
402 LogFlowFuncLeaveRC(rc);
403 return rc;
404}
405
406/**
407 * Gets an URI directory entry from HGCM service parameters.
408 *
409 * @returns VBox status code.
410 * @param cParms Number of HGCM parameters supplied in \a paParms.
411 * @param paParms Array of HGCM parameters.
412 * @param pDirData Where to store the result.
413 */
414int VBoxSvcClipboardURIGetDir(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDDIRDATA pDirData)
415{
416 int rc;
417
418 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_DIR)
419 {
420 /* Note: Context ID (paParms[0]) not used yet. */
421 rc = HGCMSvcGetU32(&paParms[1], &pDirData->cbPath);
422 if (RT_SUCCESS(rc))
423 rc = HGCMSvcGetPv(&paParms[2], (void **)&pDirData->pszPath, &pDirData->cbPath);
424 if (RT_SUCCESS(rc))
425 rc = HGCMSvcGetU32(&paParms[3], &pDirData->fMode);
426
427 LogFlowFunc(("pszPath=%s, cbPath=%RU32, fMode=0x%x\n", pDirData->pszPath, pDirData->cbPath, pDirData->fMode));
428
429 if (RT_SUCCESS(rc))
430 {
431 if (!SharedClipboardURIDirDataIsValid(pDirData))
432 rc = VERR_INVALID_PARAMETER;
433 }
434 }
435 else
436 rc = VERR_INVALID_PARAMETER;
437
438 LogFlowFuncLeaveRC(rc);
439 return rc;
440}
441
442/**
443 * Sets an URI directory entry to HGCM service parameters.
444 *
445 * @returns VBox status code.
446 * @param cParms Number of HGCM parameters supplied in \a paParms.
447 * @param paParms Array of HGCM parameters.
448 * @param pDirData Pointer to data to set to the HGCM parameters.
449 */
450int VBoxSvcClipboardURISetDir(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDDIRDATA pDirData)
451{
452 int rc;
453
454 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_READ_DIR)
455 {
456 /* Note: Context ID (paParms[0]) not used yet. */
457 HGCMSvcSetU32(&paParms[1], pDirData->cbPath);
458 HGCMSvcSetPv (&paParms[2], pDirData->pszPath, pDirData->cbPath);
459 HGCMSvcSetU32(&paParms[3], pDirData->fMode);
460
461 rc = VINF_SUCCESS;
462 }
463 else
464 rc = VERR_INVALID_PARAMETER;
465
466 LogFlowFuncLeaveRC(rc);
467 return rc;
468}
469
470/**
471 * Reads an URI file header from HGCM service parameters.
472 *
473 * @returns VBox status code.
474 * @param cParms Number of HGCM parameters supplied in \a paParms.
475 * @param paParms Array of HGCM parameters.
476 * @param pFileHdr Where to store the result.
477 */
478int VBoxSvcClipboardURIGetFileHdr(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDFILEHDR pFileHdr)
479{
480 int rc;
481
482 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_FILE_HDR)
483 {
484 /* Note: Context ID (paParms[0]) not used yet. */
485 rc = HGCMSvcGetU32(&paParms[1], &pFileHdr->cbFilePath);
486 if (RT_SUCCESS(rc))
487 rc = HGCMSvcGetPv(&paParms[2], (void **)&pFileHdr->pszFilePath, &pFileHdr->cbFilePath);
488 if (RT_SUCCESS(rc))
489 rc = HGCMSvcGetU32(&paParms[3], &pFileHdr->fFlags);
490 if (RT_SUCCESS(rc))
491 rc = HGCMSvcGetU32(&paParms[4], &pFileHdr->fMode);
492 if (RT_SUCCESS(rc))
493 rc = HGCMSvcGetU64(&paParms[5], &pFileHdr->cbSize);
494
495 LogFlowFunc(("pszPath=%s, cbPath=%RU32, fMode=0x%x, cbSize=%RU64\n",
496 pFileHdr->pszFilePath, pFileHdr->cbFilePath, pFileHdr->fMode, pFileHdr->cbSize));
497 }
498 else
499 rc = VERR_INVALID_PARAMETER;
500
501 LogFlowFuncLeaveRC(rc);
502 return rc;
503}
504
505/**
506 * Sets an URI file header to HGCM service parameters.
507 *
508 * @returns VBox status code.
509 * @param cParms Number of HGCM parameters supplied in \a paParms.
510 * @param paParms Array of HGCM parameters.
511 * @param pFileHdr Pointer to data to set to the HGCM parameters.
512 */
513int VBoxSvcClipboardURISetFileHdr(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDFILEHDR pFileHdr)
514{
515 int rc;
516
517 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_READ_FILE_HDR)
518 {
519 /* Note: Context ID (paParms[0]) not used yet. */
520 HGCMSvcSetU32(&paParms[1], pFileHdr->cbFilePath);
521 HGCMSvcSetPv (&paParms[2], pFileHdr->pszFilePath, pFileHdr->cbFilePath);
522 HGCMSvcSetU32(&paParms[3], pFileHdr->fFlags);
523 HGCMSvcSetU32(&paParms[4], pFileHdr->fMode);
524 HGCMSvcSetU64(&paParms[5], pFileHdr->cbSize);
525
526 rc = VINF_SUCCESS;
527 }
528 else
529 rc = VERR_INVALID_PARAMETER;
530
531 LogFlowFuncLeaveRC(rc);
532 return rc;
533}
534
535/**
536 * Gets an URI file data chunk from HGCM service parameters.
537 *
538 * @returns VBox status code.
539 * @param cParms Number of HGCM parameters supplied in \a paParms.
540 * @param paParms Array of HGCM parameters.
541 * @param pFileData Where to store the result.
542 */
543int VBoxSvcClipboardURIGetFileData(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDFILEDATA pFileData)
544{
545 int rc;
546
547 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_FILE_DATA)
548 {
549 /* Note: Context ID (paParms[0]) not used yet. */
550 rc = HGCMSvcGetU32(&paParms[1], &pFileData->cbData);
551 if (RT_SUCCESS(rc))
552 rc = HGCMSvcGetPv(&paParms[2], &pFileData->pvData, &pFileData->cbData);
553 if (RT_SUCCESS(rc))
554 rc = HGCMSvcGetU32(&paParms[3], &pFileData->cbChecksum);
555 if (RT_SUCCESS(rc))
556 rc = HGCMSvcGetPv(&paParms[4], &pFileData->pvChecksum, &pFileData->cbChecksum);
557
558 LogFlowFunc(("pvData=0x%p, cbData=%RU32\n", pFileData->pvData, pFileData->cbData));
559 }
560 else
561 rc = VERR_INVALID_PARAMETER;
562
563 LogFlowFuncLeaveRC(rc);
564 return rc;
565}
566
567/**
568 * Sets an URI file data chunk to HGCM service parameters.
569 *
570 * @returns VBox status code.
571 * @param cParms Number of HGCM parameters supplied in \a paParms.
572 * @param paParms Array of HGCM parameters.
573 * @param pFileData Pointer to data to set to the HGCM parameters.
574 */
575int VBoxSvcClipboardURISetFileData(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDFILEDATA pFileData)
576{
577 int rc;
578
579 if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_READ_FILE_DATA)
580 {
581 /* Note: Context ID (paParms[0]) not used yet. */
582 HGCMSvcSetU32(&paParms[1], pFileData->cbData);
583 HGCMSvcSetPv (&paParms[2], pFileData->pvData, pFileData->cbData);
584 HGCMSvcSetU32(&paParms[3], pFileData->cbChecksum);
585 HGCMSvcSetPv (&paParms[4], pFileData->pvChecksum, pFileData->cbChecksum);
586
587 rc = VINF_SUCCESS;
588 }
589 else
590 rc = VERR_INVALID_PARAMETER;
591
592 LogFlowFuncLeaveRC(rc);
593 return rc;
594}
595
596/**
597 * URI client (guest) handler for the Shared Clipboard host service.
598 *
599 * @returns VBox status code.
600 * @param u32ClientID Client ID of the client which called this handler.
601 * @param pvClient Pointer to client-specific data block.
602 * @param u32Function Function number being called.
603 * @param cParms Number of function parameters supplied.
604 * @param paParms Array function parameters supplied.
605 * @param tsArrival Timestamp of arrival.
606 * @param pfAsync Returns \c true if the response needs to be being asynchronous or \c false if not,
607 */
608int vboxSvcClipboardURIHandler(uint32_t u32ClientID,
609 void *pvClient,
610 uint32_t u32Function,
611 uint32_t cParms,
612 VBOXHGCMSVCPARM paParms[],
613 uint64_t tsArrival,
614 bool *pfAsync)
615{
616 RT_NOREF(u32ClientID, paParms, tsArrival, pfAsync);
617
618 LogFlowFunc(("u32ClientID=%RU32, u32Function=%RU32, cParms=%RU32, g_pfnExtension=%p\n",
619 u32ClientID, u32Function, cParms, g_pfnExtension));
620
621 const PVBOXCLIPBOARDCLIENTDATA pClientData = (PVBOXCLIPBOARDCLIENTDATA)pvClient;
622 AssertPtrReturn(pClientData, VERR_INVALID_POINTER);
623
624 /* Check if we've the right mode set. */
625 if (!vboxSvcClipboardURIMsgIsAllowed(vboxSvcClipboardGetMode(), u32Function))
626 return VERR_ACCESS_DENIED;
627
628 /* A (valid) service extension is needed because VBoxSVC needs to keep track of the
629 * clipboard areas cached on the host. */
630 if (!g_pfnExtension)
631 {
632#ifdef DEBUG_andy
633 AssertPtr(g_pfnExtension);
634#endif
635 LogFunc(("Invalid / no service extension set, skipping URI handling\n"));
636 return VERR_NOT_SUPPORTED;
637 }
638
639 if (!SharedClipboardURICtxGetTotalTransfers(&pClientData->URI))
640 {
641 LogFunc(("No transfers found\n"));
642 return VERR_WRONG_ORDER;
643 }
644
645 const uint32_t uTransferID = 0; /* Only one transfer is supported at the moment. */
646
647 const PSHAREDCLIPBOARDURITRANSFER pTransfer = SharedClipboardURICtxGetTransfer(&pClientData->URI, uTransferID);
648 if (!pTransfer)
649 {
650 LogFunc(("Transfer with ID %RU32 not found\n", uTransferID));
651 return VERR_WRONG_ORDER;
652 }
653
654 bool fWriteToProvider = false; /* Whether to (also) dispatch the HGCM data to the transfer provider. */
655
656 int rc = VERR_INVALID_PARAMETER; /* Play safe. */
657
658 switch (u32Function)
659 {
660 case VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_DATA_HDR:
661 {
662 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_DATA_HDR\n"));
663
664 VBOXCLIPBOARDDATAHDR dataHdr;
665 rc = VBoxSvcClipboardURISetDataHdr(cParms, paParms, &dataHdr);
666 break;
667 }
668
669 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DATA_HDR:
670 {
671 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DATA_HDR\n"));
672
673 VBOXCLIPBOARDDATAHDR dataHdr;
674 rc = SharedClipboardURIDataHdrInit(&dataHdr);
675 if (RT_SUCCESS(rc))
676 {
677 rc = VBoxSvcClipboardURIGetDataHdr(cParms, paParms, &dataHdr);
678 if (RT_SUCCESS(rc))
679 {
680 void *pvData = SharedClipboardURIDataHdrDup(&dataHdr);
681 uint32_t cbData = sizeof(VBOXCLIPBOARDDATAHDR);
682
683 PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
684 rc = SharedClipboardURITransferPayloadAlloc(SHAREDCLIPBOARDURITRANSFEREVENTTYPE_METADATA_HDR,
685 pvData, cbData, &pPayload);
686 if (RT_SUCCESS(rc))
687 {
688 rc = SharedClipboardURITransferEventSignal(pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_METADATA_HDR,
689 pPayload);
690 }
691 }
692 }
693 break;
694 }
695
696 case VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_DATA_CHUNK:
697 {
698 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_DATA_CHUNK\n"));
699 break;
700 }
701
702 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DATA_CHUNK:
703 {
704 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DATA_CHUNK\n"));
705
706 VBOXCLIPBOARDDATACHUNK dataChunk;
707 rc = SharedClipboardURIDataChunkInit(&dataChunk);
708 if (RT_SUCCESS(rc))
709 {
710 rc = VBoxSvcClipboardURIGetDataChunk(cParms, paParms, &dataChunk);
711 if (RT_SUCCESS(rc))
712 {
713 void *pvData = SharedClipboardURIDataChunkDup(&dataChunk);
714 uint32_t cbData = sizeof(VBOXCLIPBOARDDATACHUNK);
715
716 PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
717 rc = SharedClipboardURITransferPayloadAlloc(SHAREDCLIPBOARDURITRANSFEREVENTTYPE_METADATA_CHUNK,
718 pvData, cbData, &pPayload);
719 if (RT_SUCCESS(rc))
720 {
721 rc = SharedClipboardURITransferEventSignal(pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_METADATA_CHUNK,
722 pPayload);
723 }
724
725 }
726 }
727 break;
728 }
729
730 case VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_DIR:
731 {
732 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_DIR\n"));
733
734 VBOXCLIPBOARDDIRDATA data;
735 rc = VBoxSvcClipboardURISetDir(cParms, paParms, &data);
736 break;
737 }
738
739 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DIR:
740 {
741 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DIR\n"));
742
743 VBOXCLIPBOARDDIRDATA dirData;
744 rc = VBoxSvcClipboardURIGetDir(cParms, paParms, &dirData);
745 if (RT_SUCCESS(rc))
746 {
747 SharedClipboardArea *pArea = SharedClipboardURITransferGetArea(pTransfer);
748 AssertPtrBreakStmt(pArea, rc = VERR_INVALID_POINTER);
749
750 const char *pszCacheDir = pArea->GetDirAbs();
751 char *pszDir = RTPathJoinA(pszCacheDir, dirData.pszPath);
752 if (pszDir)
753 {
754 LogFlowFunc(("pszDir=%s\n", pszDir));
755
756 rc = RTDirCreateFullPath(pszDir, dirData.fMode);
757 if (RT_SUCCESS(rc))
758 {
759 SHAREDCLIPBOARDAREAOBJ Obj = { SHAREDCLIPBOARDAREAOBJTYPE_DIR, SHAREDCLIPBOARDAREAOBJSTATE_COMPLETE };
760 int rc2 = pArea->AddObject(pszDir, Obj);
761 AssertRC(rc2);
762 }
763
764 RTStrFree(pszDir);
765 }
766 else
767 rc = VERR_NO_MEMORY;
768 }
769 break;
770 }
771
772 case VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_FILE_HDR:
773 {
774 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_FILE_HDR\n"));
775
776 VBOXCLIPBOARDFILEHDR fileHdr;
777 rc = VBoxSvcClipboardURISetFileHdr(cParms, paParms, &fileHdr);
778 break;
779 }
780
781 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_FILE_HDR:
782 {
783 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_FILE_HDR\n"));
784
785 if (!SharedClipboardURIObjCtxIsValid(SharedClipboardURITransferGetCurrentObjCtx(pTransfer)))
786 {
787 pTransfer->State.ObjCtx.pObj = new SharedClipboardURIObject(SharedClipboardURIObject::Type_File);
788 if (pTransfer->State.ObjCtx.pObj) /** @todo Can this throw? */
789 {
790 rc = VINF_SUCCESS;
791 }
792 else
793 rc = VERR_NO_MEMORY;
794 }
795 else /* There still is another object being processed? */
796 rc = VERR_WRONG_ORDER;
797
798 if (RT_FAILURE(rc))
799 break;
800
801 VBOXCLIPBOARDFILEHDR fileHdr;
802 rc = VBoxSvcClipboardURIGetFileHdr(cParms, paParms, &fileHdr);
803 if (RT_SUCCESS(rc))
804 {
805 SharedClipboardArea *pArea = SharedClipboardURITransferGetArea(pTransfer);
806 AssertPtrBreakStmt(pArea, rc = VERR_WRONG_ORDER);
807
808 const char *pszCacheDir = pArea->GetDirAbs();
809
810 char pszPathAbs[RTPATH_MAX];
811 rc = RTPathJoin(pszPathAbs, sizeof(pszPathAbs), pszCacheDir, fileHdr.pszFilePath);
812 if (RT_SUCCESS(rc))
813 {
814 rc = SharedClipboardPathSanitize(pszPathAbs, sizeof(pszPathAbs));
815 if (RT_SUCCESS(rc))
816 {
817 PSHAREDCLIPBOARDCLIENTURIOBJCTX pObjCtx = SharedClipboardURITransferGetCurrentObjCtx(pTransfer);
818 AssertPtrBreakStmt(pObjCtx, VERR_INVALID_POINTER);
819
820 SharedClipboardURIObject *pObj = pObjCtx->pObj;
821 AssertPtrBreakStmt(pObj, VERR_INVALID_POINTER);
822
823 LogFlowFunc(("pszFile=%s\n", pszPathAbs));
824
825 /** @todo Add sparse file support based on fFlags? (Use Open(..., fFlags | SPARSE). */
826 rc = pObj->OpenFileEx(pszPathAbs, SharedClipboardURIObject::View_Target,
827 RTFILE_O_CREATE_REPLACE | RTFILE_O_WRITE | RTFILE_O_DENY_WRITE,
828 (fileHdr.fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR);
829 if (RT_SUCCESS(rc))
830 {
831 rc = pObj->SetSize(fileHdr.cbSize);
832
833 /** @todo Unescape path before printing. */
834 LogRel2(("Clipboard: Transferring guest file '%s' to host (%RU64 bytes, mode 0x%x)\n",
835 pObj->GetDestPathAbs().c_str(), pObj->GetSize(), pObj->GetMode()));
836
837 if (pObj->IsComplete()) /* 0-byte file? We're done already. */
838 {
839 /** @todo Sanitize path. */
840 LogRel2(("Clipboard: Transferring guest file '%s' (0 bytes) to host complete\n",
841 pObj->GetDestPathAbs().c_str()));
842
843 SharedClipboardURIObjCtxDestroy(&pTransfer->State.ObjCtx);
844 }
845
846 SHAREDCLIPBOARDAREAOBJ Obj = { SHAREDCLIPBOARDAREAOBJTYPE_FILE, SHAREDCLIPBOARDAREAOBJSTATE_NONE };
847 int rc2 = pArea->AddObject(pszPathAbs, Obj);
848 AssertRC(rc2);
849 }
850 else
851 LogRel(("Clipboard: Error opening/creating guest file '%s' on host, rc=%Rrc\n", pszPathAbs, rc));
852 }
853 }
854 }
855 break;
856 }
857
858 case VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_FILE_DATA:
859 {
860 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_READ_FILE_DATA\n"));
861
862 VBOXCLIPBOARDFILEDATA fileData;
863 rc = VBoxSvcClipboardURISetFileData(cParms, paParms, &fileData);
864 break;
865 }
866
867 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_FILE_DATA:
868 {
869 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_FILE_DATA\n"));
870
871 if (!SharedClipboardURIObjCtxIsValid(&pTransfer->State.ObjCtx))
872 {
873 rc = VERR_WRONG_ORDER;
874 break;
875 }
876
877 VBOXCLIPBOARDFILEDATA fileData;
878 rc = VBoxSvcClipboardURIGetFileData(cParms, paParms, &fileData);
879 if (RT_SUCCESS(rc))
880 {
881 PSHAREDCLIPBOARDCLIENTURIOBJCTX pObjCtx = SharedClipboardURITransferGetCurrentObjCtx(pTransfer);
882 AssertPtrBreakStmt(pObjCtx, VERR_INVALID_POINTER);
883
884 SharedClipboardURIObject *pObj = pObjCtx->pObj;
885 AssertPtrBreakStmt(pObj, VERR_INVALID_POINTER);
886
887 uint32_t cbWritten;
888 rc = pObj->Write(fileData.pvData, fileData.cbData, &cbWritten);
889 if (RT_SUCCESS(rc))
890 {
891 Assert(cbWritten <= fileData.cbData);
892 if (cbWritten < fileData.cbData)
893 {
894 /** @todo What to do when the host's disk is full? */
895 rc = VERR_DISK_FULL;
896 }
897
898 if ( pObj->IsComplete()
899 || RT_FAILURE(rc))
900 SharedClipboardURIObjCtxDestroy(&pTransfer->State.ObjCtx);
901 }
902 else
903 LogRel(("Clipboard: Error writing guest file data for '%s', rc=%Rrc\n", pObj->GetDestPathAbs().c_str(), rc));
904 }
905 break;
906 }
907
908 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_CANCEL:
909 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_CANCEL\n"));
910 AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED);
911 break;
912
913 case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_ERROR:
914 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_ERROR\n"));
915 AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED);
916 break;
917
918 default:
919 AssertMsgFailed(("Not implemented\n"));
920 break;
921 }
922
923 if (fWriteToProvider)
924 rc = VINF_SUCCESS;
925
926 if (RT_SUCCESS(rc))
927 {
928 if (fWriteToProvider)
929 {
930 SHAREDCLIPBOARDPROVIDERWRITEPARMS writeParms;
931 RT_ZERO(writeParms);
932
933 writeParms.u.HostService.uMsg = u32Function;
934 writeParms.u.HostService.cParms = cParms;
935 writeParms.u.HostService.paParms = paParms;
936
937 //rc = pTransfer->pProvider->OnWrite(&writeParms);
938 }
939 }
940
941 LogFlowFuncLeaveRC(rc);
942 return rc;
943}
944
945/**
946 * URI host handler for the Shared Clipboard host service.
947 *
948 * @returns VBox status code.
949 * @param u32Function Function number being called.
950 * @param cParms Number of function parameters supplied.
951 * @param paParms Array function parameters supplied.
952 */
953int vboxSvcClipboardURIHostHandler(uint32_t u32Function,
954 uint32_t cParms,
955 VBOXHGCMSVCPARM paParms[])
956{
957 RT_NOREF(cParms, paParms);
958
959 int rc = VERR_INVALID_PARAMETER; /* Play safe. */
960
961 switch (u32Function)
962 {
963 case VBOX_SHARED_CLIPBOARD_HOST_FN_CANCEL:
964 AssertFailed(); /** @todo Implement this. */
965 break;
966
967 case VBOX_SHARED_CLIPBOARD_HOST_FN_ERROR:
968 AssertFailed(); /** @todo Implement this. */
969 break;
970
971 default:
972 AssertMsgFailed(("Not implemented\n"));
973 break;
974
975 }
976
977 LogFlowFuncLeaveRC(rc);
978 return rc;
979}
980
981/**
982 * Registers an URI clipboard area.
983 *
984 * @returns VBox status code.
985 * @param pClientState Client state to use.
986 * @param pTransfer URI transfer to register a clipboard area for.
987 */
988int vboxSvcClipboardURIAreaRegister(PVBOXCLIPBOARDCLIENTSTATE pClientState, PSHAREDCLIPBOARDURITRANSFER pTransfer)
989{
990 LogFlowFuncEnter();
991
992 AssertMsgReturn(pTransfer->pArea == NULL, ("An area already is registered for this transfer\n"),
993 VERR_WRONG_ORDER);
994
995 pTransfer->pArea = new SharedClipboardArea();
996 if (!pTransfer->pArea)
997 return VERR_NO_MEMORY;
998
999 int rc;
1000
1001 if (g_pfnExtension)
1002 {
1003 VBOXCLIPBOARDEXTAREAPARMS parms;
1004 RT_ZERO(parms);
1005
1006 parms.uID = NIL_SHAREDCLIPBOARDAREAID;
1007
1008 if (pTransfer->State.pMeta)
1009 {
1010 parms.u.fn_register.pvData = SharedClipboardMetaDataMutableRaw(pTransfer->State.pMeta);
1011 parms.u.fn_register.cbData = (uint32_t)SharedClipboardMetaDataGetUsed(pTransfer->State.pMeta);
1012 }
1013
1014 /* As the meta data is now complete, register a new clipboard on the host side. */
1015 rc = g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_AREA_REGISTER, &parms, sizeof(parms));
1016 if (RT_SUCCESS(rc))
1017 {
1018 /* Note: Do *not* specify SHAREDCLIPBOARDAREA_OPEN_FLAGS_MUST_NOT_EXIST as flags here, as VBoxSVC took care of the
1019 * clipboard area creation already. */
1020 rc = pTransfer->pArea->OpenTemp(parms.uID /* Area ID */,
1021 SHAREDCLIPBOARDAREA_OPEN_FLAGS_NONE);
1022 }
1023
1024 LogFlowFunc(("Registered new clipboard area (%RU32) by client %RU32 with rc=%Rrc\n",
1025 parms.uID, pClientState->u32ClientID, rc));
1026 }
1027 else
1028 rc = VERR_NOT_SUPPORTED;
1029
1030 LogFlowFuncLeaveRC(rc);
1031 return rc;
1032}
1033
1034/**
1035 * Unregisters an URI clipboard area.
1036 *
1037 * @returns VBox status code.
1038 * @param pClientState Client state to use.
1039 * @param pTransfer URI transfer to unregister a clipboard area from.
1040 */
1041int vboxSvcClipboardURIAreaUnregister(PVBOXCLIPBOARDCLIENTSTATE pClientState, PSHAREDCLIPBOARDURITRANSFER pTransfer)
1042{
1043 LogFlowFuncEnter();
1044
1045 if (!pTransfer->pArea)
1046 return VINF_SUCCESS;
1047
1048 int rc = VINF_SUCCESS;
1049
1050 if (g_pfnExtension)
1051 {
1052 VBOXCLIPBOARDEXTAREAPARMS parms;
1053 RT_ZERO(parms);
1054
1055 parms.uID = pTransfer->pArea->GetID();
1056
1057 rc = g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_AREA_UNREGISTER, &parms, sizeof(parms));
1058 if (RT_SUCCESS(rc))
1059 {
1060 rc = pTransfer->pArea->Close();
1061 if (RT_SUCCESS(rc))
1062 {
1063 delete pTransfer->pArea;
1064 pTransfer->pArea = NULL;
1065 }
1066 }
1067
1068 LogFlowFunc(("Unregistered clipboard area (%RU32) by client %RU32 with rc=%Rrc\n",
1069 parms.uID, pClientState->u32ClientID, rc));
1070 }
1071
1072 delete pTransfer->pArea;
1073 pTransfer->pArea = NULL;
1074
1075 LogFlowFuncLeaveRC(rc);
1076 return rc;
1077}
1078
1079/**
1080 * Attaches to an existing (registered) URI clipboard area.
1081 *
1082 * @returns VBox status code.
1083 * @param pClientState Client state to use.
1084 * @param pTransfer URI transfer to attach a clipboard area to.
1085 * @param uID ID of clipboard area to to attach to. Specify 0 to attach to the most recent one.
1086 */
1087int vboxSvcClipboardURIAreaAttach(PVBOXCLIPBOARDCLIENTSTATE pClientState, PSHAREDCLIPBOARDURITRANSFER pTransfer,
1088 SHAREDCLIPBOARDAREAID uID)
1089{
1090 LogFlowFuncEnter();
1091
1092 AssertMsgReturn(pTransfer->pArea == NULL, ("An area already is attached to this transfer\n"),
1093 VERR_WRONG_ORDER);
1094
1095 pTransfer->pArea = new SharedClipboardArea();
1096 if (!pTransfer->pArea)
1097 return VERR_NO_MEMORY;
1098
1099 int rc = VINF_SUCCESS;
1100
1101 if (g_pfnExtension)
1102 {
1103 VBOXCLIPBOARDEXTAREAPARMS parms;
1104 RT_ZERO(parms);
1105
1106 parms.uID = uID; /* 0 means most recent clipboard area. */
1107
1108 /* The client now needs to attach to the most recent clipboard area
1109 * to keep a reference to it. The host does the actual book keeping / cleanup then.
1110 *
1111 * This might fail if the host does not have a most recent clipboard area (yet). */
1112 rc = g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_AREA_ATTACH, &parms, sizeof(parms));
1113 if (RT_SUCCESS(rc))
1114 rc = pTransfer->pArea->OpenTemp(parms.uID /* Area ID */);
1115
1116 LogFlowFunc(("Attached client %RU32 to clipboard area %RU32 with rc=%Rrc\n",
1117 pClientState->u32ClientID, parms.uID, rc));
1118 }
1119 else
1120 rc = VERR_NOT_SUPPORTED;
1121
1122 LogFlowFuncLeaveRC(rc);
1123 return rc;
1124}
1125
1126/**
1127 * Detaches from an URI clipboard area.
1128 *
1129 * @returns VBox status code.
1130 * @param pClientState Client state to use.
1131 * @param pTransfer URI transfer to detach a clipboard area from.
1132 */
1133int vboxSvcClipboardURIAreaDetach(PVBOXCLIPBOARDCLIENTSTATE pClientState, PSHAREDCLIPBOARDURITRANSFER pTransfer)
1134{
1135 LogFlowFuncEnter();
1136
1137 if (!pTransfer->pArea)
1138 return VINF_SUCCESS;
1139
1140 const uint32_t uAreaID = pTransfer->pArea->GetID();
1141
1142 int rc = VINF_SUCCESS;
1143
1144 if (g_pfnExtension)
1145 {
1146 VBOXCLIPBOARDEXTAREAPARMS parms;
1147 RT_ZERO(parms);
1148 parms.uID = uAreaID;
1149
1150 rc = g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_AREA_DETACH, &parms, sizeof(parms));
1151
1152 LogFlowFunc(("Detached client %RU32 from clipboard area %RU32 with rc=%Rrc\n",
1153 pClientState->u32ClientID, uAreaID, rc));
1154 }
1155
1156 delete pTransfer->pArea;
1157 pTransfer->pArea = NULL;
1158
1159 LogFlowFuncLeaveRC(rc);
1160 return rc;
1161}
1162
Note: See TracBrowser for help on using the repository browser.

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