VirtualBox

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

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

Shared Clipboard/URI: Build fix.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 68.5 KB
 
1/* $Id: clipboard-uri.cpp 80285 2019-08-15 09:11:47Z 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++; /* Add directory itself. */
955
956 if (RT_SUCCESS(rc))
957 {
958 RTDIR hDir;
959 rc = RTDirOpen(&hDir, pcszSrcPath);
960 if (RT_SUCCESS(rc))
961 {
962 size_t cbDirEntry = 0;
963 PRTDIRENTRYEX pDirEntry = NULL;
964 do
965 {
966 /* Retrieve the next directory entry. */
967 rc = RTDirReadExA(hDir, &pDirEntry, &cbDirEntry, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
968 if (RT_FAILURE(rc))
969 {
970 if (rc == VERR_NO_MORE_FILES)
971 rc = VINF_SUCCESS;
972 break;
973 }
974
975 switch (pDirEntry->Info.Attr.fMode & RTFS_TYPE_MASK)
976 {
977 #if 0 /* No recursion here (yet). */
978 case RTFS_TYPE_DIRECTORY:
979 {
980 /* Skip "." and ".." entries. */
981 if (RTDirEntryExIsStdDotLink(pDirEntry))
982 break;
983
984 char *pszSrc = RTPathJoinA(pcszSrcPath, pDirEntry->szName);
985 if (pszSrc)
986 {
987 char *pszDst = RTPathJoinA(pcszDstPath, pDirEntry->szName);
988 if (pszDst)
989 {
990 rc = sharedClipboardURITransferListHdrFromDir(pHdr, pszSrc, pszDst,
991 pcszDstBase, cchDstBase);
992 RTStrFree(pszDst);
993 }
994 else
995 rc = VERR_NO_MEMORY;
996
997 RTStrFree(pszSrc);
998 }
999 else
1000 rc = VERR_NO_MEMORY;
1001 break;
1002 }
1003 #endif
1004 case RTFS_TYPE_FILE:
1005 {
1006 char *pszSrc = RTPathJoinA(pcszSrcPath, pDirEntry->szName);
1007 if (pszSrc)
1008 {
1009 rc = sharedClipboardURITransferListHdrAddFile(pHdr, pszSrc);
1010 RTStrFree(pszSrc);
1011 }
1012 else
1013 rc = VERR_NO_MEMORY;
1014 break;
1015 }
1016 case RTFS_TYPE_SYMLINK:
1017 {
1018 /** @todo Not implemented yet. */
1019 }
1020
1021 default:
1022 break;
1023 }
1024
1025 } while (RT_SUCCESS(rc));
1026
1027 RTDirReadExAFree(&pDirEntry, &cbDirEntry);
1028 RTDirClose(hDir);
1029 }
1030 }
1031 }
1032 else if (RTFS_IS_FILE(objInfo.Attr.fMode))
1033 {
1034 rc = sharedClipboardURITransferListHdrAddFile(pHdr, pcszSrcPath);
1035 }
1036 else if (RTFS_IS_SYMLINK(objInfo.Attr.fMode))
1037 {
1038 /** @todo Not implemented yet. */
1039 }
1040 else
1041 rc = VERR_NOT_SUPPORTED;
1042 }
1043
1044 LogFlowFuncLeaveRC(rc);
1045 return rc;
1046}
1047
1048/**
1049 * Retrieves the header of a Shared Clipboard list.
1050 *
1051 * @returns VBox status code.
1052 * @param pTransfer URI clipboard transfer to handle.
1053 * @param hList Handle of list to get header for.
1054 * @param pHdr Where to store the returned list header information.
1055 */
1056int SharedClipboardURITransferListGetHeader(PSHAREDCLIPBOARDURITRANSFER pTransfer, SHAREDCLIPBOARDLISTHANDLE hList,
1057 PVBOXCLIPBOARDLISTHDR pHdr)
1058{
1059 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
1060 AssertPtrReturn(pHdr, VERR_INVALID_POINTER);
1061
1062 int rc;
1063
1064 LogFlowFunc(("hList=%RU64\n", hList));
1065
1066 if (pTransfer->State.enmSource == SHAREDCLIPBOARDSOURCE_LOCAL)
1067 {
1068 SharedClipboardURIListMap::iterator itList = pTransfer->pMapLists->find(hList);
1069 if (itList != pTransfer->pMapLists->end())
1070 {
1071 rc = SharedClipboardURIListHdrInit(pHdr);
1072 if (RT_SUCCESS(rc))
1073 {
1074 PSHAREDCLIPBOARDURILISTHANDLEINFO pInfo = itList->second;
1075 AssertPtr(pInfo);
1076
1077 if (RTFS_IS_DIRECTORY(pInfo->fMode))
1078 {
1079 char *pszSrcPath = RTStrDup(pInfo->OpenParms.pszPath);
1080 if (pszSrcPath)
1081 {
1082 size_t cbSrcPathLen = RTPathStripTrailingSlash(pszSrcPath);
1083 if (cbSrcPathLen)
1084 {
1085 char *pszFileName = RTPathFilename(pszSrcPath);
1086 if (pszFileName)
1087 {
1088 Assert(pszFileName >= pszSrcPath);
1089 size_t cchDstBase = pszFileName - pszSrcPath;
1090#ifdef VBOX_STRICT
1091 char *pszDstPath = &pszSrcPath[cchDstBase];
1092 LogFlowFunc(("pszSrcPath=%s, pszFileName=%s, pszDstPath=%s\n",
1093 pszSrcPath, pszFileName, pszDstPath));
1094#endif
1095 rc = sharedClipboardURITransferListHdrFromDir(pHdr,
1096 pszSrcPath, pszSrcPath, pszSrcPath, cchDstBase);
1097 }
1098 else
1099 rc = VERR_PATH_NOT_FOUND;
1100 }
1101 else
1102 rc = VERR_INVALID_PARAMETER;
1103
1104 RTStrFree(pszSrcPath);
1105 }
1106 else
1107 rc = VERR_NO_MEMORY;
1108 }
1109 else if (RTFS_IS_FILE(pInfo->fMode))
1110 {
1111 pHdr->cTotalObjects = 1;
1112
1113 RTFSOBJINFO objInfo;
1114 rc = RTFileQueryInfo(pInfo->u.Local.hFile, &objInfo, RTFSOBJATTRADD_NOTHING);
1115 if (RT_SUCCESS(rc))
1116 {
1117 pHdr->cbTotalSize = objInfo.cbObject;
1118 }
1119 }
1120 else if (RTFS_IS_SYMLINK(pInfo->fMode))
1121 {
1122 rc = VERR_NOT_IMPLEMENTED; /** @todo */
1123 }
1124 else
1125 AssertFailedStmt(rc = VERR_NOT_SUPPORTED);
1126 }
1127 }
1128 else
1129 rc = VERR_NOT_FOUND;
1130 }
1131 else if (pTransfer->State.enmSource == SHAREDCLIPBOARDSOURCE_REMOTE)
1132 {
1133 if (pTransfer->ProviderIface.pfnListHdrRead)
1134 {
1135 rc = pTransfer->ProviderIface.pfnListHdrRead(&pTransfer->ProviderCtx, hList, pHdr);
1136 }
1137 else
1138 rc = VERR_NOT_SUPPORTED;
1139 }
1140 else
1141 AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED);
1142
1143 LogFlowFuncLeaveRC(rc);
1144 return rc;
1145}
1146
1147/**
1148 * Returns the current URI object for a clipboard URI transfer list.
1149 *
1150 * @returns Pointer to URI object.
1151 * @param pTransfer URI clipboard transfer to return URI object for.
1152 */
1153PSHAREDCLIPBOARDURITRANSFEROBJ SharedClipboardURITransferListGetObj(PSHAREDCLIPBOARDURITRANSFER pTransfer,
1154 SHAREDCLIPBOARDLISTHANDLE hList, uint64_t uIdx)
1155{
1156 AssertPtrReturn(pTransfer, NULL);
1157
1158 RT_NOREF(hList, uIdx);
1159
1160 LogFlowFunc(("hList=%RU64\n", hList));
1161
1162 return NULL;
1163}
1164
1165/**
1166 * Reads a single Shared Clipboard list entry.
1167 *
1168 * @returns VBox status code or VERR_NO_MORE_FILES if the end of the list has been reached.
1169 * @param pTransfer URI clipboard transfer to handle.
1170 * @param hList List handle of list to read from.
1171 * @param pEntry Where to store the read information.
1172 */
1173int SharedClipboardURITransferListRead(PSHAREDCLIPBOARDURITRANSFER pTransfer, SHAREDCLIPBOARDLISTHANDLE hList,
1174 PVBOXCLIPBOARDLISTENTRY pEntry)
1175{
1176 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
1177 AssertPtrReturn(pEntry, VERR_INVALID_POINTER);
1178
1179 int rc = VINF_SUCCESS;
1180
1181 LogFlowFunc(("hList=%RU64\n", hList));
1182
1183 if (pTransfer->State.enmSource == SHAREDCLIPBOARDSOURCE_LOCAL)
1184 {
1185 SharedClipboardURIListMap::iterator itList = pTransfer->pMapLists->find(hList);
1186 if (itList != pTransfer->pMapLists->end())
1187 {
1188 PSHAREDCLIPBOARDURILISTHANDLEINFO pInfo = itList->second;
1189 AssertPtr(pInfo);
1190
1191 LogFlowFunc(("\tfMode=%RU32, pszPath=%s\n", pInfo->fMode, pInfo->OpenParms.pszPath));
1192
1193 if (RTFS_IS_DIRECTORY(pInfo->fMode))
1194 {
1195 for (;;)
1196 {
1197 bool fSkipEntry = false; /* Whether to skip an entry in the enumeration. */
1198
1199 size_t cbDirEntry = 0;
1200 PRTDIRENTRYEX pDirEntry = NULL;
1201 rc = RTDirReadExA(pInfo->u.Local.hDirRoot, &pDirEntry, &cbDirEntry, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
1202 if (RT_SUCCESS(rc))
1203 {
1204 switch (pDirEntry->Info.Attr.fMode & RTFS_TYPE_MASK)
1205 {
1206 case RTFS_TYPE_DIRECTORY:
1207 {
1208 /* Skip "." and ".." entries. */
1209 if (RTDirEntryExIsStdDotLink(pDirEntry))
1210 {
1211 fSkipEntry = true;
1212 break;
1213 }
1214
1215 LogFlowFunc(("Directory: %s\n", pDirEntry->szName));
1216 break;
1217 }
1218
1219 case RTFS_TYPE_FILE:
1220 {
1221 LogFlowFunc(("File: %s\n", pDirEntry->szName));
1222 break;
1223 }
1224
1225 case RTFS_TYPE_SYMLINK:
1226 {
1227 rc = VERR_NOT_IMPLEMENTED; /** @todo Not implemented yet. */
1228 break;
1229 }
1230
1231 default:
1232 break;
1233 }
1234
1235 if ( RT_SUCCESS(rc)
1236 && !fSkipEntry)
1237 {
1238 pEntry->pvInfo = (PSHAREDCLIPBOARDFSOBJINFO)RTMemAlloc(sizeof(SHAREDCLIPBOARDFSOBJINFO));
1239 if (pEntry->pvInfo)
1240 {
1241 rc = RTStrCopy(pEntry->pszName, pEntry->cbName, pDirEntry->szName);
1242 if (RT_SUCCESS(rc))
1243 {
1244 SharedClipboardFsObjFromIPRT(PSHAREDCLIPBOARDFSOBJINFO(pEntry->pvInfo), &pDirEntry->Info);
1245
1246 pEntry->cbInfo = sizeof(SHAREDCLIPBOARDFSOBJINFO);
1247 pEntry->fInfo = VBOX_SHAREDCLIPBOARD_INFO_FLAG_FSOBJINFO;
1248 }
1249 }
1250 else
1251 rc = VERR_NO_MEMORY;
1252 }
1253
1254 RTDirReadExAFree(&pDirEntry, &cbDirEntry);
1255 }
1256
1257 if ( !fSkipEntry /* Do we have a valid entry? Bail out. */
1258 || RT_FAILURE(rc))
1259 {
1260 break;
1261 }
1262 }
1263 }
1264 else if (RTFS_IS_FILE(pInfo->fMode))
1265 {
1266 LogFlowFunc(("\tSingle file: %s\n", pInfo->OpenParms.pszPath));
1267
1268 RTFSOBJINFO objInfo;
1269 rc = RTFileQueryInfo(pInfo->u.Local.hFile, &objInfo, RTFSOBJATTRADD_NOTHING);
1270 if (RT_SUCCESS(rc))
1271 {
1272 pEntry->pvInfo = (PSHAREDCLIPBOARDFSOBJINFO)RTMemAlloc(sizeof(SHAREDCLIPBOARDFSOBJINFO));
1273 if (pEntry->pvInfo)
1274 {
1275 rc = RTStrCopy(pEntry->pszName, pEntry->cbName, pInfo->OpenParms.pszPath);
1276 if (RT_SUCCESS(rc))
1277 {
1278 SharedClipboardFsObjFromIPRT(PSHAREDCLIPBOARDFSOBJINFO(pEntry->pvInfo), &objInfo);
1279
1280 pEntry->cbInfo = sizeof(SHAREDCLIPBOARDFSOBJINFO);
1281 pEntry->fInfo = VBOX_SHAREDCLIPBOARD_INFO_FLAG_FSOBJINFO;
1282 }
1283 }
1284 else
1285 rc = VERR_NO_MEMORY;
1286 }
1287 }
1288 else if (RTFS_IS_SYMLINK(pInfo->fMode))
1289 {
1290 rc = VERR_NOT_IMPLEMENTED;
1291 }
1292 else
1293 AssertFailedStmt(rc = VERR_NOT_SUPPORTED);
1294 }
1295 else
1296 rc = VERR_NOT_FOUND;
1297 }
1298 else if (pTransfer->State.enmSource == SHAREDCLIPBOARDSOURCE_REMOTE)
1299 {
1300 if (pTransfer->ProviderIface.pfnListEntryRead)
1301 rc = pTransfer->ProviderIface.pfnListEntryRead(&pTransfer->ProviderCtx, hList, pEntry);
1302 else
1303 rc = VERR_NOT_SUPPORTED;
1304 }
1305
1306 LogFlowFuncLeaveRC(rc);
1307 return rc;
1308}
1309
1310int SharedClipboardURITransferListWrite(PSHAREDCLIPBOARDURITRANSFER pTransfer, SHAREDCLIPBOARDLISTHANDLE hList,
1311 PVBOXCLIPBOARDLISTENTRY pEntry)
1312{
1313 RT_NOREF(pTransfer, hList, pEntry);
1314
1315 int rc = VINF_SUCCESS;
1316
1317#if 0
1318 if (pTransfer->ProviderIface.pfnListEntryWrite)
1319 rc = pTransfer->ProviderIface.pfnListEntryWrite(&pTransfer->ProviderCtx, hList, pEntry);
1320#endif
1321
1322 LogFlowFuncLeaveRC(rc);
1323 return rc;
1324}
1325
1326/**
1327 * Returns whether a given list handle is valid or not.
1328 *
1329 * @returns \c true if list handle is valid, \c false if not.
1330 * @param pTransfer URI clipboard transfer to handle.
1331 * @param hList List handle to check.
1332 */
1333bool SharedClipboardURITransferListHandleIsValid(PSHAREDCLIPBOARDURITRANSFER pTransfer, SHAREDCLIPBOARDLISTHANDLE hList)
1334{
1335 bool fIsValid = false;
1336
1337 if (pTransfer->State.enmSource == SHAREDCLIPBOARDSOURCE_LOCAL)
1338 {
1339 SharedClipboardURIListMap::iterator itList = pTransfer->pMapLists->find(hList);
1340 fIsValid = itList != pTransfer->pMapLists->end();
1341 }
1342 else if (pTransfer->State.enmSource == SHAREDCLIPBOARDSOURCE_REMOTE)
1343 {
1344 AssertFailed(); /** @todo Implement. */
1345 }
1346
1347 return fIsValid;
1348}
1349
1350/**
1351 * Prepares everything needed for a read / write transfer to begin.
1352 *
1353 * @returns VBox status code.
1354 * @param pTransfer URI clipboard transfer to prepare.
1355 */
1356int SharedClipboardURITransferPrepare(PSHAREDCLIPBOARDURITRANSFER pTransfer)
1357{
1358 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
1359
1360 LogFlowFuncEnter();
1361
1362 int rc = VINF_SUCCESS;
1363
1364 AssertMsgReturn(pTransfer->State.enmStatus == SHAREDCLIPBOARDURITRANSFERSTATUS_NONE,
1365 ("Transfer has wrong state (%RU32)\n", pTransfer->State.enmStatus), VERR_WRONG_ORDER);
1366
1367 LogFlowFunc(("pTransfer=%p, enmDir=%RU32\n", pTransfer, pTransfer->State.enmDir));
1368
1369 if (pTransfer->Callbacks.pfnTransferPrepare)
1370 {
1371 SHAREDCLIPBOARDURITRANSFERCALLBACKDATA callbackData = { pTransfer, pTransfer->Callbacks.pvUser };
1372 pTransfer->Callbacks.pfnTransferPrepare(&callbackData);
1373 }
1374
1375 if (RT_SUCCESS(rc))
1376 {
1377 pTransfer->State.enmStatus = SHAREDCLIPBOARDURITRANSFERSTATUS_READY;
1378
1379 /** @todo Add checksum support. */
1380 }
1381
1382 LogFlowFuncLeaveRC(rc);
1383 return rc;
1384}
1385
1386/**
1387 * Sets the URI provider interface for a given transfer.
1388 *
1389 * @returns VBox status code.
1390 * @param pTransfer Transfer to create URI provider for.
1391 * @param pCreationCtx Provider creation context to use for provider creation.
1392 */
1393int SharedClipboardURITransferSetInterface(PSHAREDCLIPBOARDURITRANSFER pTransfer,
1394 PSHAREDCLIPBOARDPROVIDERCREATIONCTX pCreationCtx)
1395{
1396 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
1397 AssertPtrReturn(pCreationCtx, VERR_INVALID_POINTER);
1398
1399 LogFlowFuncEnter();
1400
1401 int rc = VINF_SUCCESS;
1402
1403 pTransfer->ProviderIface = pCreationCtx->Interface;
1404
1405 pTransfer->ProviderCtx.pTransfer = pTransfer;
1406 pTransfer->ProviderCtx.pvUser = pCreationCtx->pvUser;
1407
1408 LogFlowFuncLeaveRC(rc);
1409 return rc;
1410}
1411
1412/**
1413 * Clears (resets) the root list of an URI transfer.
1414 *
1415 * @param pTransfer Transfer to clear URI root list for.
1416 */
1417static void sharedClipboardURIListTransferRootsClear(PSHAREDCLIPBOARDURITRANSFER pTransfer)
1418{
1419 AssertPtrReturnVoid(pTransfer);
1420
1421 pTransfer->lstRootEntries.clear();
1422}
1423
1424/**
1425 * Sets URI root list entries for a given transfer.
1426 *
1427 * @returns VBox status code.
1428 * @param pTransfer Transfer to set URI list entries for.
1429 * @param pszRoots String list (separated by CRLF) of root entries to set.
1430 * @param cbRoots Size (in bytes) of string list.
1431 */
1432int SharedClipboardURILTransferSetRoots(PSHAREDCLIPBOARDURITRANSFER pTransfer, const char *pszRoots, size_t cbRoots)
1433{
1434 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
1435 AssertPtrReturn(pszRoots, VERR_INVALID_POINTER);
1436 AssertReturn(cbRoots, VERR_INVALID_PARAMETER);
1437
1438 if (!RTStrIsValidEncoding(pszRoots))
1439 return VERR_INVALID_PARAMETER;
1440
1441 int rc = VINF_SUCCESS;
1442
1443 sharedClipboardURIListTransferRootsClear(pTransfer);
1444
1445 RTCList<RTCString> lstRootEntries = RTCString(pszRoots, cbRoots - 1).split("\r\n");
1446 for (size_t i = 0; i < lstRootEntries.size(); ++i)
1447 {
1448 SHAREDCLIPBOARDURILISTROOT listRoot;
1449
1450 listRoot.strPathAbs = lstRootEntries.at(i);
1451
1452 pTransfer->lstRootEntries.append(listRoot);
1453 }
1454
1455 LogFlowFunc(("cRoots=%RU32\n", pTransfer->lstRootEntries.size()));
1456
1457 LogFlowFuncLeaveRC(rc);
1458 return rc;
1459}
1460
1461/**
1462 * Resets an clipboard URI transfer.
1463 *
1464 * @param pTransfer URI clipboard transfer to reset.
1465 */
1466void SharedClipboardURITransferReset(PSHAREDCLIPBOARDURITRANSFER pTransfer)
1467{
1468 AssertPtrReturnVoid(pTransfer);
1469
1470 LogFlowFuncEnter();
1471
1472 sharedClipboardURIListTransferRootsClear(pTransfer);
1473}
1474
1475/**
1476 * Returns the clipboard area for a clipboard URI transfer.
1477 *
1478 * @returns Current clipboard area, or NULL if none.
1479 * @param pTransfer URI clipboard transfer to return clipboard area for.
1480 */
1481SharedClipboardArea *SharedClipboardURITransferGetArea(PSHAREDCLIPBOARDURITRANSFER pTransfer)
1482{
1483 AssertPtrReturn(pTransfer, NULL);
1484
1485 return pTransfer->pArea;
1486}
1487
1488/**
1489 * Returns the number of URI root list entries.
1490 *
1491 * @returns Root list entry count.
1492 * @param pTransfer URI clipboard transfer to return root entry count for.
1493 */
1494uint32_t SharedClipboardURILTransferRootsCount(PSHAREDCLIPBOARDURITRANSFER pTransfer)
1495{
1496 AssertPtrReturn(pTransfer, 0);
1497
1498 return (uint32_t)pTransfer->lstRootEntries.size();
1499}
1500
1501/**
1502 * Get a specific root list entry.
1503 *
1504 * @returns VBox status code.
1505 * @param pTransfer URI clipboard transfer to get root list entry of.
1506 * @param uIndex Index (zero-based) of entry to get.
1507 * @param pEntry Where to store the returned entry on success.
1508 */
1509int SharedClipboardURILTransferRootsEntry(PSHAREDCLIPBOARDURITRANSFER pTransfer,
1510 uint32_t uIndex, PVBOXCLIPBOARDROOTLISTENTRY pEntry)
1511{
1512 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
1513 AssertPtrReturn(pEntry, VERR_INVALID_POINTER);
1514
1515 if (uIndex >= pTransfer->lstRootEntries.size())
1516 return VERR_INVALID_PARAMETER;
1517
1518 int rc;
1519
1520 PSHAREDCLIPBOARDURILISTROOT pRoot = &pTransfer->lstRootEntries.at(uIndex);
1521 AssertPtrReturn(pRoot, VERR_INVALID_POINTER);
1522
1523 /* Make sure that we only advertise relative source paths, not absolute ones. */
1524 const char *pcszSrcPath = pRoot->strPathAbs.c_str();
1525
1526 char *pszFileName = RTPathFilename(pcszSrcPath);
1527 if (pszFileName)
1528 {
1529 Assert(pszFileName >= pcszSrcPath);
1530 size_t cchDstBase = pszFileName - pcszSrcPath;
1531 const char *pszDstPath = &pcszSrcPath[cchDstBase];
1532
1533 LogFlowFunc(("pcszSrcPath=%s, pszDstPath=%s\n", pcszSrcPath, pszDstPath));
1534
1535 rc = SharedClipboardURIListEntryInit(pEntry);
1536 if (RT_SUCCESS(rc))
1537 {
1538 rc = RTStrCopy(pEntry->pszName, pEntry->cbName, pszDstPath);
1539 if (RT_SUCCESS(rc))
1540 {
1541 pEntry->cbInfo = sizeof(SHAREDCLIPBOARDFSOBJINFO);
1542 pEntry->pvInfo = (PSHAREDCLIPBOARDFSOBJINFO)RTMemAlloc(pEntry->cbInfo);
1543 if (pEntry->pvInfo)
1544 {
1545 RTFSOBJINFO fsObjInfo;
1546 rc = RTPathQueryInfo(pcszSrcPath, & fsObjInfo, RTFSOBJATTRADD_NOTHING);
1547 if (RT_SUCCESS(rc))
1548 {
1549 SharedClipboardFsObjFromIPRT(PSHAREDCLIPBOARDFSOBJINFO(pEntry->pvInfo), &fsObjInfo);
1550
1551 pEntry->fInfo = VBOX_SHAREDCLIPBOARD_INFO_FLAG_FSOBJINFO;
1552 }
1553 }
1554 else
1555 rc = VERR_NO_MEMORY;
1556 }
1557 }
1558 }
1559 else
1560 rc = VERR_INVALID_POINTER;
1561
1562 LogFlowFuncLeaveRC(rc);
1563 return rc;
1564}
1565
1566/**
1567 * Returns the root entries of an URI transfer.
1568 *
1569 * @returns VBox status code.
1570 * @param pTransfer URI clipboard transfer to return root entries for.
1571 * @param ppRootList Where to store the root list on success.
1572 */
1573int SharedClipboardURILTransferRootsAsList(PSHAREDCLIPBOARDURITRANSFER pTransfer, PVBOXCLIPBOARDROOTLIST *ppRootList)
1574{
1575 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
1576 AssertPtrReturn(ppRootList, VERR_INVALID_POINTER);
1577
1578 int rc = VINF_SUCCESS;
1579
1580 if (pTransfer->State.enmSource == SHAREDCLIPBOARDSOURCE_LOCAL)
1581 {
1582 PVBOXCLIPBOARDROOTLIST pRootList = SharedClipboardURIRootListAlloc();
1583 if (!pRootList)
1584 return VERR_NO_MEMORY;
1585
1586 const uint32_t cRoots = (uint32_t)pTransfer->lstRootEntries.size();
1587
1588 LogFlowFunc(("cRoots=%RU32\n", cRoots));
1589
1590 if (cRoots)
1591 {
1592 PVBOXCLIPBOARDROOTLISTENTRY paRootListEntries
1593 = (PVBOXCLIPBOARDROOTLISTENTRY)RTMemAllocZ(cRoots * sizeof(VBOXCLIPBOARDROOTLISTENTRY));
1594 if (paRootListEntries)
1595 {
1596 for (uint32_t i = 0; i < cRoots; ++i)
1597 {
1598 rc = SharedClipboardURILTransferRootsEntry(pTransfer, i, &paRootListEntries[i]);
1599 if (RT_FAILURE(rc))
1600 break;
1601 }
1602
1603 if (RT_SUCCESS(rc))
1604 pRootList->paEntries = paRootListEntries;
1605 }
1606 else
1607 rc = VERR_NO_MEMORY;
1608 }
1609 else
1610 rc = VERR_NOT_FOUND;
1611
1612 if (RT_SUCCESS(rc))
1613 {
1614 pRootList->Hdr.cRoots = cRoots;
1615 pRootList->Hdr.fRoots = 0; /** @todo Implement this. */
1616
1617 *ppRootList = pRootList;
1618 }
1619 }
1620 else if (pTransfer->State.enmSource == SHAREDCLIPBOARDSOURCE_REMOTE)
1621 {
1622 if (pTransfer->ProviderIface.pfnGetRoots)
1623 rc = pTransfer->ProviderIface.pfnGetRoots(&pTransfer->ProviderCtx, ppRootList);
1624 else
1625 rc = VERR_NOT_SUPPORTED;
1626 }
1627
1628 LogFlowFuncLeaveRC(rc);
1629 return rc;
1630}
1631
1632/**
1633 * Returns the transfer's source.
1634 *
1635 * @returns The transfer's source.
1636 * @param pTransfer URI clipboard transfer to return source for.
1637 */
1638SHAREDCLIPBOARDSOURCE SharedClipboardURITransferGetSource(PSHAREDCLIPBOARDURITRANSFER pTransfer)
1639{
1640 AssertPtrReturn(pTransfer, SHAREDCLIPBOARDSOURCE_INVALID);
1641
1642 return pTransfer->State.enmSource;
1643}
1644
1645/**
1646 * Returns the current transfer status.
1647 *
1648 * @returns Current transfer status.
1649 * @param pTransfer URI clipboard transfer to return status for.
1650 */
1651SHAREDCLIPBOARDURITRANSFERSTATUS SharedClipboardURITransferGetStatus(PSHAREDCLIPBOARDURITRANSFER pTransfer)
1652{
1653 AssertPtrReturn(pTransfer, SHAREDCLIPBOARDURITRANSFERSTATUS_NONE);
1654
1655 return pTransfer->State.enmStatus;
1656}
1657
1658/**
1659 * Runs (starts) an URI transfer thread.
1660 *
1661 * @returns VBox status code.
1662 * @param pTransfer URI clipboard transfer to run.
1663 * @param pfnThreadFunc Pointer to thread function to use.
1664 * @param pvUser Pointer to user-provided data.
1665 */
1666int SharedClipboardURITransferRun(PSHAREDCLIPBOARDURITRANSFER pTransfer, PFNRTTHREAD pfnThreadFunc, void *pvUser)
1667{
1668 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
1669
1670 AssertMsgReturn(pTransfer->State.enmStatus == SHAREDCLIPBOARDURITRANSFERSTATUS_READY,
1671 ("Wrong status (currently is %RU32)\n", pTransfer->State.enmStatus), VERR_WRONG_ORDER);
1672
1673 int rc = sharedClipboardURITransferThreadCreate(pTransfer, pfnThreadFunc, pvUser);
1674
1675 LogFlowFuncLeaveRC(rc);
1676 return rc;
1677}
1678
1679/**
1680 * Sets or unsets the callback table to be used for a clipboard URI transfer.
1681 *
1682 * @returns VBox status code.
1683 * @param pTransfer URI clipboard transfer to set callbacks for.
1684 * @param pCallbacks Pointer to callback table to set.
1685 */
1686void SharedClipboardURITransferSetCallbacks(PSHAREDCLIPBOARDURITRANSFER pTransfer,
1687 PSHAREDCLIPBOARDURITRANSFERCALLBACKS pCallbacks)
1688{
1689 AssertPtrReturnVoid(pTransfer);
1690 AssertPtrReturnVoid(pCallbacks);
1691
1692 LogFlowFunc(("pCallbacks=%p\n", pCallbacks));
1693
1694#define SET_CALLBACK(a_pfnCallback) \
1695 if (pCallbacks->a_pfnCallback) \
1696 pTransfer->Callbacks.a_pfnCallback = pCallbacks->a_pfnCallback
1697
1698 SET_CALLBACK(pfnTransferPrepare);
1699 SET_CALLBACK(pfnTransferStarted);
1700 SET_CALLBACK(pfnListHeaderComplete);
1701 SET_CALLBACK(pfnListEntryComplete);
1702 SET_CALLBACK(pfnTransferCanceled);
1703 SET_CALLBACK(pfnTransferError);
1704 SET_CALLBACK(pfnTransferStarted);
1705
1706#undef SET_CALLBACK
1707
1708 pTransfer->Callbacks.pvUser = pCallbacks->pvUser;
1709}
1710
1711/**
1712 * Allocates a new event payload.
1713 *
1714 * @returns VBox status code.
1715 * @param uID Event ID to associate payload to.
1716 * @param pvData Data block to associate to this payload.
1717 * @param cbData Size (in bytes) of data block to associate.
1718 * @param ppPayload Where to store the allocated event payload on success.
1719 */
1720int SharedClipboardURITransferPayloadAlloc(uint32_t uID, const void *pvData, uint32_t cbData,
1721 PSHAREDCLIPBOARDURITRANSFERPAYLOAD *ppPayload)
1722{
1723 PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload =
1724 (PSHAREDCLIPBOARDURITRANSFERPAYLOAD)RTMemAlloc(sizeof(SHAREDCLIPBOARDURITRANSFERPAYLOAD));
1725 if (!pPayload)
1726 return VERR_NO_MEMORY;
1727
1728 pPayload->pvData = RTMemAlloc(cbData);
1729 if (pPayload->pvData)
1730 {
1731 memcpy(pPayload->pvData, pvData, cbData);
1732
1733 pPayload->cbData = cbData;
1734 pPayload->uID = uID;
1735
1736 *ppPayload = pPayload;
1737
1738 return VINF_SUCCESS;
1739 }
1740
1741 RTMemFree(pPayload);
1742 return VERR_NO_MEMORY;
1743}
1744
1745/**
1746 * Frees an event payload.
1747 *
1748 * @returns VBox status code.
1749 * @param pPayload URI clipboard transfer event payload to free.
1750 */
1751void SharedClipboardURITransferPayloadFree(PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload)
1752{
1753 if (!pPayload)
1754 return;
1755
1756 if (pPayload->pvData)
1757 {
1758 Assert(pPayload->cbData);
1759 RTMemFree(pPayload->pvData);
1760 pPayload->pvData = NULL;
1761 }
1762
1763 pPayload->cbData = 0;
1764
1765 RTMemFree(pPayload);
1766 pPayload = NULL;
1767}
1768
1769/**
1770 * Generates a new event ID for a specific URI transfer.
1771 *
1772 * @returns New event ID generated, or 0 on error.
1773 * @param pTransfer URI clipboard transfer to generate event for.
1774 */
1775uint16_t SharedClipboardURITransferEventIDGenerate(PSHAREDCLIPBOARDURITRANSFER pTransfer)
1776{
1777 LogFlowFunc(("New event %RU16\n", pTransfer->uEventIDNext));
1778 return pTransfer->uEventIDNext++; /** @todo Improve this. */
1779}
1780
1781/**
1782 * Registers an URI transfer event.
1783 *
1784 * @returns VBox status code.
1785 * @param pTransfer URI clipboard transfer to register event for.
1786 * @param uID Event ID to register.
1787 */
1788int SharedClipboardURITransferEventRegister(PSHAREDCLIPBOARDURITRANSFER pTransfer, uint16_t uID)
1789{
1790 int rc;
1791
1792 SharedClipboardURITransferEventMap::iterator itEvent = pTransfer->pMapEvents->find(uID);
1793 if (itEvent == pTransfer->pMapEvents->end())
1794 {
1795 PSHAREDCLIPBOARDURITRANSFEREVENT pEvent
1796 = (PSHAREDCLIPBOARDURITRANSFEREVENT)RTMemAllocZ(sizeof(SHAREDCLIPBOARDURITRANSFEREVENT));
1797 if (pEvent)
1798 {
1799 rc = RTSemEventCreate(&pEvent->hEventSem);
1800 if (RT_SUCCESS(rc))
1801 {
1802 pTransfer->pMapEvents->insert(std::pair<uint16_t, PSHAREDCLIPBOARDURITRANSFEREVENT>(uID, pEvent)); /** @todo Can this throw? */
1803
1804 LogFlowFunc(("Event %RU16\n", uID));
1805 }
1806 }
1807 else
1808 rc = VERR_NO_MEMORY;
1809 }
1810 else
1811 rc = VERR_ALREADY_EXISTS;
1812
1813#ifdef DEBUG_andy
1814 AssertRC(rc);
1815#endif
1816
1817 LogFlowFuncLeaveRC(rc);
1818 return rc;
1819}
1820
1821/**
1822 * Unregisters an URI transfer event.
1823 *
1824 * @returns VBox status code.
1825 * @param pTransfer URI clipboard transfer to unregister event for.
1826 * @param uID Event ID to unregister.
1827 */
1828int SharedClipboardURITransferEventUnregister(PSHAREDCLIPBOARDURITRANSFER pTransfer, uint16_t uID)
1829{
1830 int rc;
1831
1832 SharedClipboardURITransferEventMap::const_iterator itEvent = pTransfer->pMapEvents->find(uID);
1833 if (itEvent != pTransfer->pMapEvents->end())
1834 {
1835 SharedClipboardURITransferPayloadFree(itEvent->second->pPayload);
1836
1837 RTSemEventDestroy(itEvent->second->hEventSem);
1838
1839 RTMemFree(itEvent->second);
1840
1841 pTransfer->pMapEvents->erase(itEvent);
1842
1843 LogFlowFunc(("Event %RU16\n", uID));
1844
1845 rc = VINF_SUCCESS;
1846 }
1847 else
1848 rc = VERR_NOT_FOUND;
1849
1850 AssertRC(rc);
1851
1852 LogFlowFuncLeaveRC(rc);
1853 return rc;
1854}
1855
1856/**
1857 * Waits for an URI transfer event to get signalled.
1858 *
1859 * @returns VBox status code.
1860 * @param pTransfer URI clipboard transfer that contains the event to wait for.
1861 * @param uID Event ID to wait for.
1862 * @param uTimeoutMs Timeout (in ms) to wait.
1863 * @param ppPayload Where to store the (allocated) event payload on success. Needs to be free'd with
1864 * SharedClipboardURITransferPayloadFree().
1865 */
1866int SharedClipboardURITransferEventWait(PSHAREDCLIPBOARDURITRANSFER pTransfer, uint16_t uID, RTMSINTERVAL uTimeoutMs,
1867 PSHAREDCLIPBOARDURITRANSFERPAYLOAD *ppPayload)
1868{
1869 LogFlowFuncEnter();
1870
1871 int rc;
1872
1873 SharedClipboardURITransferEventMap::const_iterator itEvent = pTransfer->pMapEvents->find(uID);
1874 if (itEvent != pTransfer->pMapEvents->end())
1875 {
1876 rc = RTSemEventWait(itEvent->second->hEventSem, uTimeoutMs);
1877 if (RT_SUCCESS(rc))
1878 {
1879 *ppPayload = itEvent->second->pPayload;
1880
1881 itEvent->second->pPayload = NULL;
1882 }
1883 }
1884 else
1885 rc = VERR_NOT_FOUND;
1886
1887 LogFlowFuncLeaveRC(rc);
1888 return rc;
1889}
1890
1891/**
1892 * Signals an URI transfer event.
1893 *
1894 * @returns VBox status code.
1895 * @param pTransfer URI clipboard transfer of event to signal.
1896 * @param uID Event ID to signal.
1897 * @param pPayload Event payload to associate. Takes ownership. Optional.
1898 */
1899int SharedClipboardURITransferEventSignal(PSHAREDCLIPBOARDURITRANSFER pTransfer, uint16_t uID,
1900 PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload)
1901{
1902 int rc;
1903
1904 SharedClipboardURITransferEventMap::const_iterator itEvent = pTransfer->pMapEvents->find(uID);
1905 if (itEvent != pTransfer->pMapEvents->end())
1906 {
1907 Assert(itEvent->second->pPayload == NULL);
1908
1909 itEvent->second->pPayload = pPayload;
1910
1911 rc = RTSemEventSignal(itEvent->second->hEventSem);
1912 }
1913 else
1914 rc = VERR_NOT_FOUND;
1915
1916#ifdef DEBUG_andy
1917 AssertRC(rc);
1918#endif
1919
1920 LogFlowFuncLeaveRC(rc);
1921 return rc;
1922}
1923
1924/**
1925 * Creates a thread for a clipboard URI transfer.
1926 *
1927 * @returns VBox status code.
1928 * @param pTransfer URI clipboard transfer to create thread for.
1929 * @param pfnThreadFunc Thread function to use for this transfer.
1930 * @param pvUser Pointer to user-provided data.
1931 */
1932static int sharedClipboardURITransferThreadCreate(PSHAREDCLIPBOARDURITRANSFER pTransfer, PFNRTTHREAD pfnThreadFunc, void *pvUser)
1933
1934{
1935 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
1936
1937 /* Spawn a worker thread, so that we don't block the window thread for too long. */
1938 int rc = RTThreadCreate(&pTransfer->Thread.hThread, pfnThreadFunc,
1939 pvUser, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE,
1940 "shclp");
1941 if (RT_SUCCESS(rc))
1942 {
1943 int rc2 = RTThreadUserWait(pTransfer->Thread.hThread, 30 * 1000 /* Timeout in ms */);
1944 AssertRC(rc2);
1945
1946 if (pTransfer->Thread.fStarted) /* Did the thread indicate that it started correctly? */
1947 {
1948 pTransfer->State.enmStatus = SHAREDCLIPBOARDURITRANSFERSTATUS_RUNNING;
1949 }
1950 else
1951 rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
1952 }
1953
1954 LogFlowFuncLeaveRC(rc);
1955 return rc;
1956}
1957
1958/**
1959 * Destroys a thread of a clipboard URI transfer.
1960 *
1961 * @returns VBox status code.
1962 * @param pTransfer URI clipboard transfer to destroy thread for.
1963 * @param uTimeoutMs Timeout (in ms) to wait for thread creation.
1964 */
1965static int sharedClipboardURITransferThreadDestroy(PSHAREDCLIPBOARDURITRANSFER pTransfer, RTMSINTERVAL uTimeoutMs)
1966{
1967 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
1968
1969 if (pTransfer->Thread.hThread == NIL_RTTHREAD)
1970 return VINF_SUCCESS;
1971
1972 LogFlowFuncEnter();
1973
1974 /* Set stop indicator. */
1975 pTransfer->Thread.fStop = true;
1976
1977 int rcThread = VERR_WRONG_ORDER;
1978 int rc = RTThreadWait(pTransfer->Thread.hThread, uTimeoutMs, &rcThread);
1979
1980 LogFlowFunc(("Waiting for thread resulted in %Rrc (thread exited with %Rrc)\n", rc, rcThread));
1981
1982 return rc;
1983}
1984
1985/**
1986 * Initializes a clipboard URI transfer.
1987 *
1988 * @returns VBox status code.
1989 * @param pURI URI clipboard context to initialize.
1990 */
1991int SharedClipboardURICtxInit(PSHAREDCLIPBOARDURICTX pURI)
1992{
1993 AssertPtrReturn(pURI, VERR_INVALID_POINTER);
1994
1995 LogFlowFunc(("%p\n", pURI));
1996
1997 int rc = RTCritSectInit(&pURI->CritSect);
1998 if (RT_SUCCESS(rc))
1999 {
2000 RTListInit(&pURI->List);
2001
2002 pURI->cRunning = 0;
2003 pURI->cMaxRunning = 1; /* For now we only support one transfer per client at a time. */
2004
2005#ifdef DEBUG_andy
2006 pURI->cMaxRunning = UINT32_MAX;
2007#endif
2008 SharedClipboardURICtxReset(pURI);
2009 }
2010
2011 return VINF_SUCCESS;
2012}
2013
2014/**
2015 * Destroys an URI clipboard information context struct.
2016 *
2017 * @param pURI URI clipboard context to destroy.
2018 */
2019void SharedClipboardURICtxDestroy(PSHAREDCLIPBOARDURICTX pURI)
2020{
2021 AssertPtrReturnVoid(pURI);
2022
2023 LogFlowFunc(("%p\n", pURI));
2024
2025 RTCritSectDelete(&pURI->CritSect);
2026
2027 PSHAREDCLIPBOARDURITRANSFER pTransfer, pTransferNext;
2028 RTListForEachSafe(&pURI->List, pTransfer, pTransferNext, SHAREDCLIPBOARDURITRANSFER, Node)
2029 {
2030 SharedClipboardURITransferDestroy(pTransfer);
2031
2032 RTListNodeRemove(&pTransfer->Node);
2033
2034 RTMemFree(pTransfer);
2035 pTransfer = NULL;
2036 }
2037
2038 pURI->cRunning = 0;
2039 pURI->cTransfers = 0;
2040}
2041
2042/**
2043 * Resets an clipboard URI transfer.
2044 *
2045 * @param pURI URI clipboard context to reset.
2046 */
2047void SharedClipboardURICtxReset(PSHAREDCLIPBOARDURICTX pURI)
2048{
2049 AssertPtrReturnVoid(pURI);
2050
2051 LogFlowFuncEnter();
2052
2053 PSHAREDCLIPBOARDURITRANSFER pTransfer;
2054 RTListForEach(&pURI->List, pTransfer, SHAREDCLIPBOARDURITRANSFER, Node)
2055 SharedClipboardURITransferReset(pTransfer);
2056}
2057
2058/**
2059 * Adds a new URI transfer to an clipboard URI transfer.
2060 *
2061 * @returns VBox status code.
2062 * @param pURI URI clipboard context to add transfer to.
2063 * @param pTransfer Pointer to URI clipboard transfer to add.
2064 */
2065int SharedClipboardURICtxTransferAdd(PSHAREDCLIPBOARDURICTX pURI, PSHAREDCLIPBOARDURITRANSFER pTransfer)
2066{
2067 AssertPtrReturn(pURI, VERR_INVALID_POINTER);
2068 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
2069
2070 LogFlowFuncEnter();
2071
2072 if (pURI->cRunning == pURI->cMaxRunning)
2073 return VERR_SHCLPB_MAX_TRANSFERS_REACHED;
2074
2075 RTListAppend(&pURI->List, &pTransfer->Node);
2076
2077 pURI->cTransfers++;
2078 LogFlowFunc(("cTransfers=%RU32, cRunning=%RU32\n", pURI->cTransfers, pURI->cRunning));
2079
2080 return VINF_SUCCESS;
2081}
2082
2083/**
2084 * Removes an URI transfer from a clipboard URI transfer.
2085 *
2086 * @returns VBox status code.
2087 * @param pURI URI clipboard context to remove transfer from.
2088 * @param pTransfer Pointer to URI clipboard transfer to remove.
2089 */
2090int SharedClipboardURICtxTransferRemove(PSHAREDCLIPBOARDURICTX pURI, PSHAREDCLIPBOARDURITRANSFER pTransfer)
2091{
2092 AssertPtrReturn(pURI, VERR_INVALID_POINTER);
2093 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
2094
2095 LogFlowFuncEnter();
2096
2097
2098 int rc = SharedClipboardURITransferDestroy(pTransfer);
2099 if (RT_SUCCESS(rc))
2100 {
2101 RTListNodeRemove(&pTransfer->Node);
2102
2103 RTMemFree(pTransfer);
2104 pTransfer = NULL;
2105 }
2106
2107 LogFlowFuncLeaveRC(rc);
2108 return rc;
2109}
2110
2111/**
2112 * Returns a specific URI transfer, internal version.
2113 *
2114 * @returns URI transfer, or NULL if not found.
2115 * @param pURI URI clipboard context to return transfer for.
2116 * @param uIdx Index of the transfer to return.
2117 */
2118static PSHAREDCLIPBOARDURITRANSFER sharedClipboardURICtxGetTransferInternal(PSHAREDCLIPBOARDURICTX pURI, uint32_t uIdx)
2119{
2120 AssertReturn(uIdx == 0, NULL); /* Only one transfer allowed at the moment. */
2121 return RTListGetFirst(&pURI->List, SHAREDCLIPBOARDURITRANSFER, Node);
2122}
2123
2124/**
2125 * Returns a specific URI transfer.
2126 *
2127 * @returns URI transfer, or NULL if not found.
2128 * @param pURI URI clipboard context to return transfer for.
2129 * @param uIdx Index of the transfer to return.
2130 */
2131PSHAREDCLIPBOARDURITRANSFER SharedClipboardURICtxGetTransfer(PSHAREDCLIPBOARDURICTX pURI, uint32_t uIdx)
2132{
2133 return sharedClipboardURICtxGetTransferInternal(pURI, uIdx);
2134}
2135
2136/**
2137 * Returns the number of running URI transfers.
2138 *
2139 * @returns Number of running transfers.
2140 * @param pURI URI clipboard context to return number for.
2141 */
2142uint32_t SharedClipboardURICtxGetRunningTransfers(PSHAREDCLIPBOARDURICTX pURI)
2143{
2144 AssertPtrReturn(pURI, 0);
2145 return pURI->cRunning;
2146}
2147
2148/**
2149 * Returns the number of total URI transfers.
2150 *
2151 * @returns Number of total transfers.
2152 * @param pURI URI clipboard context to return number for.
2153 */
2154uint32_t SharedClipboardURICtxGetTotalTransfers(PSHAREDCLIPBOARDURICTX pURI)
2155{
2156 AssertPtrReturn(pURI, 0);
2157 return pURI->cTransfers;
2158}
2159
2160/**
2161 * Cleans up all associated transfers which are not needed (anymore).
2162 * This can be due to transfers which only have been announced but not / never being run.
2163 *
2164 * @param pURI URI clipboard context to cleanup transfers for.
2165 */
2166void SharedClipboardURICtxTransfersCleanup(PSHAREDCLIPBOARDURICTX pURI)
2167{
2168 AssertPtrReturnVoid(pURI);
2169
2170 LogFlowFunc(("cRunning=%RU32\n", pURI->cRunning));
2171
2172 /* Remove all transfers which are not in a running state (e.g. only announced). */
2173 PSHAREDCLIPBOARDURITRANSFER pTransfer, pTransferNext;
2174 RTListForEachSafe(&pURI->List, pTransfer, pTransferNext, SHAREDCLIPBOARDURITRANSFER, Node)
2175 {
2176 if (SharedClipboardURITransferGetStatus(pTransfer) != SHAREDCLIPBOARDURITRANSFERSTATUS_RUNNING)
2177 {
2178 SharedClipboardURITransferDestroy(pTransfer);
2179 RTListNodeRemove(&pTransfer->Node);
2180
2181 RTMemFree(pTransfer);
2182 pTransfer = NULL;
2183
2184 Assert(pURI->cTransfers);
2185 pURI->cTransfers--;
2186
2187 LogFlowFunc(("cTransfers=%RU32\n", pURI->cTransfers));
2188 }
2189 }
2190}
2191
2192/**
2193 * Returns whether the maximum of concurrent transfers of a specific URI context has been reached or not.
2194 *
2195 * @returns \c if maximum has been reached, \c false if not.
2196 * @param pURI URI clipboard context to determine value for.
2197 */
2198bool SharedClipboardURICtxTransfersMaximumReached(PSHAREDCLIPBOARDURICTX pURI)
2199{
2200 AssertPtrReturn(pURI, true);
2201
2202 LogFlowFunc(("cRunning=%RU32, cMaxRunning=%RU32\n", pURI->cRunning, pURI->cMaxRunning));
2203
2204 Assert(pURI->cRunning <= pURI->cMaxRunning);
2205 return pURI->cRunning == pURI->cMaxRunning;
2206}
2207
2208/**
2209 * Copies file system objinfo from IPRT to Shared Clipboard format.
2210 *
2211 * @param pDst The Shared Clipboard structure to convert data to.
2212 * @param pSrc The IPRT structure to convert data from.
2213 */
2214void SharedClipboardFsObjFromIPRT(PSHAREDCLIPBOARDFSOBJINFO pDst, PCRTFSOBJINFO pSrc)
2215{
2216 pDst->cbObject = pSrc->cbObject;
2217 pDst->cbAllocated = pSrc->cbAllocated;
2218 pDst->AccessTime = pSrc->AccessTime;
2219 pDst->ModificationTime = pSrc->ModificationTime;
2220 pDst->ChangeTime = pSrc->ChangeTime;
2221 pDst->BirthTime = pSrc->BirthTime;
2222 pDst->Attr.fMode = pSrc->Attr.fMode;
2223 /* Clear bits which we don't pass through for security reasons. */
2224 pDst->Attr.fMode &= ~(RTFS_UNIX_ISUID | RTFS_UNIX_ISGID | RTFS_UNIX_ISTXT);
2225 RT_ZERO(pDst->Attr.u);
2226 switch (pSrc->Attr.enmAdditional)
2227 {
2228 default:
2229 case RTFSOBJATTRADD_NOTHING:
2230 pDst->Attr.enmAdditional = SHAREDCLIPBOARDFSOBJATTRADD_NOTHING;
2231 break;
2232
2233 case RTFSOBJATTRADD_UNIX:
2234 pDst->Attr.enmAdditional = SHAREDCLIPBOARDFSOBJATTRADD_UNIX;
2235 pDst->Attr.u.Unix.uid = pSrc->Attr.u.Unix.uid;
2236 pDst->Attr.u.Unix.gid = pSrc->Attr.u.Unix.gid;
2237 pDst->Attr.u.Unix.cHardlinks = pSrc->Attr.u.Unix.cHardlinks;
2238 pDst->Attr.u.Unix.INodeIdDevice = pSrc->Attr.u.Unix.INodeIdDevice;
2239 pDst->Attr.u.Unix.INodeId = pSrc->Attr.u.Unix.INodeId;
2240 pDst->Attr.u.Unix.fFlags = pSrc->Attr.u.Unix.fFlags;
2241 pDst->Attr.u.Unix.GenerationId = pSrc->Attr.u.Unix.GenerationId;
2242 pDst->Attr.u.Unix.Device = pSrc->Attr.u.Unix.Device;
2243 break;
2244
2245 case RTFSOBJATTRADD_EASIZE:
2246 pDst->Attr.enmAdditional = SHAREDCLIPBOARDFSOBJATTRADD_EASIZE;
2247 pDst->Attr.u.EASize.cb = pSrc->Attr.u.EASize.cb;
2248 break;
2249 }
2250}
2251
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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