VirtualBox

source: vbox/trunk/src/VBox/GuestHost/SharedClipboard/clipboard-uri.cpp@ 80334

最後變更 在這個檔案從80334是 80318,由 vboxsync 提交於 6 年 前

Shared Clipboard/URI: More work on context IDs and entry list handling.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 68.3 KB
 
1/* $Id: clipboard-uri.cpp 80318 2019-08-16 09:13:49Z vboxsync $ */
2/** @file
3 * Shared Clipboard: Common URI transfer handling code.
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.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
18#define LOG_GROUP LOG_GROUP_SHARED_CLIPBOARD
19#include <VBox/log.h>
20
21#include <iprt/dir.h>
22#include <iprt/file.h>
23#include <iprt/path.h>
24#include <iprt/semaphore.h>
25
26#include <VBox/err.h>
27#include <VBox/HostServices/VBoxClipboardSvc.h>
28#include <VBox/GuestHost/SharedClipboard-uri.h>
29
30
31#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
32static int sharedClipboardURITransferThreadCreate(PSHAREDCLIPBOARDURITRANSFER pTransfer, PFNRTTHREAD pfnThreadFunc, void *pvUser);
33static int sharedClipboardURITransferThreadDestroy(PSHAREDCLIPBOARDURITRANSFER pTransfer, RTMSINTERVAL uTimeoutMs);
34static int sharedClipboardURITransferWriteThread(RTTHREAD hThread, void *pvUser);
35static PSHAREDCLIPBOARDURITRANSFER sharedClipboardURICtxGetTransferInternal(PSHAREDCLIPBOARDURICTX pURI, uint32_t uIdx);
36#endif
37
38/** @todo Split this file up in different modules. */
39
40/**
41 * Allocates a new URI root list.
42 *
43 * @returns Allocated URI root list on success, or NULL on failure.
44 */
45PVBOXCLIPBOARDROOTLIST SharedClipboardURIRootListAlloc(void)
46{
47 PVBOXCLIPBOARDROOTLIST pRootList = (PVBOXCLIPBOARDROOTLIST)RTMemAllocZ(sizeof(VBOXCLIPBOARDROOTLIST));
48
49 return pRootList;
50}
51
52/**
53 * Frees an URI root list.
54 *
55 * @param pRootList URI root list to free. The pointer will be
56 * invalid after returning from this function.
57 */
58void SharedClipboardURIRootListFree(PVBOXCLIPBOARDROOTLIST pRootList)
59{
60 if (!pRootList)
61 return;
62
63 for (uint32_t i = 0; i < pRootList->Hdr.cRoots; i++)
64 SharedClipboardURIListEntryDestroy(&pRootList->paEntries[i]);
65
66 RTMemFree(pRootList);
67 pRootList = NULL;
68}
69
70/**
71 * Initializes an URI root list header.
72 *
73 * @returns VBox status code.
74 * @param pRootLstHdr Root list header to initialize.
75 */
76int SharedClipboardURIRootListHdrInit(PVBOXCLIPBOARDROOTLISTHDR pRootLstHdr)
77{
78 AssertPtrReturn(pRootLstHdr, VERR_INVALID_POINTER);
79
80 RT_BZERO(pRootLstHdr, sizeof(VBOXCLIPBOARDROOTLISTHDR));
81
82 return VINF_SUCCESS;
83}
84
85/**
86 * Destroys an URI root list header.
87 *
88 * @param pRootLstHdr Root list header to destroy.
89 */
90void SharedClipboardURIRootListHdrDestroy(PVBOXCLIPBOARDROOTLISTHDR pRootLstHdr)
91{
92 if (!pRootLstHdr)
93 return;
94
95 pRootLstHdr->fRoots = 0;
96 pRootLstHdr->cRoots = 0;
97}
98
99/**
100 * Duplicates an URI list header.
101 *
102 * @returns Duplicated URI list header on success, or NULL on failure.
103 * @param pRootLstHdr Root list header to duplicate.
104 */
105PVBOXCLIPBOARDROOTLISTHDR SharedClipboardURIRootListHdrDup(PVBOXCLIPBOARDROOTLISTHDR pRootLstHdr)
106{
107 AssertPtrReturn(pRootLstHdr, NULL);
108
109 int rc = VINF_SUCCESS;
110
111 PVBOXCLIPBOARDROOTLISTHDR pRootsDup = (PVBOXCLIPBOARDROOTLISTHDR)RTMemAllocZ(sizeof(VBOXCLIPBOARDROOTLISTHDR));
112 if (pRootsDup)
113 {
114 *pRootsDup = *pRootLstHdr;
115 }
116 else
117 rc = VERR_NO_MEMORY;
118
119 if (RT_FAILURE(rc))
120 {
121 SharedClipboardURIRootListHdrDestroy(pRootsDup);
122 pRootsDup = NULL;
123 }
124
125 return pRootsDup;
126}
127
128/**
129 * (Deep) Copies a clipboard root list entry structure.
130 *
131 * @returns VBox status code.
132 * @param pListEntry Clipboard root list entry to copy.
133 */
134int SharedClipboardURIRootListEntryCopy(PVBOXCLIPBOARDROOTLISTENTRY pDst, PVBOXCLIPBOARDROOTLISTENTRY pSrc)
135{
136 return SharedClipboardURIListEntryCopy(pDst, pSrc);
137}
138
139/**
140 * Duplicates (allocates) a clipboard root list entry structure.
141 *
142 * @returns Duplicated clipboard root list entry structure on success.
143 * @param pListEntry Clipboard root list entry to duplicate.
144 */
145PVBOXCLIPBOARDROOTLISTENTRY SharedClipboardURIRootListEntryDup(PVBOXCLIPBOARDROOTLISTENTRY pRootListEntry)
146{
147 return SharedClipboardURIListEntryDup(pRootListEntry);
148}
149
150/**
151 * Destroys a clipboard root list entry structure.
152 *
153 * @param pListEntry Clipboard root list entry structure to destroy.
154 */
155void SharedClipboardURIRootListEntryDestroy(PVBOXCLIPBOARDROOTLISTENTRY pRootListEntry)
156{
157 return SharedClipboardURIListEntryDestroy(pRootListEntry);
158}
159
160/**
161 * Allocates a URI list header structure.
162 *
163 * @returns VBox status code.
164 * @param ppListHdr Where to store the allocated URI list header structure on success.
165 */
166int SharedClipboardURIListHdrAlloc(PVBOXCLIPBOARDLISTHDR *ppListHdr)
167{
168 int rc;
169
170 PVBOXCLIPBOARDLISTHDR pListHdr = (PVBOXCLIPBOARDLISTHDR)RTMemAllocZ(sizeof(VBOXCLIPBOARDLISTHDR));
171 if (pListHdr)
172 {
173 *ppListHdr = pListHdr;
174 rc = VINF_SUCCESS;
175 }
176 else
177 rc = VERR_NO_MEMORY;
178
179 LogFlowFuncLeaveRC(rc);
180 return rc;
181}
182
183/**
184 * Frees an URI list header structure.
185 *
186 * @param pListEntry URI list header structure to free.
187 */
188void SharedClipboardURIListHdrFree(PVBOXCLIPBOARDLISTHDR pListHdr)
189{
190 if (!pListHdr)
191 return;
192
193 LogFlowFuncEnter();
194
195 SharedClipboardURIListHdrDestroy(pListHdr);
196
197 RTMemFree(pListHdr);
198 pListHdr = NULL;
199}
200
201/**
202 * Duplicates (allocates) an URI list header structure.
203 *
204 * @returns Duplicated URI list header structure on success.
205 * @param pListHdr URI list header to duplicate.
206 */
207PVBOXCLIPBOARDLISTHDR SharedClipboardURIListHdrDup(PVBOXCLIPBOARDLISTHDR pListHdr)
208{
209 AssertPtrReturn(pListHdr, NULL);
210
211 PVBOXCLIPBOARDLISTHDR pListHdrDup = (PVBOXCLIPBOARDLISTHDR)RTMemAlloc(sizeof(VBOXCLIPBOARDLISTHDR));
212 if (pListHdrDup)
213 {
214 *pListHdrDup = *pListHdr;
215 }
216
217 return pListHdrDup;
218}
219
220/**
221 * Initializes an URI data header struct.
222 *
223 * @returns VBox status code.
224 * @param pListHdr Data header struct to initialize.
225 */
226int SharedClipboardURIListHdrInit(PVBOXCLIPBOARDLISTHDR pListHdr)
227{
228 AssertPtrReturn(pListHdr, VERR_INVALID_POINTER);
229
230 LogFlowFuncEnter();
231
232 SharedClipboardURIListHdrReset(pListHdr);
233
234 return VINF_SUCCESS;
235}
236
237/**
238 * Destroys an URI data header struct.
239 *
240 * @param pListHdr Data header struct to destroy.
241 */
242void SharedClipboardURIListHdrDestroy(PVBOXCLIPBOARDLISTHDR pListHdr)
243{
244 if (!pListHdr)
245 return;
246
247 LogFlowFuncEnter();
248}
249
250/**
251 * Resets a VBOXCLIPBOARDListHdr structture.
252 *
253 * @returns VBox status code.
254 * @param pListHdr VBOXCLIPBOARDListHdr structture to reset.
255 */
256void SharedClipboardURIListHdrReset(PVBOXCLIPBOARDLISTHDR pListHdr)
257{
258 AssertPtrReturnVoid(pListHdr);
259
260 LogFlowFuncEnter();
261
262 RT_BZERO(pListHdr, sizeof(VBOXCLIPBOARDLISTHDR));
263}
264
265/**
266 * Returns whether a given clipboard data header is valid or not.
267 *
268 * @returns \c true if valid, \c false if not.
269 * @param pListHdr Clipboard data header to validate.
270 */
271bool SharedClipboardURIListHdrIsValid(PVBOXCLIPBOARDLISTHDR pListHdr)
272{
273 RT_NOREF(pListHdr);
274 return true; /** @todo Implement this. */
275}
276
277int SharedClipboardURIListOpenParmsCopy(PVBOXCLIPBOARDLISTOPENPARMS pDst, PVBOXCLIPBOARDLISTOPENPARMS pSrc)
278{
279 AssertPtrReturn(pDst, VERR_INVALID_POINTER);
280 AssertPtrReturn(pSrc, VERR_INVALID_POINTER);
281
282 int rc = VINF_SUCCESS;
283
284 if (pSrc->pszFilter)
285 {
286 pDst->pszFilter = RTStrDup(pSrc->pszFilter);
287 if (!pDst->pszFilter)
288 rc = VERR_NO_MEMORY;
289 }
290
291 if ( RT_SUCCESS(rc)
292 && pSrc->pszPath)
293 {
294 pDst->pszPath = RTStrDup(pSrc->pszPath);
295 if (!pDst->pszPath)
296 rc = VERR_NO_MEMORY;
297 }
298
299 if (RT_SUCCESS(rc))
300 {
301 pDst->fList = pDst->fList;
302 pDst->cbFilter = pSrc->cbFilter;
303 pDst->cbPath = pSrc->cbPath;
304 }
305
306 return rc;
307}
308
309/**
310 * Duplicates an URI list open parameters structure.
311 *
312 * @returns Duplicated URI list open parameters structure on success, or NULL on failure.
313 * @param pParms URI list open parameters structure to duplicate.
314 */
315PVBOXCLIPBOARDLISTOPENPARMS SharedClipboardURIListOpenParmsDup(PVBOXCLIPBOARDLISTOPENPARMS pParms)
316{
317 AssertPtrReturn(pParms, NULL);
318
319 PVBOXCLIPBOARDLISTOPENPARMS pParmsDup = (PVBOXCLIPBOARDLISTOPENPARMS)RTMemAllocZ(sizeof(VBOXCLIPBOARDLISTOPENPARMS));
320 if (!pParmsDup)
321 return NULL;
322
323 int rc = SharedClipboardURIListOpenParmsCopy(pParmsDup, pParms);
324 if (RT_FAILURE(rc))
325 {
326 SharedClipboardURIListOpenParmsDestroy(pParmsDup);
327
328 RTMemFree(pParmsDup);
329 pParmsDup = NULL;
330 }
331
332 return pParmsDup;
333}
334
335/**
336 * Initializes an URI list open parameters structure.
337 *
338 * @returns VBox status code.
339 * @param pParms URI list open parameters structure to initialize.
340 */
341int SharedClipboardURIListOpenParmsInit(PVBOXCLIPBOARDLISTOPENPARMS pParms)
342{
343 AssertPtrReturn(pParms, VERR_INVALID_POINTER);
344
345 RT_BZERO(pParms, sizeof(VBOXCLIPBOARDLISTOPENPARMS));
346
347 pParms->cbFilter = 64; /** @todo Make this dynamic. */
348 pParms->pszFilter = RTStrAlloc(pParms->cbFilter);
349
350 pParms->cbPath = RTPATH_MAX;
351 pParms->pszPath = RTStrAlloc(pParms->cbPath);
352
353 LogFlowFuncLeave();
354 return VINF_SUCCESS;
355}
356
357/**
358 * Destroys an URI list open parameters structure.
359 *
360 * @param pParms URI list open parameters structure to destroy.
361 */
362void SharedClipboardURIListOpenParmsDestroy(PVBOXCLIPBOARDLISTOPENPARMS pParms)
363{
364 if (!pParms)
365 return;
366
367 if (pParms->pszFilter)
368 {
369 RTStrFree(pParms->pszFilter);
370 pParms->pszFilter = NULL;
371 }
372
373 if (pParms->pszPath)
374 {
375 RTStrFree(pParms->pszPath);
376 pParms->pszPath = NULL;
377 }
378}
379
380/**
381 * Creates (allocates) and initializes a clipboard list entry structure.
382 *
383 * @param ppDirData Where to return the created clipboard list entry structure on success.
384 */
385int SharedClipboardURIListEntryAlloc(PVBOXCLIPBOARDLISTENTRY *ppListEntry)
386{
387 PVBOXCLIPBOARDLISTENTRY pListEntry = (PVBOXCLIPBOARDLISTENTRY)RTMemAlloc(sizeof(VBOXCLIPBOARDLISTENTRY));
388 if (!pListEntry)
389 return VERR_NO_MEMORY;
390
391 int rc = SharedClipboardURIListEntryInit(pListEntry);
392 if (RT_SUCCESS(rc))
393 *ppListEntry = pListEntry;
394
395 return rc;
396}
397
398/**
399 * Frees a clipboard list entry structure.
400 *
401 * @param pListEntry Clipboard list entry structure to free.
402 */
403void SharedClipboardURIListEntryFree(PVBOXCLIPBOARDLISTENTRY pListEntry)
404{
405 if (!pListEntry)
406 return;
407
408 SharedClipboardURIListEntryDestroy(pListEntry);
409 RTMemFree(pListEntry);
410}
411
412/**
413 * (Deep) Copies a clipboard list entry structure.
414 *
415 * @returns VBox status code.
416 * @param pListEntry Clipboard list entry to copy.
417 */
418int SharedClipboardURIListEntryCopy(PVBOXCLIPBOARDLISTENTRY pDst, PVBOXCLIPBOARDLISTENTRY pSrc)
419{
420 AssertPtrReturn(pDst, VERR_INVALID_POINTER);
421 AssertPtrReturn(pSrc, VERR_INVALID_POINTER);
422
423 int rc = VINF_SUCCESS;
424
425 *pDst = *pSrc;
426
427 if (pSrc->pszName)
428 {
429 pDst->pszName = RTStrDup(pSrc->pszName);
430 if (!pDst->pszName)
431 rc = VERR_NO_MEMORY;
432 }
433
434 if ( RT_SUCCESS(rc)
435 && pSrc->pvInfo)
436 {
437 pDst->pvInfo = RTMemDup(pSrc->pvInfo, pSrc->cbInfo);
438 if (pDst->pvInfo)
439 {
440 pDst->cbInfo = pSrc->cbInfo;
441 }
442 else
443 rc = VERR_NO_MEMORY;
444 }
445
446 if (RT_FAILURE(rc))
447 {
448 if (pDst->pvInfo)
449 {
450 RTMemFree(pDst->pvInfo);
451 pDst->pvInfo = NULL;
452 pDst->cbInfo = 0;
453 }
454 }
455
456 return rc;
457}
458
459/**
460 * Duplicates (allocates) a clipboard list entry structure.
461 *
462 * @returns Duplicated clipboard list entry structure on success.
463 * @param pListEntry Clipboard list entry to duplicate.
464 */
465PVBOXCLIPBOARDLISTENTRY SharedClipboardURIListEntryDup(PVBOXCLIPBOARDLISTENTRY pListEntry)
466{
467 AssertPtrReturn(pListEntry, NULL);
468
469 int rc = VINF_SUCCESS;
470
471 PVBOXCLIPBOARDLISTENTRY pListEntryDup = (PVBOXCLIPBOARDLISTENTRY)RTMemAllocZ(sizeof(VBOXCLIPBOARDLISTENTRY));
472 if (pListEntryDup)
473 rc = SharedClipboardURIListEntryCopy(pListEntryDup, pListEntry);
474
475 if (RT_FAILURE(rc))
476 {
477 SharedClipboardURIListEntryDestroy(pListEntryDup);
478
479 RTMemFree(pListEntryDup);
480 pListEntryDup = NULL;
481 }
482
483 return pListEntryDup;
484}
485
486/**
487 * Initializes a clipboard list entry structure.
488 *
489 * @returns VBox status code.
490 * @param pListEntry Clipboard list entry structure to initialize.
491 */
492int SharedClipboardURIListEntryInit(PVBOXCLIPBOARDLISTENTRY pListEntry)
493{
494 RT_BZERO(pListEntry, sizeof(VBOXCLIPBOARDLISTENTRY));
495
496 pListEntry->pszName = RTStrAlloc(VBOXCLIPBOARDLISTENTRY_MAX_NAME);
497 if (!pListEntry->pszName)
498 return VERR_NO_MEMORY;
499
500 pListEntry->cbName = VBOXCLIPBOARDLISTENTRY_MAX_NAME;
501 pListEntry->pvInfo = NULL;
502 pListEntry->cbInfo = 0;
503 pListEntry->fInfo = 0;
504
505 return VINF_SUCCESS;
506}
507
508/**
509 * Destroys a clipboard list entry structure.
510 *
511 * @param pListEntry Clipboard list entry structure to destroy.
512 */
513void SharedClipboardURIListEntryDestroy(PVBOXCLIPBOARDLISTENTRY pListEntry)
514{
515 if (!pListEntry)
516 return;
517
518 if (pListEntry->pszName)
519 {
520 RTStrFree(pListEntry->pszName);
521
522 pListEntry->pszName = NULL;
523 pListEntry->cbName = 0;
524 }
525
526 if (pListEntry->pvInfo)
527 {
528 RTMemFree(pListEntry->pvInfo);
529 pListEntry->pvInfo = NULL;
530 pListEntry->cbInfo = 0;
531 }
532}
533
534/**
535 * Returns whether a given clipboard data chunk is valid or not.
536 *
537 * @returns \c true if valid, \c false if not.
538 * @param pListEntry Clipboard data chunk to validate.
539 */
540bool SharedClipboardURIListEntryIsValid(PVBOXCLIPBOARDLISTENTRY pListEntry)
541{
542 RT_NOREF(pListEntry);
543
544 /** @todo Verify checksum. */
545
546 return true; /** @todo Implement this. */
547}
548
549/**
550 * Initializes an URI object context.
551 *
552 * @returns VBox status code.
553 * @param pObjCtx URI object context to initialize.
554 */
555int SharedClipboardURIObjCtxInit(PSHAREDCLIPBOARDCLIENTURIOBJCTX pObjCtx)
556{
557 AssertPtrReturn(pObjCtx, VERR_INVALID_POINTER);
558
559 LogFlowFuncEnter();
560
561 pObjCtx->uHandle = SHAREDCLIPBOARDOBJHANDLE_INVALID;
562
563 return VINF_SUCCESS;
564}
565
566/**
567 * Destroys an URI object context.
568 *
569 * @param pObjCtx URI object context to destroy.
570 */
571void SharedClipboardURIObjCtxDestroy(PSHAREDCLIPBOARDCLIENTURIOBJCTX pObjCtx)
572{
573 AssertPtrReturnVoid(pObjCtx);
574
575 LogFlowFuncEnter();
576}
577
578/**
579 * Returns if an URI object context is valid or not.
580 *
581 * @returns \c true if valid, \c false if not.
582 * @param pObjCtx URI object context to check.
583 */
584bool SharedClipboardURIObjCtxIsValid(PSHAREDCLIPBOARDCLIENTURIOBJCTX pObjCtx)
585{
586 return ( pObjCtx
587 && pObjCtx->uHandle != SHAREDCLIPBOARDOBJHANDLE_INVALID);
588}
589
590int SharedClipboardURIObjectOpen(PSHAREDCLIPBOARDURITRANSFER pTransfer, PVBOXCLIPBOARDOBJOPENCREATEPARMS pOpenCreateParms,
591 PSHAREDCLIPBOARDOBJHANDLE phObj)
592{
593 RT_NOREF(pTransfer, pOpenCreateParms, phObj);
594 return 0;
595}
596
597int SharedClipboardURIObjectClose(SHAREDCLIPBOARDOBJHANDLE hObj)
598{
599 RT_NOREF(hObj);
600 return 0;
601}
602
603int SharedClipboardURIObjectRead(SHAREDCLIPBOARDOBJHANDLE hObj, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead, uint32_t fFlags)
604{
605 RT_NOREF(hObj, pvBuf, cbBuf, pcbRead, fFlags);
606 return 0;
607}
608
609int SharedClipboardURIObjectWrite(SHAREDCLIPBOARDOBJHANDLE hObj, void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten,
610 uint32_t fFlags)
611{
612 RT_NOREF(hObj, pvBuf, cbBuf, pcbWritten, fFlags);
613 return 0;
614}
615
616int SharedClipboardURIObjectQueryInfo(SHAREDCLIPBOARDOBJHANDLE hObj, PSHAREDCLIPBOARDFSOBJINFO pObjInfo)
617{
618 RT_NOREF(hObj, pObjInfo);
619 return 0;
620}
621
622/**
623 * Initializes an URI clipboard transfer struct.
624 *
625 * @returns VBox status code.
626 * @param enmDir Specifies the transfer direction of this transfer.
627 * @param enmSource Specifies the data source of the transfer.
628 * @param ppTransfer Where to return the created URI transfer struct.
629 * Must be destroyed by SharedClipboardURITransferDestroy().
630 */
631int SharedClipboardURITransferCreate(SHAREDCLIPBOARDURITRANSFERDIR enmDir, SHAREDCLIPBOARDSOURCE enmSource,
632 PSHAREDCLIPBOARDURITRANSFER *ppTransfer)
633{
634 AssertPtrReturn(ppTransfer, VERR_INVALID_POINTER);
635
636 LogFlowFuncEnter();
637
638 PSHAREDCLIPBOARDURITRANSFER pTransfer = (PSHAREDCLIPBOARDURITRANSFER)RTMemAlloc(sizeof(SHAREDCLIPBOARDURITRANSFER));
639 if (!pTransfer)
640 return VERR_NO_MEMORY;
641
642 int rc = VINF_SUCCESS;
643
644 pTransfer->State.uID = 0;
645 pTransfer->State.enmStatus = SHAREDCLIPBOARDURITRANSFERSTATUS_NONE;
646 pTransfer->State.enmDir = enmDir;
647 pTransfer->State.enmSource = enmSource;
648
649 LogFlowFunc(("enmDir=%RU32, enmSource=%RU32\n", pTransfer->State.enmDir, pTransfer->State.enmSource));
650
651 pTransfer->pArea = NULL; /* Will be created later if needed. */
652
653 pTransfer->Thread.hThread = NIL_RTTHREAD;
654 pTransfer->Thread.fCancelled = false;
655 pTransfer->Thread.fStarted = false;
656 pTransfer->Thread.fStop = false;
657
658 pTransfer->uListHandleNext = 1;
659 pTransfer->uObjHandleNext = 1;
660 pTransfer->uEventIDNext = 1;
661
662 pTransfer->uTimeoutMs = 30 * 1000; /* 30s timeout by default. */
663 pTransfer->cbMaxChunkSize = _64K; /** @todo Make this configurable. */
664
665 pTransfer->pvUser = NULL;
666 pTransfer->cbUser = 0;
667
668 RT_ZERO(pTransfer->Callbacks);
669
670 pTransfer->pMapEvents = new SharedClipboardURITransferEventMap();
671 if (pTransfer->pMapEvents)
672 {
673 pTransfer->pMapLists = new SharedClipboardURIListMap();
674 if (pTransfer->pMapLists)
675 {
676 *ppTransfer = pTransfer;
677 }
678 }
679 else
680 rc = VERR_NO_MEMORY;
681
682 if (RT_FAILURE(rc))
683 {
684 RTMemFree(pTransfer);
685 }
686
687 LogFlowFuncLeaveRC(rc);
688 return rc;
689}
690
691/**
692 * Destroys an URI clipboard transfer context struct.
693 *
694 * @returns VBox status code.
695 * @param pURI URI clipboard transfer to destroy.
696 */
697int SharedClipboardURITransferDestroy(PSHAREDCLIPBOARDURITRANSFER pTransfer)
698{
699 if (!pTransfer)
700 return VINF_SUCCESS;
701
702 LogFlowFuncEnter();
703
704 int rc = sharedClipboardURITransferThreadDestroy(pTransfer, 30 * 1000 /* Timeout in ms */);
705 if (RT_FAILURE(rc))
706 return rc;
707
708 if (pTransfer->pMapEvents)
709 {
710 delete pTransfer->pMapEvents;
711 pTransfer->pMapEvents = NULL;
712 }
713
714 if (pTransfer->pMapLists)
715 {
716 delete pTransfer->pMapLists;
717 pTransfer->pMapLists = NULL;
718 }
719
720 LogFlowFuncLeave();
721 return VINF_SUCCESS;
722}
723
724int SharedClipboardURITransferOpen(PSHAREDCLIPBOARDURITRANSFER pTransfer)
725{
726 int rc = VINF_SUCCESS;
727
728 if (pTransfer->ProviderIface.pfnTransferOpen)
729 rc = pTransfer->ProviderIface.pfnTransferOpen(&pTransfer->ProviderCtx);
730
731 LogFlowFuncLeaveRC(rc);
732 return rc;
733}
734
735int SharedClipboardURITransferClose(PSHAREDCLIPBOARDURITRANSFER pTransfer)
736{
737 int rc = VINF_SUCCESS;
738
739 if (pTransfer->ProviderIface.pfnTransferClose)
740 rc = pTransfer->ProviderIface.pfnTransferClose(&pTransfer->ProviderCtx);
741
742 LogFlowFuncLeaveRC(rc);
743 return rc;
744}
745
746/**
747 * Creates a new list handle (local only).
748 *
749 * @returns New List handle on success, or SHAREDCLIPBOARDLISTHANDLE_INVALID on error.
750 * @param pTransfer URI clipboard transfer to create new list handle for.
751 */
752static SHAREDCLIPBOARDLISTHANDLE sharedClipboardURITransferListHandleNew(PSHAREDCLIPBOARDURITRANSFER pTransfer)
753{
754 return pTransfer->uListHandleNext++; /** @todo Good enough for now. Improve this later. */
755}
756
757/**
758 * Opens a list.
759 *
760 * @returns VBox status code.
761 * @param pTransfer URI clipboard transfer to handle.
762 * @param pOpenParms List open parameters to use for opening.
763 * @param phList Where to store the List handle of opened list on success.
764 */
765int SharedClipboardURITransferListOpen(PSHAREDCLIPBOARDURITRANSFER pTransfer, PVBOXCLIPBOARDLISTOPENPARMS pOpenParms,
766 PSHAREDCLIPBOARDLISTHANDLE phList)
767{
768 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
769 AssertPtrReturn(pOpenParms, VERR_INVALID_POINTER);
770 AssertPtrReturn(phList, VERR_INVALID_POINTER);
771
772 int rc;
773
774 SHAREDCLIPBOARDLISTHANDLE hList = SHAREDCLIPBOARDLISTHANDLE_INVALID;
775
776 if (pTransfer->State.enmSource == SHAREDCLIPBOARDSOURCE_LOCAL)
777 {
778 PSHAREDCLIPBOARDURILISTHANDLEINFO pInfo
779 = (PSHAREDCLIPBOARDURILISTHANDLEINFO)RTMemAlloc(sizeof(SHAREDCLIPBOARDURILISTHANDLEINFO));
780 if (pInfo)
781 {
782 LogFlowFunc(("pszPath=%s\n", pOpenParms->pszPath));
783
784 RTFSOBJINFO objInfo;
785 rc = RTPathQueryInfo(pOpenParms->pszPath, &objInfo, RTFSOBJATTRADD_NOTHING);
786 if (RT_SUCCESS(rc))
787 {
788 if (RTFS_IS_DIRECTORY(objInfo.Attr.fMode))
789 {
790 rc = RTDirOpen(&pInfo->u.Local.hDirRoot, pOpenParms->pszPath);
791 }
792 else if (RTFS_IS_FILE(objInfo.Attr.fMode))
793 {
794 rc = RTFileOpen(&pInfo->u.Local.hFile, pOpenParms->pszPath,
795 RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE);
796 }
797 else if (RTFS_IS_SYMLINK(objInfo.Attr.fMode))
798 {
799 rc = VERR_NOT_IMPLEMENTED; /** @todo */
800 }
801 else
802 AssertFailedStmt(rc = VERR_NOT_SUPPORTED);
803
804 if (RT_SUCCESS(rc))
805 rc = SharedClipboardURIListOpenParmsCopy(&pInfo->OpenParms, pOpenParms);
806
807 if (RT_SUCCESS(rc))
808 {
809 pInfo->fMode = objInfo.Attr.fMode;
810
811 hList = sharedClipboardURITransferListHandleNew(pTransfer);
812
813 pTransfer->pMapLists->insert(
814 std::pair<SHAREDCLIPBOARDLISTHANDLE, PSHAREDCLIPBOARDURILISTHANDLEINFO>(hList, pInfo));
815 }
816 else
817 {
818 if (RTFS_IS_DIRECTORY(objInfo.Attr.fMode))
819 {
820 if (RTDirIsValid(pInfo->u.Local.hDirRoot))
821 RTDirClose(pInfo->u.Local.hDirRoot);
822 }
823 else if (RTFS_IS_FILE(objInfo.Attr.fMode))
824 {
825 if (RTFileIsValid(pInfo->u.Local.hFile))
826 RTFileClose(pInfo->u.Local.hFile);
827 }
828
829 RTMemFree(pInfo);
830 pInfo = NULL;
831 }
832 }
833 }
834 else
835 rc = VERR_NO_MEMORY;
836 }
837 else if (pTransfer->State.enmSource == SHAREDCLIPBOARDSOURCE_REMOTE)
838 {
839 if (pTransfer->ProviderIface.pfnListOpen)
840 {
841 rc = pTransfer->ProviderIface.pfnListOpen(&pTransfer->ProviderCtx, pOpenParms, &hList);
842 }
843 else
844 rc = VERR_NOT_SUPPORTED;
845 }
846 else
847 AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED);
848
849 if (RT_SUCCESS(rc))
850 *phList = hList;
851
852 LogFlowFuncLeaveRC(rc);
853 return rc;
854}
855
856/**
857 * Closes a list.
858 *
859 * @returns VBox status code.
860 * @param pTransfer URI clipboard transfer to handle.
861 * @param hList Handle of list to close.
862 */
863int SharedClipboardURITransferListClose(PSHAREDCLIPBOARDURITRANSFER pTransfer, SHAREDCLIPBOARDLISTHANDLE hList)
864{
865 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
866
867 if (hList == SHAREDCLIPBOARDLISTHANDLE_INVALID)
868 return VINF_SUCCESS;
869
870 int rc = VINF_SUCCESS;
871
872 if (pTransfer->State.enmSource == SHAREDCLIPBOARDSOURCE_LOCAL)
873 {
874 SharedClipboardURIListMap::iterator itList = pTransfer->pMapLists->find(hList);
875 if (itList != pTransfer->pMapLists->end())
876 {
877 PSHAREDCLIPBOARDURILISTHANDLEINFO pInfo = itList->second;
878 AssertPtr(pInfo);
879
880 if (RTDirIsValid(pInfo->u.Local.hDirRoot))
881 RTDirClose(pInfo->u.Local.hDirRoot);
882
883 RTMemFree(pInfo);
884
885 pTransfer->pMapLists->erase(itList);
886 }
887 else
888 rc = VERR_NOT_FOUND;
889 }
890 else if (pTransfer->State.enmSource == SHAREDCLIPBOARDSOURCE_REMOTE)
891 {
892 if (pTransfer->ProviderIface.pfnListClose)
893 {
894 rc = pTransfer->ProviderIface.pfnListClose(&pTransfer->ProviderCtx, hList);
895 }
896 else
897 rc = VERR_NOT_SUPPORTED;
898 }
899
900 LogFlowFuncLeaveRC(rc);
901 return rc;
902}
903
904/**
905 * Adds a file to a list heaer.
906 *
907 * @returns VBox status code.
908 * @param pHdr List header to add file to.
909 * @param pszPath Path of file to add.
910 */
911static int sharedClipboardURITransferListHdrAddFile(PVBOXCLIPBOARDLISTHDR pHdr, const char *pszPath)
912{
913 uint64_t cbSize = 0;
914 int rc = RTFileQuerySize(pszPath, &cbSize);
915 if (RT_SUCCESS(rc))
916 {
917 pHdr->cbTotalSize += cbSize;
918 pHdr->cTotalObjects++;
919 }
920
921 LogFlowFuncLeaveRC(rc);
922 return rc;
923}
924
925/**
926 * Builds a list header, internal version.
927 *
928 * @returns VBox status code.
929 * @param pHdr Where to store the build list header.
930 * @param pcszSrcPath Source path of list.
931 * @param pcszDstPath Destination path of list.
932 * @param pcszDstBase Destination base path.
933 * @param cchDstBase Number of charaters of destination base path.
934 */
935static int sharedClipboardURITransferListHdrFromDir(PVBOXCLIPBOARDLISTHDR pHdr,
936 const char *pcszSrcPath, const char *pcszDstPath,
937 const char *pcszDstBase, size_t cchDstBase)
938{
939 AssertPtrReturn(pcszSrcPath, VERR_INVALID_POINTER);
940 AssertPtrReturn(pcszDstBase, VERR_INVALID_POINTER);
941 AssertPtrReturn(pcszDstPath, VERR_INVALID_POINTER);
942
943 RT_NOREF(cchDstBase);
944
945 LogFlowFunc(("pcszSrcPath=%s, pcszDstPath=%s, pcszDstBase=%s, cchDstBase=%zu\n",
946 pcszSrcPath, pcszDstPath, pcszDstBase, cchDstBase));
947
948 RTFSOBJINFO objInfo;
949 int rc = RTPathQueryInfo(pcszSrcPath, &objInfo, RTFSOBJATTRADD_NOTHING);
950 if (RT_SUCCESS(rc))
951 {
952 if (RTFS_IS_DIRECTORY(objInfo.Attr.fMode))
953 {
954 pHdr->cTotalObjects++;
955
956 RTDIR hDir;
957 rc = RTDirOpen(&hDir, pcszSrcPath);
958 if (RT_SUCCESS(rc))
959 {
960 size_t cbDirEntry = 0;
961 PRTDIRENTRYEX pDirEntry = NULL;
962 do
963 {
964 /* Retrieve the next directory entry. */
965 rc = RTDirReadExA(hDir, &pDirEntry, &cbDirEntry, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
966 if (RT_FAILURE(rc))
967 {
968 if (rc == VERR_NO_MORE_FILES)
969 rc = VINF_SUCCESS;
970 break;
971 }
972
973 switch (pDirEntry->Info.Attr.fMode & RTFS_TYPE_MASK)
974 {
975 #if 0 /* No recursion here (yet). */
976 case RTFS_TYPE_DIRECTORY:
977 {
978 /* Skip "." and ".." entries. */
979 if (RTDirEntryExIsStdDotLink(pDirEntry))
980 break;
981
982 char *pszSrc = RTPathJoinA(pcszSrcPath, pDirEntry->szName);
983 if (pszSrc)
984 {
985 char *pszDst = RTPathJoinA(pcszDstPath, pDirEntry->szName);
986 if (pszDst)
987 {
988 rc = sharedClipboardURITransferListHdrFromDir(pHdr, pszSrc, pszDst,
989 pcszDstBase, cchDstBase);
990 RTStrFree(pszDst);
991 }
992 else
993 rc = VERR_NO_MEMORY;
994
995 RTStrFree(pszSrc);
996 }
997 else
998 rc = VERR_NO_MEMORY;
999 break;
1000 }
1001 #endif
1002 case RTFS_TYPE_FILE:
1003 {
1004 char *pszSrc = RTPathJoinA(pcszSrcPath, pDirEntry->szName);
1005 if (pszSrc)
1006 {
1007 rc = sharedClipboardURITransferListHdrAddFile(pHdr, pszSrc);
1008 RTStrFree(pszSrc);
1009 }
1010 else
1011 rc = VERR_NO_MEMORY;
1012 break;
1013 }
1014 case RTFS_TYPE_SYMLINK:
1015 {
1016 /** @todo Not implemented yet. */
1017 }
1018
1019 default:
1020 break;
1021 }
1022
1023 } while (RT_SUCCESS(rc));
1024
1025 RTDirReadExAFree(&pDirEntry, &cbDirEntry);
1026 RTDirClose(hDir);
1027 }
1028 }
1029 else if (RTFS_IS_FILE(objInfo.Attr.fMode))
1030 {
1031 rc = sharedClipboardURITransferListHdrAddFile(pHdr, pcszSrcPath);
1032 }
1033 else if (RTFS_IS_SYMLINK(objInfo.Attr.fMode))
1034 {
1035 /** @todo Not implemented yet. */
1036 }
1037 else
1038 rc = VERR_NOT_SUPPORTED;
1039 }
1040
1041 LogFlowFuncLeaveRC(rc);
1042 return rc;
1043}
1044
1045/**
1046 * Retrieves the header of a Shared Clipboard list.
1047 *
1048 * @returns VBox status code.
1049 * @param pTransfer URI clipboard transfer to handle.
1050 * @param hList Handle of list to get header for.
1051 * @param pHdr Where to store the returned list header information.
1052 */
1053int SharedClipboardURITransferListGetHeader(PSHAREDCLIPBOARDURITRANSFER pTransfer, SHAREDCLIPBOARDLISTHANDLE hList,
1054 PVBOXCLIPBOARDLISTHDR pHdr)
1055{
1056 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
1057 AssertPtrReturn(pHdr, VERR_INVALID_POINTER);
1058
1059 int rc;
1060
1061 LogFlowFunc(("hList=%RU64\n", hList));
1062
1063 if (pTransfer->State.enmSource == SHAREDCLIPBOARDSOURCE_LOCAL)
1064 {
1065 SharedClipboardURIListMap::iterator itList = pTransfer->pMapLists->find(hList);
1066 if (itList != pTransfer->pMapLists->end())
1067 {
1068 rc = SharedClipboardURIListHdrInit(pHdr);
1069 if (RT_SUCCESS(rc))
1070 {
1071 PSHAREDCLIPBOARDURILISTHANDLEINFO pInfo = itList->second;
1072 AssertPtr(pInfo);
1073
1074 if (RTFS_IS_DIRECTORY(pInfo->fMode))
1075 {
1076 char *pszSrcPath = RTStrDup(pInfo->OpenParms.pszPath);
1077 if (pszSrcPath)
1078 {
1079 size_t cbSrcPathLen = RTPathStripTrailingSlash(pszSrcPath);
1080 if (cbSrcPathLen)
1081 {
1082 char *pszFileName = RTPathFilename(pszSrcPath);
1083 if (pszFileName)
1084 {
1085 Assert(pszFileName >= pszSrcPath);
1086 size_t cchDstBase = pszFileName - pszSrcPath;
1087#ifdef VBOX_STRICT
1088 char *pszDstPath = &pszSrcPath[cchDstBase];
1089 LogFlowFunc(("pszSrcPath=%s, pszFileName=%s, pszDstPath=%s\n",
1090 pszSrcPath, pszFileName, pszDstPath));
1091#endif
1092 rc = sharedClipboardURITransferListHdrFromDir(pHdr,
1093 pszSrcPath, pszSrcPath, pszSrcPath, cchDstBase);
1094 }
1095 else
1096 rc = VERR_PATH_NOT_FOUND;
1097 }
1098 else
1099 rc = VERR_INVALID_PARAMETER;
1100
1101 RTStrFree(pszSrcPath);
1102 }
1103 else
1104 rc = VERR_NO_MEMORY;
1105 }
1106 else if (RTFS_IS_FILE(pInfo->fMode))
1107 {
1108 pHdr->cTotalObjects = 1;
1109
1110 RTFSOBJINFO objInfo;
1111 rc = RTFileQueryInfo(pInfo->u.Local.hFile, &objInfo, RTFSOBJATTRADD_NOTHING);
1112 if (RT_SUCCESS(rc))
1113 {
1114 pHdr->cbTotalSize = objInfo.cbObject;
1115 }
1116 }
1117 else if (RTFS_IS_SYMLINK(pInfo->fMode))
1118 {
1119 rc = VERR_NOT_IMPLEMENTED; /** @todo */
1120 }
1121 else
1122 AssertFailedStmt(rc = VERR_NOT_SUPPORTED);
1123 }
1124
1125 LogFlowFunc(("cTotalObj=%RU64, cbTotalSize=%RU64\n", pHdr->cTotalObjects, pHdr->cbTotalSize));
1126 }
1127 else
1128 rc = VERR_NOT_FOUND;
1129 }
1130 else if (pTransfer->State.enmSource == SHAREDCLIPBOARDSOURCE_REMOTE)
1131 {
1132 if (pTransfer->ProviderIface.pfnListHdrRead)
1133 {
1134 rc = pTransfer->ProviderIface.pfnListHdrRead(&pTransfer->ProviderCtx, hList, pHdr);
1135 }
1136 else
1137 rc = VERR_NOT_SUPPORTED;
1138 }
1139 else
1140 AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED);
1141
1142 LogFlowFuncLeaveRC(rc);
1143 return rc;
1144}
1145
1146/**
1147 * Returns the current URI object for a clipboard URI transfer list.
1148 *
1149 * @returns Pointer to URI object.
1150 * @param pTransfer URI clipboard transfer to return URI object for.
1151 */
1152PSHAREDCLIPBOARDURITRANSFEROBJ SharedClipboardURITransferListGetObj(PSHAREDCLIPBOARDURITRANSFER pTransfer,
1153 SHAREDCLIPBOARDLISTHANDLE hList, uint64_t uIdx)
1154{
1155 AssertPtrReturn(pTransfer, NULL);
1156
1157 RT_NOREF(hList, uIdx);
1158
1159 LogFlowFunc(("hList=%RU64\n", hList));
1160
1161 return NULL;
1162}
1163
1164/**
1165 * Reads a single Shared Clipboard list entry.
1166 *
1167 * @returns VBox status code or VERR_NO_MORE_FILES if the end of the list has been reached.
1168 * @param pTransfer URI clipboard transfer to handle.
1169 * @param hList List handle of list to read from.
1170 * @param pEntry Where to store the read information.
1171 */
1172int SharedClipboardURITransferListRead(PSHAREDCLIPBOARDURITRANSFER pTransfer, SHAREDCLIPBOARDLISTHANDLE hList,
1173 PVBOXCLIPBOARDLISTENTRY pEntry)
1174{
1175 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
1176 AssertPtrReturn(pEntry, VERR_INVALID_POINTER);
1177
1178 int rc = VINF_SUCCESS;
1179
1180 LogFlowFunc(("hList=%RU64\n", hList));
1181
1182 if (pTransfer->State.enmSource == SHAREDCLIPBOARDSOURCE_LOCAL)
1183 {
1184 SharedClipboardURIListMap::iterator itList = pTransfer->pMapLists->find(hList);
1185 if (itList != pTransfer->pMapLists->end())
1186 {
1187 PSHAREDCLIPBOARDURILISTHANDLEINFO pInfo = itList->second;
1188 AssertPtr(pInfo);
1189
1190 LogFlowFunc(("\tfMode=%RU32, pszPath=%s\n", pInfo->fMode, pInfo->OpenParms.pszPath));
1191
1192 if (RTFS_IS_DIRECTORY(pInfo->fMode))
1193 {
1194 for (;;)
1195 {
1196 bool fSkipEntry = false; /* Whether to skip an entry in the enumeration. */
1197
1198 size_t cbDirEntry = 0;
1199 PRTDIRENTRYEX pDirEntry = NULL;
1200 rc = RTDirReadExA(pInfo->u.Local.hDirRoot, &pDirEntry, &cbDirEntry, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
1201 if (RT_SUCCESS(rc))
1202 {
1203 switch (pDirEntry->Info.Attr.fMode & RTFS_TYPE_MASK)
1204 {
1205 case RTFS_TYPE_DIRECTORY:
1206 {
1207 /* Skip "." and ".." entries. */
1208 if (RTDirEntryExIsStdDotLink(pDirEntry))
1209 {
1210 fSkipEntry = true;
1211 break;
1212 }
1213
1214 LogFlowFunc(("Directory: %s\n", pDirEntry->szName));
1215 break;
1216 }
1217
1218 case RTFS_TYPE_FILE:
1219 {
1220 LogFlowFunc(("File: %s\n", pDirEntry->szName));
1221 break;
1222 }
1223
1224 case RTFS_TYPE_SYMLINK:
1225 {
1226 rc = VERR_NOT_IMPLEMENTED; /** @todo Not implemented yet. */
1227 break;
1228 }
1229
1230 default:
1231 break;
1232 }
1233
1234 if ( RT_SUCCESS(rc)
1235 && !fSkipEntry)
1236 {
1237 pEntry->pvInfo = (PSHAREDCLIPBOARDFSOBJINFO)RTMemAlloc(sizeof(SHAREDCLIPBOARDFSOBJINFO));
1238 if (pEntry->pvInfo)
1239 {
1240 rc = RTStrCopy(pEntry->pszName, pEntry->cbName, pDirEntry->szName);
1241 if (RT_SUCCESS(rc))
1242 {
1243 SharedClipboardFsObjFromIPRT(PSHAREDCLIPBOARDFSOBJINFO(pEntry->pvInfo), &pDirEntry->Info);
1244
1245 pEntry->cbInfo = sizeof(SHAREDCLIPBOARDFSOBJINFO);
1246 pEntry->fInfo = VBOX_SHAREDCLIPBOARD_INFO_FLAG_FSOBJINFO;
1247 }
1248 }
1249 else
1250 rc = VERR_NO_MEMORY;
1251 }
1252
1253 RTDirReadExAFree(&pDirEntry, &cbDirEntry);
1254 }
1255
1256 if ( !fSkipEntry /* Do we have a valid entry? Bail out. */
1257 || RT_FAILURE(rc))
1258 {
1259 break;
1260 }
1261 }
1262 }
1263 else if (RTFS_IS_FILE(pInfo->fMode))
1264 {
1265 LogFlowFunc(("\tSingle file: %s\n", pInfo->OpenParms.pszPath));
1266
1267 RTFSOBJINFO objInfo;
1268 rc = RTFileQueryInfo(pInfo->u.Local.hFile, &objInfo, RTFSOBJATTRADD_NOTHING);
1269 if (RT_SUCCESS(rc))
1270 {
1271 pEntry->pvInfo = (PSHAREDCLIPBOARDFSOBJINFO)RTMemAlloc(sizeof(SHAREDCLIPBOARDFSOBJINFO));
1272 if (pEntry->pvInfo)
1273 {
1274 rc = RTStrCopy(pEntry->pszName, pEntry->cbName, pInfo->OpenParms.pszPath);
1275 if (RT_SUCCESS(rc))
1276 {
1277 SharedClipboardFsObjFromIPRT(PSHAREDCLIPBOARDFSOBJINFO(pEntry->pvInfo), &objInfo);
1278
1279 pEntry->cbInfo = sizeof(SHAREDCLIPBOARDFSOBJINFO);
1280 pEntry->fInfo = VBOX_SHAREDCLIPBOARD_INFO_FLAG_FSOBJINFO;
1281 }
1282 }
1283 else
1284 rc = VERR_NO_MEMORY;
1285 }
1286 }
1287 else if (RTFS_IS_SYMLINK(pInfo->fMode))
1288 {
1289 rc = VERR_NOT_IMPLEMENTED;
1290 }
1291 else
1292 AssertFailedStmt(rc = VERR_NOT_SUPPORTED);
1293 }
1294 else
1295 rc = VERR_NOT_FOUND;
1296 }
1297 else if (pTransfer->State.enmSource == SHAREDCLIPBOARDSOURCE_REMOTE)
1298 {
1299 if (pTransfer->ProviderIface.pfnListEntryRead)
1300 rc = pTransfer->ProviderIface.pfnListEntryRead(&pTransfer->ProviderCtx, hList, pEntry);
1301 else
1302 rc = VERR_NOT_SUPPORTED;
1303 }
1304
1305 LogFlowFuncLeaveRC(rc);
1306 return rc;
1307}
1308
1309int SharedClipboardURITransferListWrite(PSHAREDCLIPBOARDURITRANSFER pTransfer, SHAREDCLIPBOARDLISTHANDLE hList,
1310 PVBOXCLIPBOARDLISTENTRY pEntry)
1311{
1312 RT_NOREF(pTransfer, hList, pEntry);
1313
1314 int rc = VINF_SUCCESS;
1315
1316#if 0
1317 if (pTransfer->ProviderIface.pfnListEntryWrite)
1318 rc = pTransfer->ProviderIface.pfnListEntryWrite(&pTransfer->ProviderCtx, hList, pEntry);
1319#endif
1320
1321 LogFlowFuncLeaveRC(rc);
1322 return rc;
1323}
1324
1325/**
1326 * Returns whether a given list handle is valid or not.
1327 *
1328 * @returns \c true if list handle is valid, \c false if not.
1329 * @param pTransfer URI clipboard transfer to handle.
1330 * @param hList List handle to check.
1331 */
1332bool SharedClipboardURITransferListHandleIsValid(PSHAREDCLIPBOARDURITRANSFER pTransfer, SHAREDCLIPBOARDLISTHANDLE hList)
1333{
1334 bool fIsValid = false;
1335
1336 if (pTransfer->State.enmSource == SHAREDCLIPBOARDSOURCE_LOCAL)
1337 {
1338 SharedClipboardURIListMap::iterator itList = pTransfer->pMapLists->find(hList);
1339 fIsValid = itList != pTransfer->pMapLists->end();
1340 }
1341 else if (pTransfer->State.enmSource == SHAREDCLIPBOARDSOURCE_REMOTE)
1342 {
1343 AssertFailed(); /** @todo Implement. */
1344 }
1345
1346 return fIsValid;
1347}
1348
1349/**
1350 * Prepares everything needed for a read / write transfer to begin.
1351 *
1352 * @returns VBox status code.
1353 * @param pTransfer URI clipboard transfer to prepare.
1354 */
1355int SharedClipboardURITransferPrepare(PSHAREDCLIPBOARDURITRANSFER pTransfer)
1356{
1357 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
1358
1359 LogFlowFuncEnter();
1360
1361 int rc = VINF_SUCCESS;
1362
1363 AssertMsgReturn(pTransfer->State.enmStatus == SHAREDCLIPBOARDURITRANSFERSTATUS_NONE,
1364 ("Transfer has wrong state (%RU32)\n", pTransfer->State.enmStatus), VERR_WRONG_ORDER);
1365
1366 LogFlowFunc(("pTransfer=%p, enmDir=%RU32\n", pTransfer, pTransfer->State.enmDir));
1367
1368 if (pTransfer->Callbacks.pfnTransferPrepare)
1369 {
1370 SHAREDCLIPBOARDURITRANSFERCALLBACKDATA callbackData = { pTransfer, pTransfer->Callbacks.pvUser };
1371 pTransfer->Callbacks.pfnTransferPrepare(&callbackData);
1372 }
1373
1374 if (RT_SUCCESS(rc))
1375 {
1376 pTransfer->State.enmStatus = SHAREDCLIPBOARDURITRANSFERSTATUS_READY;
1377
1378 /** @todo Add checksum support. */
1379 }
1380
1381 LogFlowFuncLeaveRC(rc);
1382 return rc;
1383}
1384
1385/**
1386 * Sets the URI provider interface for a given transfer.
1387 *
1388 * @returns VBox status code.
1389 * @param pTransfer Transfer to create URI provider for.
1390 * @param pCreationCtx Provider creation context to use for provider creation.
1391 */
1392int SharedClipboardURITransferSetInterface(PSHAREDCLIPBOARDURITRANSFER pTransfer,
1393 PSHAREDCLIPBOARDPROVIDERCREATIONCTX pCreationCtx)
1394{
1395 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
1396 AssertPtrReturn(pCreationCtx, VERR_INVALID_POINTER);
1397
1398 LogFlowFuncEnter();
1399
1400 int rc = VINF_SUCCESS;
1401
1402 pTransfer->ProviderIface = pCreationCtx->Interface;
1403
1404 pTransfer->ProviderCtx.pTransfer = pTransfer;
1405 pTransfer->ProviderCtx.pvUser = pCreationCtx->pvUser;
1406
1407 LogFlowFuncLeaveRC(rc);
1408 return rc;
1409}
1410
1411/**
1412 * Clears (resets) the root list of an URI transfer.
1413 *
1414 * @param pTransfer Transfer to clear URI root list for.
1415 */
1416static void sharedClipboardURIListTransferRootsClear(PSHAREDCLIPBOARDURITRANSFER pTransfer)
1417{
1418 AssertPtrReturnVoid(pTransfer);
1419
1420 pTransfer->lstRootEntries.clear();
1421}
1422
1423/**
1424 * Sets URI root list entries for a given transfer.
1425 *
1426 * @returns VBox status code.
1427 * @param pTransfer Transfer to set URI list entries for.
1428 * @param pszRoots String list (separated by CRLF) of root entries to set.
1429 * @param cbRoots Size (in bytes) of string list.
1430 */
1431int SharedClipboardURILTransferSetRoots(PSHAREDCLIPBOARDURITRANSFER pTransfer, const char *pszRoots, size_t cbRoots)
1432{
1433 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
1434 AssertPtrReturn(pszRoots, VERR_INVALID_POINTER);
1435 AssertReturn(cbRoots, VERR_INVALID_PARAMETER);
1436
1437 if (!RTStrIsValidEncoding(pszRoots))
1438 return VERR_INVALID_PARAMETER;
1439
1440 int rc = VINF_SUCCESS;
1441
1442 sharedClipboardURIListTransferRootsClear(pTransfer);
1443
1444 RTCList<RTCString> lstRootEntries = RTCString(pszRoots, cbRoots - 1).split("\r\n");
1445 for (size_t i = 0; i < lstRootEntries.size(); ++i)
1446 {
1447 SHAREDCLIPBOARDURILISTROOT listRoot;
1448
1449 listRoot.strPathAbs = lstRootEntries.at(i);
1450
1451 pTransfer->lstRootEntries.append(listRoot);
1452 }
1453
1454 LogFlowFunc(("cRoots=%RU32\n", pTransfer->lstRootEntries.size()));
1455
1456 LogFlowFuncLeaveRC(rc);
1457 return rc;
1458}
1459
1460/**
1461 * Resets an clipboard URI transfer.
1462 *
1463 * @param pTransfer URI clipboard transfer to reset.
1464 */
1465void SharedClipboardURITransferReset(PSHAREDCLIPBOARDURITRANSFER pTransfer)
1466{
1467 AssertPtrReturnVoid(pTransfer);
1468
1469 LogFlowFuncEnter();
1470
1471 sharedClipboardURIListTransferRootsClear(pTransfer);
1472}
1473
1474/**
1475 * Returns the clipboard area for a clipboard URI transfer.
1476 *
1477 * @returns Current clipboard area, or NULL if none.
1478 * @param pTransfer URI clipboard transfer to return clipboard area for.
1479 */
1480SharedClipboardArea *SharedClipboardURITransferGetArea(PSHAREDCLIPBOARDURITRANSFER pTransfer)
1481{
1482 AssertPtrReturn(pTransfer, NULL);
1483
1484 return pTransfer->pArea;
1485}
1486
1487/**
1488 * Returns the number of URI root list entries.
1489 *
1490 * @returns Root list entry count.
1491 * @param pTransfer URI clipboard transfer to return root entry count for.
1492 */
1493uint32_t SharedClipboardURILTransferRootsCount(PSHAREDCLIPBOARDURITRANSFER pTransfer)
1494{
1495 AssertPtrReturn(pTransfer, 0);
1496
1497 return (uint32_t)pTransfer->lstRootEntries.size();
1498}
1499
1500/**
1501 * Get a specific root list entry.
1502 *
1503 * @returns VBox status code.
1504 * @param pTransfer URI clipboard transfer to get root list entry of.
1505 * @param uIndex Index (zero-based) of entry to get.
1506 * @param pEntry Where to store the returned entry on success.
1507 */
1508int SharedClipboardURILTransferRootsEntry(PSHAREDCLIPBOARDURITRANSFER pTransfer,
1509 uint32_t uIndex, PVBOXCLIPBOARDROOTLISTENTRY pEntry)
1510{
1511 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
1512 AssertPtrReturn(pEntry, VERR_INVALID_POINTER);
1513
1514 if (uIndex >= pTransfer->lstRootEntries.size())
1515 return VERR_INVALID_PARAMETER;
1516
1517 int rc;
1518
1519 PSHAREDCLIPBOARDURILISTROOT pRoot = &pTransfer->lstRootEntries.at(uIndex);
1520 AssertPtrReturn(pRoot, VERR_INVALID_POINTER);
1521
1522 /* Make sure that we only advertise relative source paths, not absolute ones. */
1523 const char *pcszSrcPath = pRoot->strPathAbs.c_str();
1524
1525 char *pszFileName = RTPathFilename(pcszSrcPath);
1526 if (pszFileName)
1527 {
1528 Assert(pszFileName >= pcszSrcPath);
1529 size_t cchDstBase = pszFileName - pcszSrcPath;
1530 const char *pszDstPath = &pcszSrcPath[cchDstBase];
1531
1532 LogFlowFunc(("pcszSrcPath=%s, pszDstPath=%s\n", pcszSrcPath, pszDstPath));
1533
1534 rc = SharedClipboardURIListEntryInit(pEntry);
1535 if (RT_SUCCESS(rc))
1536 {
1537 rc = RTStrCopy(pEntry->pszName, pEntry->cbName, pszDstPath);
1538 if (RT_SUCCESS(rc))
1539 {
1540 pEntry->cbInfo = sizeof(SHAREDCLIPBOARDFSOBJINFO);
1541 pEntry->pvInfo = (PSHAREDCLIPBOARDFSOBJINFO)RTMemAlloc(pEntry->cbInfo);
1542 if (pEntry->pvInfo)
1543 {
1544 RTFSOBJINFO fsObjInfo;
1545 rc = RTPathQueryInfo(pcszSrcPath, & fsObjInfo, RTFSOBJATTRADD_NOTHING);
1546 if (RT_SUCCESS(rc))
1547 {
1548 SharedClipboardFsObjFromIPRT(PSHAREDCLIPBOARDFSOBJINFO(pEntry->pvInfo), &fsObjInfo);
1549
1550 pEntry->fInfo = VBOX_SHAREDCLIPBOARD_INFO_FLAG_FSOBJINFO;
1551 }
1552 }
1553 else
1554 rc = VERR_NO_MEMORY;
1555 }
1556 }
1557 }
1558 else
1559 rc = VERR_INVALID_POINTER;
1560
1561 LogFlowFuncLeaveRC(rc);
1562 return rc;
1563}
1564
1565/**
1566 * Returns the root entries of an URI transfer.
1567 *
1568 * @returns VBox status code.
1569 * @param pTransfer URI clipboard transfer to return root entries for.
1570 * @param ppRootList Where to store the root list on success.
1571 */
1572int SharedClipboardURILTransferRootsAsList(PSHAREDCLIPBOARDURITRANSFER pTransfer, PVBOXCLIPBOARDROOTLIST *ppRootList)
1573{
1574 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
1575 AssertPtrReturn(ppRootList, VERR_INVALID_POINTER);
1576
1577 int rc = VINF_SUCCESS;
1578
1579 if (pTransfer->State.enmSource == SHAREDCLIPBOARDSOURCE_LOCAL)
1580 {
1581 PVBOXCLIPBOARDROOTLIST pRootList = SharedClipboardURIRootListAlloc();
1582 if (!pRootList)
1583 return VERR_NO_MEMORY;
1584
1585 const uint32_t cRoots = (uint32_t)pTransfer->lstRootEntries.size();
1586
1587 LogFlowFunc(("cRoots=%RU32\n", cRoots));
1588
1589 if (cRoots)
1590 {
1591 PVBOXCLIPBOARDROOTLISTENTRY paRootListEntries
1592 = (PVBOXCLIPBOARDROOTLISTENTRY)RTMemAllocZ(cRoots * sizeof(VBOXCLIPBOARDROOTLISTENTRY));
1593 if (paRootListEntries)
1594 {
1595 for (uint32_t i = 0; i < cRoots; ++i)
1596 {
1597 rc = SharedClipboardURILTransferRootsEntry(pTransfer, i, &paRootListEntries[i]);
1598 if (RT_FAILURE(rc))
1599 break;
1600 }
1601
1602 if (RT_SUCCESS(rc))
1603 pRootList->paEntries = paRootListEntries;
1604 }
1605 else
1606 rc = VERR_NO_MEMORY;
1607 }
1608 else
1609 rc = VERR_NOT_FOUND;
1610
1611 if (RT_SUCCESS(rc))
1612 {
1613 pRootList->Hdr.cRoots = cRoots;
1614 pRootList->Hdr.fRoots = 0; /** @todo Implement this. */
1615
1616 *ppRootList = pRootList;
1617 }
1618 }
1619 else if (pTransfer->State.enmSource == SHAREDCLIPBOARDSOURCE_REMOTE)
1620 {
1621 if (pTransfer->ProviderIface.pfnGetRoots)
1622 rc = pTransfer->ProviderIface.pfnGetRoots(&pTransfer->ProviderCtx, ppRootList);
1623 else
1624 rc = VERR_NOT_SUPPORTED;
1625 }
1626
1627 LogFlowFuncLeaveRC(rc);
1628 return rc;
1629}
1630
1631/**
1632 * Returns the transfer's source.
1633 *
1634 * @returns The transfer's source.
1635 * @param pTransfer URI clipboard transfer to return source for.
1636 */
1637SHAREDCLIPBOARDSOURCE SharedClipboardURITransferGetSource(PSHAREDCLIPBOARDURITRANSFER pTransfer)
1638{
1639 AssertPtrReturn(pTransfer, SHAREDCLIPBOARDSOURCE_INVALID);
1640
1641 return pTransfer->State.enmSource;
1642}
1643
1644/**
1645 * Returns the current transfer status.
1646 *
1647 * @returns Current transfer status.
1648 * @param pTransfer URI clipboard transfer to return status for.
1649 */
1650SHAREDCLIPBOARDURITRANSFERSTATUS SharedClipboardURITransferGetStatus(PSHAREDCLIPBOARDURITRANSFER pTransfer)
1651{
1652 AssertPtrReturn(pTransfer, SHAREDCLIPBOARDURITRANSFERSTATUS_NONE);
1653
1654 return pTransfer->State.enmStatus;
1655}
1656
1657/**
1658 * Runs (starts) an URI transfer thread.
1659 *
1660 * @returns VBox status code.
1661 * @param pTransfer URI clipboard transfer to run.
1662 * @param pfnThreadFunc Pointer to thread function to use.
1663 * @param pvUser Pointer to user-provided data.
1664 */
1665int SharedClipboardURITransferRun(PSHAREDCLIPBOARDURITRANSFER pTransfer, PFNRTTHREAD pfnThreadFunc, void *pvUser)
1666{
1667 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
1668
1669 AssertMsgReturn(pTransfer->State.enmStatus == SHAREDCLIPBOARDURITRANSFERSTATUS_READY,
1670 ("Wrong status (currently is %RU32)\n", pTransfer->State.enmStatus), VERR_WRONG_ORDER);
1671
1672 int rc = sharedClipboardURITransferThreadCreate(pTransfer, pfnThreadFunc, pvUser);
1673
1674 LogFlowFuncLeaveRC(rc);
1675 return rc;
1676}
1677
1678/**
1679 * Sets or unsets the callback table to be used for a clipboard URI transfer.
1680 *
1681 * @returns VBox status code.
1682 * @param pTransfer URI clipboard transfer to set callbacks for.
1683 * @param pCallbacks Pointer to callback table to set.
1684 */
1685void SharedClipboardURITransferSetCallbacks(PSHAREDCLIPBOARDURITRANSFER pTransfer,
1686 PSHAREDCLIPBOARDURITRANSFERCALLBACKS pCallbacks)
1687{
1688 AssertPtrReturnVoid(pTransfer);
1689 AssertPtrReturnVoid(pCallbacks);
1690
1691 LogFlowFunc(("pCallbacks=%p\n", pCallbacks));
1692
1693#define SET_CALLBACK(a_pfnCallback) \
1694 if (pCallbacks->a_pfnCallback) \
1695 pTransfer->Callbacks.a_pfnCallback = pCallbacks->a_pfnCallback
1696
1697 SET_CALLBACK(pfnTransferPrepare);
1698 SET_CALLBACK(pfnTransferStarted);
1699 SET_CALLBACK(pfnListHeaderComplete);
1700 SET_CALLBACK(pfnListEntryComplete);
1701 SET_CALLBACK(pfnTransferCanceled);
1702 SET_CALLBACK(pfnTransferError);
1703 SET_CALLBACK(pfnTransferStarted);
1704
1705#undef SET_CALLBACK
1706
1707 pTransfer->Callbacks.pvUser = pCallbacks->pvUser;
1708}
1709
1710/**
1711 * Allocates a new event payload.
1712 *
1713 * @returns VBox status code.
1714 * @param uID Event ID to associate payload to.
1715 * @param pvData Data block to associate to this payload.
1716 * @param cbData Size (in bytes) of data block to associate.
1717 * @param ppPayload Where to store the allocated event payload on success.
1718 */
1719int SharedClipboardURITransferPayloadAlloc(uint32_t uID, const void *pvData, uint32_t cbData,
1720 PSHAREDCLIPBOARDURITRANSFERPAYLOAD *ppPayload)
1721{
1722 PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload =
1723 (PSHAREDCLIPBOARDURITRANSFERPAYLOAD)RTMemAlloc(sizeof(SHAREDCLIPBOARDURITRANSFERPAYLOAD));
1724 if (!pPayload)
1725 return VERR_NO_MEMORY;
1726
1727 pPayload->pvData = RTMemAlloc(cbData);
1728 if (pPayload->pvData)
1729 {
1730 memcpy(pPayload->pvData, pvData, cbData);
1731
1732 pPayload->cbData = cbData;
1733 pPayload->uID = uID;
1734
1735 *ppPayload = pPayload;
1736
1737 return VINF_SUCCESS;
1738 }
1739
1740 RTMemFree(pPayload);
1741 return VERR_NO_MEMORY;
1742}
1743
1744/**
1745 * Frees an event payload.
1746 *
1747 * @returns VBox status code.
1748 * @param pPayload URI clipboard transfer event payload to free.
1749 */
1750void SharedClipboardURITransferPayloadFree(PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload)
1751{
1752 if (!pPayload)
1753 return;
1754
1755 if (pPayload->pvData)
1756 {
1757 Assert(pPayload->cbData);
1758 RTMemFree(pPayload->pvData);
1759 pPayload->pvData = NULL;
1760 }
1761
1762 pPayload->cbData = 0;
1763
1764 RTMemFree(pPayload);
1765 pPayload = NULL;
1766}
1767
1768/**
1769 * Generates a new event ID for a specific URI transfer.
1770 *
1771 * @returns New event ID generated, or 0 on error.
1772 * @param pTransfer URI clipboard transfer to generate event for.
1773 */
1774uint16_t SharedClipboardURITransferEventIDGenerate(PSHAREDCLIPBOARDURITRANSFER pTransfer)
1775{
1776 LogFlowFunc(("New event %RU16\n", pTransfer->uEventIDNext));
1777 return pTransfer->uEventIDNext++; /** @todo Improve this. */
1778}
1779
1780/**
1781 * Registers an URI transfer event.
1782 *
1783 * @returns VBox status code.
1784 * @param pTransfer URI clipboard transfer to register event for.
1785 * @param uID Event ID to register.
1786 */
1787int SharedClipboardURITransferEventRegister(PSHAREDCLIPBOARDURITRANSFER pTransfer, uint16_t uID)
1788{
1789 int rc;
1790
1791 SharedClipboardURITransferEventMap::iterator itEvent = pTransfer->pMapEvents->find(uID);
1792 if (itEvent == pTransfer->pMapEvents->end())
1793 {
1794 PSHAREDCLIPBOARDURITRANSFEREVENT pEvent
1795 = (PSHAREDCLIPBOARDURITRANSFEREVENT)RTMemAllocZ(sizeof(SHAREDCLIPBOARDURITRANSFEREVENT));
1796 if (pEvent)
1797 {
1798 rc = RTSemEventCreate(&pEvent->hEventSem);
1799 if (RT_SUCCESS(rc))
1800 {
1801 pTransfer->pMapEvents->insert(std::pair<uint16_t, PSHAREDCLIPBOARDURITRANSFEREVENT>(uID, pEvent)); /** @todo Can this throw? */
1802
1803 LogFlowFunc(("Event %RU16\n", uID));
1804 }
1805 }
1806 else
1807 rc = VERR_NO_MEMORY;
1808 }
1809 else
1810 rc = VERR_ALREADY_EXISTS;
1811
1812#ifdef DEBUG_andy
1813 AssertRC(rc);
1814#endif
1815
1816 LogFlowFuncLeaveRC(rc);
1817 return rc;
1818}
1819
1820/**
1821 * Unregisters an URI transfer event.
1822 *
1823 * @returns VBox status code.
1824 * @param pTransfer URI clipboard transfer to unregister event for.
1825 * @param uID Event ID to unregister.
1826 */
1827int SharedClipboardURITransferEventUnregister(PSHAREDCLIPBOARDURITRANSFER pTransfer, uint16_t uID)
1828{
1829 int rc;
1830
1831 SharedClipboardURITransferEventMap::const_iterator itEvent = pTransfer->pMapEvents->find(uID);
1832 if (itEvent != pTransfer->pMapEvents->end())
1833 {
1834 SharedClipboardURITransferPayloadFree(itEvent->second->pPayload);
1835
1836 RTSemEventDestroy(itEvent->second->hEventSem);
1837
1838 RTMemFree(itEvent->second);
1839
1840 pTransfer->pMapEvents->erase(itEvent);
1841
1842 LogFlowFunc(("Event %RU16\n", uID));
1843
1844 rc = VINF_SUCCESS;
1845 }
1846 else
1847 rc = VERR_NOT_FOUND;
1848
1849 AssertRC(rc);
1850
1851 LogFlowFuncLeaveRC(rc);
1852 return rc;
1853}
1854
1855/**
1856 * Waits for an URI transfer event to get signalled.
1857 *
1858 * @returns VBox status code.
1859 * @param pTransfer URI clipboard transfer that contains the event to wait for.
1860 * @param uID Event ID to wait for.
1861 * @param uTimeoutMs Timeout (in ms) to wait.
1862 * @param ppPayload Where to store the (allocated) event payload on success. Needs to be free'd with
1863 * SharedClipboardURITransferPayloadFree().
1864 */
1865int SharedClipboardURITransferEventWait(PSHAREDCLIPBOARDURITRANSFER pTransfer, uint16_t uID, RTMSINTERVAL uTimeoutMs,
1866 PSHAREDCLIPBOARDURITRANSFERPAYLOAD *ppPayload)
1867{
1868 LogFlowFuncEnter();
1869
1870 int rc;
1871
1872 SharedClipboardURITransferEventMap::const_iterator itEvent = pTransfer->pMapEvents->find(uID);
1873 if (itEvent != pTransfer->pMapEvents->end())
1874 {
1875 rc = RTSemEventWait(itEvent->second->hEventSem, uTimeoutMs);
1876 if (RT_SUCCESS(rc))
1877 {
1878 *ppPayload = itEvent->second->pPayload;
1879
1880 itEvent->second->pPayload = NULL;
1881 }
1882 }
1883 else
1884 rc = VERR_NOT_FOUND;
1885
1886 LogFlowFuncLeaveRC(rc);
1887 return rc;
1888}
1889
1890/**
1891 * Signals an URI transfer event.
1892 *
1893 * @returns VBox status code.
1894 * @param pTransfer URI clipboard transfer of event to signal.
1895 * @param uID Event ID to signal.
1896 * @param pPayload Event payload to associate. Takes ownership. Optional.
1897 */
1898int SharedClipboardURITransferEventSignal(PSHAREDCLIPBOARDURITRANSFER pTransfer, uint16_t uID,
1899 PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload)
1900{
1901 int rc;
1902
1903 SharedClipboardURITransferEventMap::const_iterator itEvent = pTransfer->pMapEvents->find(uID);
1904 if (itEvent != pTransfer->pMapEvents->end())
1905 {
1906 Assert(itEvent->second->pPayload == NULL);
1907
1908 itEvent->second->pPayload = pPayload;
1909
1910 rc = RTSemEventSignal(itEvent->second->hEventSem);
1911 }
1912 else
1913 rc = VERR_NOT_FOUND;
1914
1915#ifdef DEBUG_andy
1916 AssertRC(rc);
1917#endif
1918
1919 LogFlowFuncLeaveRC(rc);
1920 return rc;
1921}
1922
1923/**
1924 * Creates a thread for a clipboard URI transfer.
1925 *
1926 * @returns VBox status code.
1927 * @param pTransfer URI clipboard transfer to create thread for.
1928 * @param pfnThreadFunc Thread function to use for this transfer.
1929 * @param pvUser Pointer to user-provided data.
1930 */
1931static int sharedClipboardURITransferThreadCreate(PSHAREDCLIPBOARDURITRANSFER pTransfer, PFNRTTHREAD pfnThreadFunc, void *pvUser)
1932
1933{
1934 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
1935
1936 /* Spawn a worker thread, so that we don't block the window thread for too long. */
1937 int rc = RTThreadCreate(&pTransfer->Thread.hThread, pfnThreadFunc,
1938 pvUser, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE,
1939 "shclp");
1940 if (RT_SUCCESS(rc))
1941 {
1942 int rc2 = RTThreadUserWait(pTransfer->Thread.hThread, 30 * 1000 /* Timeout in ms */);
1943 AssertRC(rc2);
1944
1945 if (pTransfer->Thread.fStarted) /* Did the thread indicate that it started correctly? */
1946 {
1947 pTransfer->State.enmStatus = SHAREDCLIPBOARDURITRANSFERSTATUS_RUNNING;
1948 }
1949 else
1950 rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
1951 }
1952
1953 LogFlowFuncLeaveRC(rc);
1954 return rc;
1955}
1956
1957/**
1958 * Destroys a thread of a clipboard URI transfer.
1959 *
1960 * @returns VBox status code.
1961 * @param pTransfer URI clipboard transfer to destroy thread for.
1962 * @param uTimeoutMs Timeout (in ms) to wait for thread creation.
1963 */
1964static int sharedClipboardURITransferThreadDestroy(PSHAREDCLIPBOARDURITRANSFER pTransfer, RTMSINTERVAL uTimeoutMs)
1965{
1966 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
1967
1968 if (pTransfer->Thread.hThread == NIL_RTTHREAD)
1969 return VINF_SUCCESS;
1970
1971 LogFlowFuncEnter();
1972
1973 /* Set stop indicator. */
1974 pTransfer->Thread.fStop = true;
1975
1976 int rcThread = VERR_WRONG_ORDER;
1977 int rc = RTThreadWait(pTransfer->Thread.hThread, uTimeoutMs, &rcThread);
1978
1979 LogFlowFunc(("Waiting for thread resulted in %Rrc (thread exited with %Rrc)\n", rc, rcThread));
1980
1981 return rc;
1982}
1983
1984/**
1985 * Initializes a clipboard URI transfer.
1986 *
1987 * @returns VBox status code.
1988 * @param pURI URI clipboard context to initialize.
1989 */
1990int SharedClipboardURICtxInit(PSHAREDCLIPBOARDURICTX pURI)
1991{
1992 AssertPtrReturn(pURI, VERR_INVALID_POINTER);
1993
1994 LogFlowFunc(("%p\n", pURI));
1995
1996 int rc = RTCritSectInit(&pURI->CritSect);
1997 if (RT_SUCCESS(rc))
1998 {
1999 RTListInit(&pURI->List);
2000
2001 pURI->cRunning = 0;
2002 pURI->cMaxRunning = 1; /* For now we only support one transfer per client at a time. */
2003
2004#ifdef DEBUG_andy
2005 pURI->cMaxRunning = UINT32_MAX;
2006#endif
2007 SharedClipboardURICtxReset(pURI);
2008 }
2009
2010 return VINF_SUCCESS;
2011}
2012
2013/**
2014 * Destroys an URI clipboard information context struct.
2015 *
2016 * @param pURI URI clipboard context to destroy.
2017 */
2018void SharedClipboardURICtxDestroy(PSHAREDCLIPBOARDURICTX pURI)
2019{
2020 AssertPtrReturnVoid(pURI);
2021
2022 LogFlowFunc(("%p\n", pURI));
2023
2024 RTCritSectDelete(&pURI->CritSect);
2025
2026 PSHAREDCLIPBOARDURITRANSFER pTransfer, pTransferNext;
2027 RTListForEachSafe(&pURI->List, pTransfer, pTransferNext, SHAREDCLIPBOARDURITRANSFER, Node)
2028 {
2029 SharedClipboardURITransferDestroy(pTransfer);
2030
2031 RTListNodeRemove(&pTransfer->Node);
2032
2033 RTMemFree(pTransfer);
2034 pTransfer = NULL;
2035 }
2036
2037 pURI->cRunning = 0;
2038 pURI->cTransfers = 0;
2039}
2040
2041/**
2042 * Resets an clipboard URI transfer.
2043 *
2044 * @param pURI URI clipboard context to reset.
2045 */
2046void SharedClipboardURICtxReset(PSHAREDCLIPBOARDURICTX pURI)
2047{
2048 AssertPtrReturnVoid(pURI);
2049
2050 LogFlowFuncEnter();
2051
2052 PSHAREDCLIPBOARDURITRANSFER pTransfer;
2053 RTListForEach(&pURI->List, pTransfer, SHAREDCLIPBOARDURITRANSFER, Node)
2054 SharedClipboardURITransferReset(pTransfer);
2055}
2056
2057/**
2058 * Adds a new URI transfer to an clipboard URI transfer.
2059 *
2060 * @returns VBox status code.
2061 * @param pURI URI clipboard context to add transfer to.
2062 * @param pTransfer Pointer to URI clipboard transfer to add.
2063 */
2064int SharedClipboardURICtxTransferAdd(PSHAREDCLIPBOARDURICTX pURI, PSHAREDCLIPBOARDURITRANSFER pTransfer)
2065{
2066 AssertPtrReturn(pURI, VERR_INVALID_POINTER);
2067 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
2068
2069 LogFlowFuncEnter();
2070
2071 if (pURI->cRunning == pURI->cMaxRunning)
2072 return VERR_SHCLPB_MAX_TRANSFERS_REACHED;
2073
2074 RTListAppend(&pURI->List, &pTransfer->Node);
2075
2076 pURI->cTransfers++;
2077 LogFlowFunc(("cTransfers=%RU32, cRunning=%RU32\n", pURI->cTransfers, pURI->cRunning));
2078
2079 return VINF_SUCCESS;
2080}
2081
2082/**
2083 * Removes an URI transfer from a clipboard URI transfer.
2084 *
2085 * @returns VBox status code.
2086 * @param pURI URI clipboard context to remove transfer from.
2087 * @param pTransfer Pointer to URI clipboard transfer to remove.
2088 */
2089int SharedClipboardURICtxTransferRemove(PSHAREDCLIPBOARDURICTX pURI, PSHAREDCLIPBOARDURITRANSFER pTransfer)
2090{
2091 AssertPtrReturn(pURI, VERR_INVALID_POINTER);
2092 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
2093
2094 LogFlowFuncEnter();
2095
2096
2097 int rc = SharedClipboardURITransferDestroy(pTransfer);
2098 if (RT_SUCCESS(rc))
2099 {
2100 RTListNodeRemove(&pTransfer->Node);
2101
2102 RTMemFree(pTransfer);
2103 pTransfer = NULL;
2104 }
2105
2106 LogFlowFuncLeaveRC(rc);
2107 return rc;
2108}
2109
2110/**
2111 * Returns a specific URI transfer, internal version.
2112 *
2113 * @returns URI transfer, or NULL if not found.
2114 * @param pURI URI clipboard context to return transfer for.
2115 * @param uIdx Index of the transfer to return.
2116 */
2117static PSHAREDCLIPBOARDURITRANSFER sharedClipboardURICtxGetTransferInternal(PSHAREDCLIPBOARDURICTX pURI, uint32_t uIdx)
2118{
2119 AssertReturn(uIdx == 0, NULL); /* Only one transfer allowed at the moment. */
2120 return RTListGetFirst(&pURI->List, SHAREDCLIPBOARDURITRANSFER, Node);
2121}
2122
2123/**
2124 * Returns a specific URI transfer.
2125 *
2126 * @returns URI transfer, or NULL if not found.
2127 * @param pURI URI clipboard context to return transfer for.
2128 * @param uIdx Index of the transfer to return.
2129 */
2130PSHAREDCLIPBOARDURITRANSFER SharedClipboardURICtxGetTransfer(PSHAREDCLIPBOARDURICTX pURI, uint32_t uIdx)
2131{
2132 return sharedClipboardURICtxGetTransferInternal(pURI, uIdx);
2133}
2134
2135/**
2136 * Returns the number of running URI transfers.
2137 *
2138 * @returns Number of running transfers.
2139 * @param pURI URI clipboard context to return number for.
2140 */
2141uint32_t SharedClipboardURICtxGetRunningTransfers(PSHAREDCLIPBOARDURICTX pURI)
2142{
2143 AssertPtrReturn(pURI, 0);
2144 return pURI->cRunning;
2145}
2146
2147/**
2148 * Returns the number of total URI transfers.
2149 *
2150 * @returns Number of total transfers.
2151 * @param pURI URI clipboard context to return number for.
2152 */
2153uint32_t SharedClipboardURICtxGetTotalTransfers(PSHAREDCLIPBOARDURICTX pURI)
2154{
2155 AssertPtrReturn(pURI, 0);
2156 return pURI->cTransfers;
2157}
2158
2159/**
2160 * Cleans up all associated transfers which are not needed (anymore).
2161 * This can be due to transfers which only have been announced but not / never being run.
2162 *
2163 * @param pURI URI clipboard context to cleanup transfers for.
2164 */
2165void SharedClipboardURICtxTransfersCleanup(PSHAREDCLIPBOARDURICTX pURI)
2166{
2167 AssertPtrReturnVoid(pURI);
2168
2169 LogFlowFunc(("cRunning=%RU32\n", pURI->cRunning));
2170
2171 /* Remove all transfers which are not in a running state (e.g. only announced). */
2172 PSHAREDCLIPBOARDURITRANSFER pTransfer, pTransferNext;
2173 RTListForEachSafe(&pURI->List, pTransfer, pTransferNext, SHAREDCLIPBOARDURITRANSFER, Node)
2174 {
2175 if (SharedClipboardURITransferGetStatus(pTransfer) != SHAREDCLIPBOARDURITRANSFERSTATUS_RUNNING)
2176 {
2177 SharedClipboardURITransferDestroy(pTransfer);
2178 RTListNodeRemove(&pTransfer->Node);
2179
2180 RTMemFree(pTransfer);
2181 pTransfer = NULL;
2182
2183 Assert(pURI->cTransfers);
2184 pURI->cTransfers--;
2185
2186 LogFlowFunc(("cTransfers=%RU32\n", pURI->cTransfers));
2187 }
2188 }
2189}
2190
2191/**
2192 * Returns whether the maximum of concurrent transfers of a specific URI context has been reached or not.
2193 *
2194 * @returns \c if maximum has been reached, \c false if not.
2195 * @param pURI URI clipboard context to determine value for.
2196 */
2197bool SharedClipboardURICtxTransfersMaximumReached(PSHAREDCLIPBOARDURICTX pURI)
2198{
2199 AssertPtrReturn(pURI, true);
2200
2201 LogFlowFunc(("cRunning=%RU32, cMaxRunning=%RU32\n", pURI->cRunning, pURI->cMaxRunning));
2202
2203 Assert(pURI->cRunning <= pURI->cMaxRunning);
2204 return pURI->cRunning == pURI->cMaxRunning;
2205}
2206
2207/**
2208 * Copies file system objinfo from IPRT to Shared Clipboard format.
2209 *
2210 * @param pDst The Shared Clipboard structure to convert data to.
2211 * @param pSrc The IPRT structure to convert data from.
2212 */
2213void SharedClipboardFsObjFromIPRT(PSHAREDCLIPBOARDFSOBJINFO pDst, PCRTFSOBJINFO pSrc)
2214{
2215 pDst->cbObject = pSrc->cbObject;
2216 pDst->cbAllocated = pSrc->cbAllocated;
2217 pDst->AccessTime = pSrc->AccessTime;
2218 pDst->ModificationTime = pSrc->ModificationTime;
2219 pDst->ChangeTime = pSrc->ChangeTime;
2220 pDst->BirthTime = pSrc->BirthTime;
2221 pDst->Attr.fMode = pSrc->Attr.fMode;
2222 /* Clear bits which we don't pass through for security reasons. */
2223 pDst->Attr.fMode &= ~(RTFS_UNIX_ISUID | RTFS_UNIX_ISGID | RTFS_UNIX_ISTXT);
2224 RT_ZERO(pDst->Attr.u);
2225 switch (pSrc->Attr.enmAdditional)
2226 {
2227 default:
2228 case RTFSOBJATTRADD_NOTHING:
2229 pDst->Attr.enmAdditional = SHAREDCLIPBOARDFSOBJATTRADD_NOTHING;
2230 break;
2231
2232 case RTFSOBJATTRADD_UNIX:
2233 pDst->Attr.enmAdditional = SHAREDCLIPBOARDFSOBJATTRADD_UNIX;
2234 pDst->Attr.u.Unix.uid = pSrc->Attr.u.Unix.uid;
2235 pDst->Attr.u.Unix.gid = pSrc->Attr.u.Unix.gid;
2236 pDst->Attr.u.Unix.cHardlinks = pSrc->Attr.u.Unix.cHardlinks;
2237 pDst->Attr.u.Unix.INodeIdDevice = pSrc->Attr.u.Unix.INodeIdDevice;
2238 pDst->Attr.u.Unix.INodeId = pSrc->Attr.u.Unix.INodeId;
2239 pDst->Attr.u.Unix.fFlags = pSrc->Attr.u.Unix.fFlags;
2240 pDst->Attr.u.Unix.GenerationId = pSrc->Attr.u.Unix.GenerationId;
2241 pDst->Attr.u.Unix.Device = pSrc->Attr.u.Unix.Device;
2242 break;
2243
2244 case RTFSOBJATTRADD_EASIZE:
2245 pDst->Attr.enmAdditional = SHAREDCLIPBOARDFSOBJATTRADD_EASIZE;
2246 pDst->Attr.u.EASize.cb = pSrc->Attr.u.EASize.cb;
2247 break;
2248 }
2249}
2250
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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