VirtualBox

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

Last change on this file since 79860 was 79702, checked in by vboxsync, 5 years ago

Shared Clipboard/URI: Update.

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

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