VirtualBox

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

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

Shared Clipboard/URI: SCM fix.

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