VirtualBox

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

Last change on this file since 79497 was 79497, 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: 41.5 KB
Line 
1/* $Id: clipboard-uri.cpp 79497 2019-07-03 13:28:33Z 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/path.h>
22#include <iprt/semaphore.h>
23
24#include <VBox/err.h>
25#include <VBox/HostServices/VBoxClipboardSvc.h>
26#include <VBox/GuestHost/SharedClipboard-uri.h>
27
28
29#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
30static int sharedClipboardURITransferThreadCreate(PSHAREDCLIPBOARDURITRANSFER pTransfer, PFNRTTHREAD pfnThreadFunc, void *pvUser);
31static int sharedClipboardURITransferThreadDestroy(PSHAREDCLIPBOARDURITRANSFER pTransfer, RTMSINTERVAL uTimeoutMs);
32static int sharedClipboardURITransferWriteThread(RTTHREAD hThread, void *pvUser);
33static PSHAREDCLIPBOARDURITRANSFER sharedClipboardURICtxGetTransferInternal(PSHAREDCLIPBOARDURICTX pURI, uint32_t uIdx);
34#endif
35
36
37/**
38 * Allocates a VBOXCLIPBOARDListHdr structure.
39 *
40 * @returns VBox status code.
41 * @param ppListEntry Where to store the allocated VBOXCLIPBOARDListHdr structure on success.
42 */
43int SharedClipboardURIListHdrAlloc(PVBOXCLIPBOARDLISTHDR *ppListHdr)
44{
45 int rc;
46
47 PVBOXCLIPBOARDLISTHDR pListHdr = (PVBOXCLIPBOARDLISTHDR)RTMemAllocZ(sizeof(VBOXCLIPBOARDLISTHDR));
48 if (pListHdr)
49 {
50 *ppListHdr = pListHdr;
51 rc = VINF_SUCCESS;
52 }
53 else
54 rc = VERR_NO_MEMORY;
55
56 LogFlowFuncLeaveRC(rc);
57 return rc;
58}
59
60/**
61 * Frees a VBOXCLIPBOARDListHdr structure.
62 *
63 * @param pListEntry VBOXCLIPBOARDListHdr structure to free.
64 */
65void SharedClipboardURIListHdrFree(PVBOXCLIPBOARDLISTHDR pListHdr)
66{
67 if (!pListHdr)
68 return;
69
70 LogFlowFuncEnter();
71
72 SharedClipboardURIListHdrDestroy(pListHdr);
73
74 RTMemFree(pListHdr);
75 pListHdr = NULL;
76}
77
78/**
79 * Duplicates (allocates) a VBOXCLIPBOARDListHdr structure.
80 *
81 * @returns Duplicated VBOXCLIPBOARDListHdr structure on success.
82 * @param pListHdr VBOXCLIPBOARDListHdr to duplicate.
83 */
84PVBOXCLIPBOARDLISTHDR SharedClipboardURIListHdrDup(PVBOXCLIPBOARDLISTHDR pListHdr)
85{
86 AssertPtrReturn(pListHdr, NULL);
87
88 PVBOXCLIPBOARDLISTHDR pListHdrDup = (PVBOXCLIPBOARDLISTHDR)RTMemAlloc(sizeof(VBOXCLIPBOARDLISTHDR));
89 if (pListHdrDup)
90 {
91 *pListHdrDup = *pListHdr;
92
93 if (pListHdr->pszFilter)
94 {
95 pListHdrDup->pszFilter = RTStrDup(pListHdr->pszFilter);
96 pListHdrDup->cbFilter = (uint32_t)strlen(pListHdrDup->pszFilter);
97 }
98 }
99
100 return pListHdrDup;
101}
102
103/**
104 * Initializes an URI data header struct.
105 *
106 * @returns VBox status code.
107 * @param pListHdr Data header struct to initialize.
108 */
109int SharedClipboardURIListHdrInit(PVBOXCLIPBOARDLISTHDR pListHdr)
110{
111 AssertPtrReturn(pListHdr, VERR_INVALID_POINTER);
112
113 SharedClipboardURIListHdrReset(pListHdr);
114
115 return VINF_SUCCESS;
116}
117
118/**
119 * Destroys an URI data header struct.
120 *
121 * @param pListHdr Data header struct to destroy.
122 */
123void SharedClipboardURIListHdrDestroy(PVBOXCLIPBOARDLISTHDR pListHdr)
124{
125 if (!pListHdr)
126 return;
127
128 LogFlowFuncEnter();
129
130 if (pListHdr->pszFilter)
131 {
132 Assert(pListHdr->cbFilter);
133
134 RTStrFree(pListHdr->pszFilter);
135 pListHdr->pszFilter = NULL;
136 pListHdr->cbFilter = 0;
137 }
138}
139
140/**
141 * Resets a VBOXCLIPBOARDListHdr structture.
142 *
143 * @returns VBox status code.
144 * @param pListHdr VBOXCLIPBOARDListHdr structture to reset.
145 */
146void SharedClipboardURIListHdrReset(PVBOXCLIPBOARDLISTHDR pListHdr)
147{
148 AssertPtrReturnVoid(pListHdr);
149
150 LogFlowFuncEnter();
151
152 RT_BZERO(pListHdr, sizeof(VBOXCLIPBOARDLISTHDR));
153}
154
155/**
156 * Returns whether a given clipboard data header is valid or not.
157 *
158 * @returns \c true if valid, \c false if not.
159 * @param pListHdr Clipboard data header to validate.
160 */
161bool SharedClipboardURIListHdrIsValid(PVBOXCLIPBOARDLISTHDR pListHdr)
162{
163 RT_NOREF(pListHdr);
164 return true; /** @todo Implement this. */
165}
166
167/**
168 * Creates (allocates) and initializes a VBOXCLIPBOARDListEntry structure.
169 *
170 * @param ppDirData Where to return the created VBOXCLIPBOARDListEntry structure on success.
171 */
172int SharedClipboardURIListEntryAlloc(PVBOXCLIPBOARDLISTENTRY *ppListEntry)
173{
174 PVBOXCLIPBOARDLISTENTRY pListEntry = (PVBOXCLIPBOARDLISTENTRY)RTMemAlloc(sizeof(VBOXCLIPBOARDLISTENTRY));
175 if (!pListEntry)
176 return VERR_NO_MEMORY;
177
178 int rc = SharedClipboardURIListEntryInit(pListEntry);
179 if (RT_SUCCESS(rc))
180 *ppListEntry = pListEntry;
181
182 return rc;
183}
184
185/**
186 * Frees a VBOXCLIPBOARDListEntry structure.
187 *
188 * @param pListEntry VBOXCLIPBOARDListEntry structure to free.
189 */
190void SharedClipboardURIListEntryFree(PVBOXCLIPBOARDLISTENTRY pListEntry)
191{
192 if (!pListEntry)
193 return;
194
195 SharedClipboardURIListEntryDestroy(pListEntry);
196 RTMemFree(pListEntry);
197}
198
199/**
200 * Duplicates (allocates) a VBOXCLIPBOARDListEntry structure.
201 *
202 * @returns Duplicated VBOXCLIPBOARDListEntry structure on success.
203 * @param pListEntry VBOXCLIPBOARDListEntry to duplicate.
204 */
205PVBOXCLIPBOARDLISTENTRY SharedClipboardURIListEntryDup(PVBOXCLIPBOARDLISTENTRY pListEntry)
206{
207 AssertPtrReturn(pListEntry, NULL);
208
209 PVBOXCLIPBOARDLISTENTRY pListEntryDup = (PVBOXCLIPBOARDLISTENTRY)RTMemAlloc(sizeof(VBOXCLIPBOARDLISTENTRY));
210 if (pListEntryDup)
211 {
212 *pListEntryDup = *pListEntry;
213
214 if (pListEntry->pvInfo)
215 {
216 pListEntryDup->pvInfo= RTMemDup(pListEntry->pvInfo, pListEntry->cbInfo);
217 pListEntryDup->cbInfo = pListEntry->cbInfo;
218 }
219 }
220
221 return pListEntryDup;
222}
223
224/**
225 * Initializes a VBOXCLIPBOARDListEntry structure.
226 *
227 * @param pListEntry VBOXCLIPBOARDListEntry structure to initialize.
228 */
229int SharedClipboardURIListEntryInit(PVBOXCLIPBOARDLISTENTRY pListEntry)
230{
231 RT_BZERO(pListEntry, sizeof(VBOXCLIPBOARDLISTENTRY));
232
233 return VINF_SUCCESS;
234}
235
236/**
237 * Initializes a VBOXCLIPBOARDListEntry structure.
238 *
239 * @param pListEntry VBOXCLIPBOARDListEntry structure to destroy.
240 */
241void SharedClipboardURIListEntryDestroy(PVBOXCLIPBOARDLISTENTRY pListEntry)
242{
243 if (pListEntry->pvInfo)
244 {
245 RTMemFree(pListEntry->pvInfo);
246 pListEntry->pvInfo = NULL;
247 pListEntry->cbInfo = 0;
248 }
249}
250
251/**
252 * Returns whether a given clipboard data chunk is valid or not.
253 *
254 * @returns \c true if valid, \c false if not.
255 * @param pListEntry Clipboard data chunk to validate.
256 */
257bool SharedClipboardURIListEntryIsValid(PVBOXCLIPBOARDLISTENTRY pListEntry)
258{
259 RT_NOREF(pListEntry);
260
261 /** @todo Verify checksum. */
262
263 return true; /** @todo Implement this. */
264}
265
266#if 0
267/**
268 * Creates (allocates) and initializes a VBOXCLIPBOARDDIRDATA structure.
269 *
270 * @param ppDirData Where to return the created VBOXCLIPBOARDDIRDATA structure on success.
271 */
272int SharedClipboardURIDirDataAlloc(PVBOXCLIPBOARDDIRDATA *ppDirData)
273{
274 PVBOXCLIPBOARDDIRDATA pDirData = (PVBOXCLIPBOARDDIRDATA)RTMemAlloc(sizeof(VBOXCLIPBOARDDIRDATA));
275 if (!pDirData)
276 return VERR_NO_MEMORY;
277
278 int rc = SharedClipboardURIDirDataInit(pDirData);
279 if (RT_SUCCESS(rc))
280 *ppDirData = pDirData;
281
282 return rc;
283}
284
285/**
286 * Frees a VBOXCLIPBOARDDIRDATA structure.
287 *
288 * @param pDirData Where to return the created VBOXCLIPBOARDDIRDATA structure on success.
289 */
290void SharedClipboardURIDirDataFree(PVBOXCLIPBOARDDIRDATA pDirData)
291{
292 if (!pDirData)
293 return;
294
295 SharedClipboardURIDirDataDestroy(pDirData);
296 RTMemFree(pDirData);
297}
298
299/**
300 * Initializes a VBOXCLIPBOARDDIRDATA structure.
301 *
302 * @param pDirData VBOXCLIPBOARDDIRDATA structure to initialize.
303 */
304int SharedClipboardURIDirDataInit(PVBOXCLIPBOARDDIRDATA pDirData)
305{
306 RT_BZERO(pDirData, sizeof(VBOXCLIPBOARDDIRDATA));
307
308 return VINF_SUCCESS;
309}
310
311/**
312 * Destroys a VBOXCLIPBOARDDIRDATA structure.
313 *
314 * @param pDirData VBOXCLIPBOARDDIRDATA structure to destroy.
315 */
316void SharedClipboardURIDirDataDestroy(PVBOXCLIPBOARDDIRDATA pDirData)
317{
318 if (!pDirData)
319 return;
320
321 if (pDirData->pszPath)
322 {
323 Assert(pDirData->cbPath);
324 RTStrFree(pDirData->pszPath);
325 pDirData->pszPath = NULL;
326 }
327}
328
329/**
330 * Duplicates (allocates) a VBOXCLIPBOARDDIRDATA structure.
331 *
332 * @returns Duplicated VBOXCLIPBOARDDIRDATA structure on success.
333 * @param pDirData VBOXCLIPBOARDDIRDATA to duplicate.
334 */
335PVBOXCLIPBOARDDIRDATA SharedClipboardURIDirDataDup(PVBOXCLIPBOARDDIRDATA pDirData)
336{
337 AssertPtrReturn(pDirData, NULL);
338
339 PVBOXCLIPBOARDDIRDATA pDirDataDup = (PVBOXCLIPBOARDDIRDATA)RTMemAllocZ(sizeof(VBOXCLIPBOARDDIRDATA));
340 if (pDirDataDup)
341 {
342 *pDirDataDup = *pDirData;
343
344 if (pDirData->pszPath)
345 {
346 pDirDataDup->pszPath = RTStrDup(pDirData->pszPath);
347 if (pDirDataDup->pszPath)
348 pDirDataDup->cbPath = pDirData->cbPath;
349 }
350 }
351
352 return pDirDataDup;
353}
354
355/**
356 * Returns whether given clipboard directory data is valid or not.
357 *
358 * @returns \c true if valid, \c false if not.
359 * @param pDirData Clipboard directory data to validate.
360 */
361bool SharedClipboardURIDirDataIsValid(PVBOXCLIPBOARDDIRDATA pDirData)
362{
363 if ( !pDirData->cbPath
364 || pDirData->cbPath > RTPATH_MAX)
365 return false;
366
367 if (!RTStrIsValidEncoding(pDirData->pszPath))
368 return false;
369
370 return true;
371}
372
373/**
374 * Initializes a VBOXCLIPBOARDFILEHDR structure.
375 *
376 * @param pDirData VBOXCLIPBOARDFILEHDR structure to initialize.
377 */
378int SharedClipboardURIFileHdrInit(PVBOXCLIPBOARDFILEHDR pFileHdr)
379{
380 RT_BZERO(pFileHdr, sizeof(VBOXCLIPBOARDFILEHDR));
381
382 return VINF_SUCCESS;
383}
384
385/**
386 * Destroys a VBOXCLIPBOARDFILEHDR structure.
387 *
388 * @param pFileHdr VBOXCLIPBOARDFILEHDR structure to destroy.
389 */
390void SharedClipboardURIFileHdrDestroy(PVBOXCLIPBOARDFILEHDR pFileHdr)
391{
392 if (!pFileHdr)
393 return;
394
395 if (pFileHdr->pszFilePath)
396 {
397 Assert(pFileHdr->pszFilePath);
398 RTStrFree(pFileHdr->pszFilePath);
399 pFileHdr->pszFilePath = NULL;
400 }
401}
402
403/**
404 * Frees a VBOXCLIPBOARDFILEHDR structure.
405 *
406 * @param pFileHdr VBOXCLIPBOARDFILEHDR structure to free.
407 */
408void SharedClipboardURIFileHdrFree(PVBOXCLIPBOARDFILEHDR pFileHdr)
409{
410 if (!pFileHdr)
411 return;
412
413 SharedClipboardURIFileHdrDestroy(pFileHdr);
414
415 RTMemFree(pFileHdr);
416 pFileHdr = NULL;
417}
418
419/**
420 * Duplicates (allocates) a VBOXCLIPBOARDFILEHDR structure.
421 *
422 * @returns Duplicated VBOXCLIPBOARDFILEHDR structure on success.
423 * @param pFileHdr VBOXCLIPBOARDFILEHDR to duplicate.
424 */
425PVBOXCLIPBOARDFILEHDR SharedClipboardURIFileHdrDup(PVBOXCLIPBOARDFILEHDR pFileHdr)
426{
427 AssertPtrReturn(pFileHdr, NULL);
428
429 PVBOXCLIPBOARDFILEHDR pFileHdrDup = (PVBOXCLIPBOARDFILEHDR)RTMemAllocZ(sizeof(VBOXCLIPBOARDFILEHDR));
430 if (pFileHdrDup)
431 {
432 *pFileHdrDup = *pFileHdr;
433
434 if (pFileHdr->pszFilePath)
435 {
436 pFileHdrDup->pszFilePath = RTStrDup(pFileHdr->pszFilePath);
437 if (pFileHdrDup->pszFilePath)
438 pFileHdrDup->cbFilePath = pFileHdrDup->cbFilePath;
439 }
440 }
441
442 return pFileHdrDup;
443}
444
445/**
446 * Returns whether a given clipboard file header is valid or not.
447 *
448 * @returns \c true if valid, \c false if not.
449 * @param pFileHdr Clipboard file header to validate.
450 * @param pListHdr Data header to use for validation.
451 */
452bool SharedClipboardURIFileHdrIsValid(PVBOXCLIPBOARDFILEHDR pFileHdr, PVBOXCLIPBOARDLISTHDR pListHdr)
453{
454 if ( !pFileHdr->cbFilePath
455 || pFileHdr->cbFilePath > RTPATH_MAX)
456 return false;
457
458 if (!RTStrIsValidEncoding(pFileHdr->pszFilePath))
459 return false;
460
461 if (pFileHdr->cbSize > pListHdr->cbTotalSize)
462 return false;
463
464 return true;
465}
466
467/**
468 * Destroys a VBOXCLIPBOARDFILEDATA structure.
469 *
470 * @param pFileData VBOXCLIPBOARDFILEDATA structure to destroy.
471 */
472void SharedClipboardURIFileDataDestroy(PVBOXCLIPBOARDFILEDATA pFileData)
473{
474 if (!pFileData)
475 return;
476
477 if (pFileData->pvData)
478 {
479 Assert(pFileData->cbData);
480 RTMemFree(pFileData->pvData);
481 pFileData->pvData = NULL;
482 }
483}
484
485/**
486 * Duplicates (allocates) a VBOXCLIPBOARDFILEDATA structure.
487 *
488 * @returns Duplicated VBOXCLIPBOARDFILEDATA structure on success.
489 * @param pFileData VBOXCLIPBOARDFILEDATA to duplicate.
490 */
491PVBOXCLIPBOARDFILEDATA SharedClipboardURIFileDataDup(PVBOXCLIPBOARDFILEDATA pFileData)
492{
493 AssertPtrReturn(pFileData, NULL);
494
495 PVBOXCLIPBOARDFILEDATA pFileDataDup = (PVBOXCLIPBOARDFILEDATA)RTMemAllocZ(sizeof(VBOXCLIPBOARDFILEDATA));
496 if (pFileDataDup)
497 {
498 *pFileDataDup = *pFileData;
499
500 if (pFileData->pvData)
501 {
502 pFileDataDup->pvData = RTMemDup(pFileData->pvData, pFileData->cbData);
503 if (pFileDataDup->pvData)
504 pFileDataDup->cbData = pFileDataDup->cbData;
505 }
506
507 if (pFileData->pvChecksum)
508 {
509 pFileDataDup->pvChecksum = RTMemDup(pFileData->pvChecksum, pFileData->cbChecksum);
510 if (pFileDataDup->pvChecksum)
511 pFileDataDup->cbChecksum = pFileData->cbChecksum;
512 }
513 }
514
515 return pFileDataDup;
516}
517
518/**
519 * Returns whether given clipboard file data is valid or not.
520 *
521 * @returns \c true if valid, \c false if not.
522 * @param pFileData Clipboard file data to validate.
523 * @param pListHdr Data header to use for validation.
524 */
525bool SharedClipboardURIFileDataIsValid(PVBOXCLIPBOARDFILEDATA pFileData, PVBOXCLIPBOARDLISTHDR pListHdr)
526{
527 RT_NOREF(pFileData, pListHdr);
528 return true;
529}
530#endif
531
532/**
533 * Initializes an URI object context.
534 *
535 * @returns VBox status code.
536 * @param pObjCtx URI object context to initialize.
537 */
538int SharedClipboardURIObjCtxInit(PSHAREDCLIPBOARDCLIENTURIOBJCTX pObjCtx)
539{
540 AssertPtrReturn(pObjCtx, VERR_INVALID_POINTER);
541
542 LogFlowFuncEnter();
543
544 pObjCtx->uHandle = SHAREDCLIPBOARDOBJHANDLE_INVALID;
545 pObjCtx->pObjInfo = NULL;
546
547 return VINF_SUCCESS;
548}
549
550/**
551 * Destroys an URI object context.
552 *
553 * @param pObjCtx URI object context to destroy.
554 */
555void SharedClipboardURIObjCtxDestroy(PSHAREDCLIPBOARDCLIENTURIOBJCTX pObjCtx)
556{
557 AssertPtrReturnVoid(pObjCtx);
558
559 LogFlowFuncEnter();
560
561 pObjCtx->pObjInfo = NULL;
562}
563
564/**
565 * Returns if an URI object context is valid or not.
566 *
567 * @returns \c true if valid, \c false if not.
568 * @param pObjCtx URI object context to check.
569 */
570bool SharedClipboardURIObjCtxIsValid(PSHAREDCLIPBOARDCLIENTURIOBJCTX pObjCtx)
571{
572 return ( pObjCtx
573 && pObjCtx->uHandle != SHAREDCLIPBOARDOBJHANDLE_INVALID
574 && pObjCtx->pObjInfo);
575}
576
577/**
578 * Initializes an URI clipboard transfer struct.
579 *
580 * @returns VBox status code.
581 * @param enmDir Specifies the transfer direction of this transfer.
582 * @param enmSource Specifies the data source of the transfer.
583 * @param ppTransfer Where to return the created URI transfer struct.
584 * Must be destroyed by SharedClipboardURITransferDestroy().
585 */
586int SharedClipboardURITransferCreate(SHAREDCLIPBOARDURITRANSFERDIR enmDir, SHAREDCLIPBOARDSOURCE enmSource,
587 PSHAREDCLIPBOARDURITRANSFER *ppTransfer)
588{
589 AssertPtrReturn(ppTransfer, VERR_INVALID_POINTER);
590
591 LogFlowFuncEnter();
592
593 PSHAREDCLIPBOARDURITRANSFER pTransfer = (PSHAREDCLIPBOARDURITRANSFER)RTMemAlloc(sizeof(SHAREDCLIPBOARDURITRANSFER));
594 if (!pTransfer)
595 return VERR_NO_MEMORY;
596
597 int rc = VINF_SUCCESS;
598
599 pTransfer->State.enmStatus = SHAREDCLIPBOARDURITRANSFERSTATUS_NONE;
600 pTransfer->State.enmDir = enmDir;
601 pTransfer->State.enmSource = enmSource;
602
603 LogFlowFunc(("enmDir=%RU32, enmSource=%RU32\n", pTransfer->State.enmDir, pTransfer->State.enmSource));
604
605 pTransfer->pArea = NULL; /* Will be created later if needed. */
606
607 pTransfer->Thread.hThread = NIL_RTTHREAD;
608 pTransfer->Thread.fCancelled = false;
609 pTransfer->Thread.fStarted = false;
610 pTransfer->Thread.fStop = false;
611
612 pTransfer->pvUser = NULL;
613 pTransfer->cbUser = 0;
614
615 RT_ZERO(pTransfer->Callbacks);
616
617 pTransfer->pURIList = new SharedClipboardURIList();
618 if (pTransfer->pURIList)
619 {
620 pTransfer->Events.pMap = new SharedClipboardURITransferEventMap();
621 if (pTransfer->Events.pMap)
622 {
623 rc = SharedClipboardURIObjCtxInit(&pTransfer->State.ObjCtx);
624 if (RT_SUCCESS(rc))
625 {
626 *ppTransfer = pTransfer;
627 }
628 }
629 else
630 rc = VERR_NO_MEMORY;
631 }
632 else
633 rc = VERR_NO_MEMORY;
634
635 if (RT_FAILURE(rc))
636 {
637 RTMemFree(pTransfer);
638 }
639
640 LogFlowFuncLeaveRC(rc);
641 return rc;
642}
643
644/**
645 * Destroys an URI clipboard transfer context struct.
646 *
647 * @returns VBox status code.
648 * @param pURI URI clipboard transfer to destroy.
649 */
650int SharedClipboardURITransferDestroy(PSHAREDCLIPBOARDURITRANSFER pTransfer)
651{
652 if (!pTransfer)
653 return VINF_SUCCESS;
654
655 LogFlowFuncEnter();
656
657 int rc = sharedClipboardURITransferThreadDestroy(pTransfer, 30 * 1000 /* Timeout in ms */);
658 if (RT_FAILURE(rc))
659 return rc;
660
661 if (pTransfer->pURIList)
662 {
663 delete pTransfer->pURIList;
664 pTransfer->pURIList = NULL;
665 }
666
667 if (pTransfer->Events.pMap)
668 {
669 delete pTransfer->Events.pMap;
670 pTransfer->Events.pMap = NULL;
671 }
672
673 SharedClipboardURIObjCtxDestroy(&pTransfer->State.ObjCtx);
674
675 LogFlowFuncLeave();
676 return VINF_SUCCESS;
677}
678
679int SharedClipboardURITransferOpen(PSHAREDCLIPBOARDURITRANSFER pTransfer)
680{
681 int rc = VINF_SUCCESS;
682
683 if (pTransfer->ProviderIface.pfnTransferOpen)
684 rc = pTransfer->ProviderIface.pfnTransferOpen(&pTransfer->ProviderCtx);
685
686 LogFlowFuncLeaveRC(rc);
687 return rc;
688}
689
690int SharedClipboardURITransferClose(PSHAREDCLIPBOARDURITRANSFER pTransfer)
691{
692 int rc = VINF_SUCCESS;
693
694 if (pTransfer->ProviderIface.pfnTransferClose)
695 rc = pTransfer->ProviderIface.pfnTransferClose(&pTransfer->ProviderCtx);
696
697 LogFlowFuncLeaveRC(rc);
698 return rc;
699}
700
701int SharedClipboardURITransferListOpen(PSHAREDCLIPBOARDURITRANSFER pTransfer, PVBOXCLIPBOARDLISTHDR pListHdr,
702 PVBOXCLIPBOARDLISTHANDLE phList)
703{
704 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
705 AssertPtrReturn(pListHdr, VERR_INVALID_POINTER);
706 /* phList is optional. */
707
708 int rc = VINF_SUCCESS;
709
710 VBOXCLIPBOARDLISTHANDLE hList = SHAREDCLIPBOARDLISTHANDLE_INVALID;
711
712 if (pTransfer->ProviderIface.pfnListOpen)
713 rc = pTransfer->ProviderIface.pfnListOpen(&pTransfer->ProviderCtx, pListHdr, &hList);
714
715 if (RT_SUCCESS(rc))
716 {
717 AssertPtr(pTransfer->ProviderIface.pfnListHdrRead);
718 rc = pTransfer->ProviderIface.pfnListHdrRead(&pTransfer->ProviderCtx, hList, pListHdr);
719 }
720
721 if (RT_SUCCESS(rc))
722 {
723 if (phList)
724 *phList = hList;
725 }
726 else if (pTransfer->ProviderIface.pfnListClose)
727 {
728 int rc2 = pTransfer->ProviderIface.pfnListClose(&pTransfer->ProviderCtx, hList);
729 AssertRC(rc2);
730 }
731
732 LogFlowFuncLeaveRC(rc);
733 return rc;
734}
735
736int SharedClipboardURITransferListClose(PSHAREDCLIPBOARDURITRANSFER pTransfer, VBOXCLIPBOARDLISTHANDLE hList)
737{
738 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
739
740 int rc = VINF_SUCCESS;
741
742 if (pTransfer->ProviderIface.pfnListClose)
743 rc = pTransfer->ProviderIface.pfnListClose(&pTransfer->ProviderCtx, hList);
744
745 LogFlowFuncLeaveRC(rc);
746 return rc;
747}
748
749int SharedClipboardURITransferListRead(PSHAREDCLIPBOARDURITRANSFER pTransfer, VBOXCLIPBOARDLISTHANDLE hList,
750 PVBOXCLIPBOARDLISTENTRY pEntry)
751{
752 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
753
754 int rc = VINF_SUCCESS;
755
756 if (pTransfer->ProviderIface.pfnListEntryRead)
757 rc = pTransfer->ProviderIface.pfnListEntryRead(&pTransfer->ProviderCtx, hList, pEntry);
758
759 LogFlowFuncLeaveRC(rc);
760 return rc;
761}
762
763int SharedClipboardURITransferListWrite(PSHAREDCLIPBOARDURITRANSFER pTransfer, VBOXCLIPBOARDLISTHANDLE hList,
764 PVBOXCLIPBOARDLISTENTRY pEntry)
765{
766 int rc = VINF_SUCCESS;
767
768 if (pTransfer->ProviderIface.pfnListEntryWrite)
769 rc = pTransfer->ProviderIface.pfnListEntryWrite(&pTransfer->ProviderCtx, hList, pEntry);
770
771 LogFlowFuncLeaveRC(rc);
772 return rc;
773}
774
775bool SharedClipboardURITransferListHandleIsValid(PSHAREDCLIPBOARDURITRANSFER pTransfer, VBOXCLIPBOARDLISTHANDLE hList)
776{
777 RT_NOREF(pTransfer, hList);
778
779 return true; /** @todo Implement this. */
780}
781
782/**
783 * Prepares everything needed for a read / write transfer to begin.
784 *
785 * @returns VBox status code.
786 * @param pTransfer URI clipboard transfer to prepare.
787 */
788int SharedClipboardURITransferPrepare(PSHAREDCLIPBOARDURITRANSFER pTransfer)
789{
790 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
791
792 LogFlowFuncEnter();
793
794 int rc = VINF_SUCCESS;
795
796 AssertMsgReturn(pTransfer->State.enmStatus == SHAREDCLIPBOARDURITRANSFERSTATUS_NONE,
797 ("Transfer has wrong state (%RU32)\n", pTransfer->State.enmStatus), VERR_WRONG_ORDER);
798
799 LogFlowFunc(("pTransfer=%p, enmDir=%RU32\n", pTransfer, pTransfer->State.enmDir));
800
801 if (pTransfer->Callbacks.pfnTransferPrepare)
802 {
803 SHAREDCLIPBOARDURITRANSFERCALLBACKDATA callbackData = { pTransfer, pTransfer->Callbacks.pvUser };
804 pTransfer->Callbacks.pfnTransferPrepare(&callbackData);
805 }
806
807 if (RT_SUCCESS(rc))
808 {
809 pTransfer->State.enmStatus = SHAREDCLIPBOARDURITRANSFERSTATUS_READY;
810
811 /** @todo Add checksum support. */
812 }
813
814 LogFlowFuncLeaveRC(rc);
815 return rc;
816}
817
818/**
819 * Creates an URI provider for a given transfer.
820 *
821 * @returns VBox status code.
822 * @param pTransfer Transfer to create URI provider for.
823 * @param pCreationCtx Provider creation context to use for provider creation.
824 */
825int SharedClipboardURITransferProviderCreate(PSHAREDCLIPBOARDURITRANSFER pTransfer,
826 PSHAREDCLIPBOARDPROVIDERCREATIONCTX pCreationCtx)
827{
828 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
829 AssertPtrReturn(pCreationCtx, VERR_INVALID_POINTER);
830
831 LogFlowFuncEnter();
832
833 int rc = VINF_SUCCESS;
834
835 pTransfer->ProviderIface = pCreationCtx->Interface;
836
837 pTransfer->ProviderCtx.pTransfer = pTransfer;
838 pTransfer->ProviderCtx.pvUser = pCreationCtx->pvUser;
839
840 LogFlowFuncLeaveRC(rc);
841 return rc;
842}
843
844/**
845 * Resets an clipboard URI transfer.
846 *
847 * @param pTransfer URI clipboard transfer to reset.
848 */
849void SharedClipboardURITransferReset(PSHAREDCLIPBOARDURITRANSFER pTransfer)
850{
851 AssertPtrReturnVoid(pTransfer);
852
853 LogFlowFuncEnter();
854
855 /** @todo Anything else to do here? */
856
857 if (pTransfer->pURIList)
858 pTransfer->pURIList->Clear();
859
860 SharedClipboardURIObjCtxDestroy(&pTransfer->State.ObjCtx);
861}
862
863/**
864 * Returns the clipboard area for a clipboard URI transfer.
865 *
866 * @returns Current clipboard area, or NULL if none.
867 * @param pTransfer URI clipboard transfer to return clipboard area for.
868 */
869SharedClipboardArea *SharedClipboardURITransferGetArea(PSHAREDCLIPBOARDURITRANSFER pTransfer)
870{
871 AssertPtrReturn(pTransfer, NULL);
872
873 return pTransfer->pArea;
874}
875
876/**
877 * Returns the current object context of a clipboard URI transfer.
878 *
879 * @returns Current object context, or NULL if none.
880 * @param pTransfer URI clipboard transfer to return object context for.
881 */
882PSHAREDCLIPBOARDCLIENTURIOBJCTX SharedClipboardURITransferGetCurrentObjCtx(PSHAREDCLIPBOARDURITRANSFER pTransfer)
883{
884 /* At the moment we only have one object context per transfer at a time. */
885 return &pTransfer->State.ObjCtx;
886}
887
888/**
889 * Returns the current URI object for a clipboard URI transfer.
890 *
891 * @returns Current URI object, or NULL if none.
892 * @param pTransfer URI clipboard transfer to return current URI object for.
893 */
894const SharedClipboardURIObject *SharedClipboardURITransferGetCurrentObject(PSHAREDCLIPBOARDURITRANSFER pTransfer)
895{
896 AssertPtrReturn(pTransfer, NULL);
897
898 if (pTransfer->pURIList)
899 return pTransfer->pURIList->First();
900
901 return NULL;
902}
903
904/**
905 * Returns the URI list for a clipboard URI transfer.
906 *
907 * @returns Pointer to URI list.
908 * @param pTransfer URI clipboard transfer to return URI list for.
909 */
910SharedClipboardURIList *SharedClipboardURITransferGetList(PSHAREDCLIPBOARDURITRANSFER pTransfer)
911{
912 AssertPtrReturn(pTransfer, NULL);
913
914 return pTransfer->pURIList;
915}
916
917/**
918 * Returns the current URI object for a clipboard URI transfer.
919 *
920 * @returns Pointer to URI object.
921 * @param pTransfer URI clipboard transfer to return URI object for.
922 */
923SharedClipboardURIObject *SharedClipboardURITransferGetObject(PSHAREDCLIPBOARDURITRANSFER pTransfer, uint64_t uIdx)
924{
925 AssertPtrReturn(pTransfer, NULL);
926
927 if (!pTransfer->pURIList)
928 return NULL;
929
930 return pTransfer->pURIList->At(uIdx);
931}
932
933SHAREDCLIPBOARDSOURCE SharedClipboardURITransferGetSource(PSHAREDCLIPBOARDURITRANSFER pTransfer)
934{
935 AssertPtrReturn(pTransfer, SHAREDCLIPBOARDSOURCE_INVALID);
936
937 return pTransfer->State.enmSource;
938}
939
940/**
941 * Returns the current transfer status.
942 *
943 * @returns Current transfer status.
944 * @param pTransfer URI clipboard transfer to return status for.
945 */
946SHAREDCLIPBOARDURITRANSFERSTATUS SharedClipboardURITransferGetStatus(PSHAREDCLIPBOARDURITRANSFER pTransfer)
947{
948 AssertPtrReturn(pTransfer, SHAREDCLIPBOARDURITRANSFERSTATUS_NONE);
949
950 return pTransfer->State.enmStatus;
951}
952
953/**
954 * Runs (starts) an URI transfer thread.
955 *
956 * @returns VBox status code.
957 * @param pTransfer URI clipboard transfer to run.
958 * @param pfnThreadFunc Pointer to thread function to use.
959 * @param pvUser Pointer to user-provided data.
960 */
961int SharedClipboardURITransferRun(PSHAREDCLIPBOARDURITRANSFER pTransfer, PFNRTTHREAD pfnThreadFunc, void *pvUser)
962{
963 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
964
965 AssertMsgReturn(pTransfer->State.enmStatus == SHAREDCLIPBOARDURITRANSFERSTATUS_READY,
966 ("Wrong status (currently is %RU32)\n", pTransfer->State.enmStatus), VERR_WRONG_ORDER);
967
968 int rc = sharedClipboardURITransferThreadCreate(pTransfer, pfnThreadFunc, pvUser);
969
970 LogFlowFuncLeaveRC(rc);
971 return rc;
972}
973
974/**
975 * Sets or unsets the callback table to be used for a clipboard URI transfer.
976 *
977 * @returns VBox status code.
978 * @param pTransfer URI clipboard transfer to set callbacks for.
979 * @param pCallbacks Pointer to callback table to set.
980 */
981void SharedClipboardURITransferSetCallbacks(PSHAREDCLIPBOARDURITRANSFER pTransfer,
982 PSHAREDCLIPBOARDURITRANSFERCALLBACKS pCallbacks)
983{
984 AssertPtrReturnVoid(pTransfer);
985 AssertPtrReturnVoid(pCallbacks);
986
987 LogFlowFunc(("pCallbacks=%p\n", pCallbacks));
988
989#define SET_CALLBACK(a_pfnCallback) \
990 if (pCallbacks->a_pfnCallback) \
991 pTransfer->Callbacks.a_pfnCallback = pCallbacks->a_pfnCallback
992
993 SET_CALLBACK(pfnTransferPrepare);
994 SET_CALLBACK(pfnTransferStarted);
995 SET_CALLBACK(pfnListHeaderComplete);
996 SET_CALLBACK(pfnListEntryComplete);
997 SET_CALLBACK(pfnTransferCanceled);
998 SET_CALLBACK(pfnTransferError);
999 SET_CALLBACK(pfnTransferStarted);
1000
1001#undef SET_CALLBACK
1002
1003 pTransfer->Callbacks.pvUser = pCallbacks->pvUser;
1004}
1005
1006int SharedClipboardURITransferPayloadAlloc(uint32_t uID, const void *pvData, uint32_t cbData,
1007 PSHAREDCLIPBOARDURITRANSFERPAYLOAD *ppPayload)
1008{
1009 PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload =
1010 (PSHAREDCLIPBOARDURITRANSFERPAYLOAD)RTMemAlloc(sizeof(SHAREDCLIPBOARDURITRANSFERPAYLOAD));
1011 if (!pPayload)
1012 return VERR_NO_MEMORY;
1013
1014 pPayload->pvData = RTMemAlloc(cbData);
1015 if (pPayload->pvData)
1016 {
1017 memcpy(pPayload->pvData, pvData, cbData);
1018
1019 pPayload->cbData = cbData;
1020 pPayload->uID = uID;
1021
1022 *ppPayload = pPayload;
1023
1024 return VINF_SUCCESS;
1025 }
1026
1027 RTMemFree(pPayload);
1028 return VERR_NO_MEMORY;
1029}
1030
1031void SharedClipboardURITransferPayloadFree(PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload)
1032{
1033 if (!pPayload)
1034 return;
1035
1036 if (pPayload->pvData)
1037 {
1038 Assert(pPayload->cbData);
1039 RTMemFree(pPayload->pvData);
1040 pPayload->pvData = NULL;
1041 }
1042
1043 pPayload->cbData = 0;
1044
1045 RTMemFree(pPayload);
1046 pPayload = NULL;
1047}
1048
1049int SharedClipboardURITransferEventRegister(PSHAREDCLIPBOARDURITRANSFER pTransfer, uint32_t uID)
1050{
1051 int rc;
1052
1053 SharedClipboardURITransferEventMap::iterator itEvent = pTransfer->Events.pMap->find(uID);
1054 if (itEvent == pTransfer->Events.pMap->end())
1055 {
1056 PSHAREDCLIPBOARDURITRANSFEREVENT pEvent
1057 = (PSHAREDCLIPBOARDURITRANSFEREVENT)RTMemAllocZ(sizeof(SHAREDCLIPBOARDURITRANSFEREVENT));
1058 if (pEvent)
1059 {
1060 rc = RTSemEventCreate(&pEvent->hEventSem);
1061 if (RT_SUCCESS(rc))
1062 {
1063 pTransfer->Events.pMap->insert(std::pair<uint32_t, PSHAREDCLIPBOARDURITRANSFEREVENT>(uID, pEvent)); /** @todo Can this throw? */
1064 }
1065 }
1066 else
1067 rc = VERR_NO_MEMORY;
1068 }
1069 else
1070 rc = VERR_ALREADY_EXISTS;
1071
1072 LogFlowFuncLeaveRC(rc);
1073 return rc;
1074}
1075
1076int SharedClipboardURITransferEventUnregister(PSHAREDCLIPBOARDURITRANSFER pTransfer, uint32_t uID)
1077{
1078 int rc;
1079
1080 SharedClipboardURITransferEventMap::const_iterator itEvent = pTransfer->Events.pMap->find(uID);
1081 if (itEvent != pTransfer->Events.pMap->end())
1082 {
1083 SharedClipboardURITransferPayloadFree(itEvent->second->pPayload);
1084
1085 RTSemEventDestroy(itEvent->second->hEventSem);
1086
1087 RTMemFree(itEvent->second);
1088
1089 pTransfer->Events.pMap->erase(itEvent);
1090
1091 rc = VINF_SUCCESS;
1092 }
1093 else
1094 rc = VERR_NOT_FOUND;
1095
1096 LogFlowFuncLeaveRC(rc);
1097 return rc;
1098}
1099
1100int SharedClipboardURITransferEventWait(PSHAREDCLIPBOARDURITRANSFER pTransfer, uint32_t uID, RTMSINTERVAL uTimeoutMs,
1101 PSHAREDCLIPBOARDURITRANSFERPAYLOAD *ppPayload)
1102{
1103 LogFlowFuncEnter();
1104
1105 int rc;
1106
1107 SharedClipboardURITransferEventMap::const_iterator itEvent = pTransfer->Events.pMap->find(uID);
1108 if (itEvent != pTransfer->Events.pMap->end())
1109 {
1110 rc = RTSemEventWait(itEvent->second->hEventSem, uTimeoutMs);
1111 if (RT_SUCCESS(rc))
1112 {
1113 *ppPayload = itEvent->second->pPayload;
1114
1115 itEvent->second->pPayload = NULL;
1116 }
1117 }
1118 else
1119 rc = VERR_NOT_FOUND;
1120
1121 LogFlowFuncLeaveRC(rc);
1122 return rc;
1123}
1124
1125int SharedClipboardURITransferEventSignal(PSHAREDCLIPBOARDURITRANSFER pTransfer, uint32_t uID,
1126 PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload)
1127{
1128 int rc;
1129
1130 SharedClipboardURITransferEventMap::const_iterator itEvent = pTransfer->Events.pMap->find(uID);
1131 if (itEvent != pTransfer->Events.pMap->end())
1132 {
1133 Assert(itEvent->second->pPayload == NULL);
1134
1135 itEvent->second->pPayload = pPayload;
1136
1137 rc = RTSemEventSignal(itEvent->second->hEventSem);
1138 }
1139 else
1140 rc = VERR_NOT_FOUND;
1141
1142 LogFlowFuncLeaveRC(rc);
1143 return rc;
1144}
1145
1146/**
1147 * Creates a thread for a clipboard URI transfer.
1148 *
1149 * @returns VBox status code.
1150 * @param pTransfer URI clipboard transfer to create thread for.
1151 * @param pfnThreadFunc Thread function to use for this transfer.
1152 * @param pvUser Pointer to user-provided data.
1153 */
1154static int sharedClipboardURITransferThreadCreate(PSHAREDCLIPBOARDURITRANSFER pTransfer, PFNRTTHREAD pfnThreadFunc, void *pvUser)
1155
1156{
1157 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
1158
1159 /* Spawn a worker thread, so that we don't block the window thread for too long. */
1160 int rc = RTThreadCreate(&pTransfer->Thread.hThread, pfnThreadFunc,
1161 pvUser, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE,
1162 "shclp");
1163 if (RT_SUCCESS(rc))
1164 {
1165 int rc2 = RTThreadUserWait(pTransfer->Thread.hThread, 30 * 1000 /* Timeout in ms */);
1166 AssertRC(rc2);
1167
1168 if (pTransfer->Thread.fStarted) /* Did the thread indicate that it started correctly? */
1169 {
1170 pTransfer->State.enmStatus = SHAREDCLIPBOARDURITRANSFERSTATUS_RUNNING;
1171 }
1172 else
1173 rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
1174 }
1175
1176 LogFlowFuncLeaveRC(rc);
1177 return rc;
1178}
1179
1180/**
1181 * Destroys a thread of a clipboard URI transfer.
1182 *
1183 * @returns VBox status code.
1184 * @param pTransfer URI clipboard transfer to destroy thread for.
1185 * @param uTimeoutMs Timeout (in ms) to wait for thread creation.
1186 */
1187static int sharedClipboardURITransferThreadDestroy(PSHAREDCLIPBOARDURITRANSFER pTransfer, RTMSINTERVAL uTimeoutMs)
1188{
1189 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
1190
1191 if (pTransfer->Thread.hThread == NIL_RTTHREAD)
1192 return VINF_SUCCESS;
1193
1194 LogFlowFuncEnter();
1195
1196 /* Set stop indicator. */
1197 pTransfer->Thread.fStop = true;
1198
1199 int rcThread = VERR_WRONG_ORDER;
1200 int rc = RTThreadWait(pTransfer->Thread.hThread, uTimeoutMs, &rcThread);
1201
1202 LogFlowFunc(("Waiting for thread resulted in %Rrc (thread exited with %Rrc)\n", rc, rcThread));
1203
1204 return rc;
1205}
1206
1207/**
1208 * Initializes a clipboard URI transfer.
1209 *
1210 * @returns VBox status code.
1211 * @param pURI URI clipboard context to initialize.
1212 */
1213int SharedClipboardURICtxInit(PSHAREDCLIPBOARDURICTX pURI)
1214{
1215 AssertPtrReturn(pURI, VERR_INVALID_POINTER);
1216
1217 LogFlowFunc(("%p\n", pURI));
1218
1219 int rc = RTCritSectInit(&pURI->CritSect);
1220 if (RT_SUCCESS(rc))
1221 {
1222 RTListInit(&pURI->List);
1223
1224 pURI->cRunning = 0;
1225 pURI->cMaxRunning = 1; /* For now we only support one transfer per client at a time. */
1226
1227#ifdef DEBUG_andy
1228 pURI->cMaxRunning = UINT32_MAX;
1229#endif
1230 SharedClipboardURICtxReset(pURI);
1231 }
1232
1233 return VINF_SUCCESS;
1234}
1235
1236/**
1237 * Destroys an URI clipboard information context struct.
1238 *
1239 * @param pURI URI clipboard context to destroy.
1240 */
1241void SharedClipboardURICtxDestroy(PSHAREDCLIPBOARDURICTX pURI)
1242{
1243 AssertPtrReturnVoid(pURI);
1244
1245 LogFlowFunc(("%p\n", pURI));
1246
1247 RTCritSectDelete(&pURI->CritSect);
1248
1249 PSHAREDCLIPBOARDURITRANSFER pTransfer, pTransferNext;
1250 RTListForEachSafe(&pURI->List, pTransfer, pTransferNext, SHAREDCLIPBOARDURITRANSFER, Node)
1251 {
1252 SharedClipboardURITransferDestroy(pTransfer);
1253
1254 RTListNodeRemove(&pTransfer->Node);
1255
1256 RTMemFree(pTransfer);
1257 pTransfer = NULL;
1258 }
1259
1260 pURI->cRunning = 0;
1261 pURI->cTransfers = 0;
1262}
1263
1264/**
1265 * Resets an clipboard URI transfer.
1266 *
1267 * @param pURI URI clipboard context to reset.
1268 */
1269void SharedClipboardURICtxReset(PSHAREDCLIPBOARDURICTX pURI)
1270{
1271 AssertPtrReturnVoid(pURI);
1272
1273 LogFlowFuncEnter();
1274
1275 PSHAREDCLIPBOARDURITRANSFER pTransfer;
1276 RTListForEach(&pURI->List, pTransfer, SHAREDCLIPBOARDURITRANSFER, Node)
1277 SharedClipboardURITransferReset(pTransfer);
1278}
1279
1280/**
1281 * Adds a new URI transfer to an clipboard URI transfer.
1282 *
1283 * @returns VBox status code.
1284 * @param pURI URI clipboard context to add transfer to.
1285 * @param pTransfer Pointer to URI clipboard transfer to add.
1286 */
1287int SharedClipboardURICtxTransferAdd(PSHAREDCLIPBOARDURICTX pURI, PSHAREDCLIPBOARDURITRANSFER pTransfer)
1288{
1289 AssertPtrReturn(pURI, VERR_INVALID_POINTER);
1290 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
1291
1292 LogFlowFuncEnter();
1293
1294 if (pURI->cRunning == pURI->cMaxRunning)
1295 return VERR_SHCLPB_MAX_TRANSFERS_REACHED;
1296
1297 RTListAppend(&pURI->List, &pTransfer->Node);
1298
1299 pURI->cTransfers++;
1300 LogFlowFunc(("cTransfers=%RU32, cRunning=%RU32\n", pURI->cTransfers, pURI->cRunning));
1301
1302 return VINF_SUCCESS;
1303}
1304
1305/**
1306 * Removes an URI transfer from a clipboard URI transfer.
1307 *
1308 * @returns VBox status code.
1309 * @param pURI URI clipboard context to remove transfer from.
1310 * @param pTransfer Pointer to URI clipboard transfer to remove.
1311 */
1312int SharedClipboardURICtxTransferRemove(PSHAREDCLIPBOARDURICTX pURI, PSHAREDCLIPBOARDURITRANSFER pTransfer)
1313{
1314 AssertPtrReturn(pURI, VERR_INVALID_POINTER);
1315 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
1316
1317 LogFlowFuncEnter();
1318
1319
1320 int rc = SharedClipboardURITransferDestroy(pTransfer);
1321 if (RT_SUCCESS(rc))
1322 {
1323 RTListNodeRemove(&pTransfer->Node);
1324
1325 RTMemFree(pTransfer);
1326 pTransfer = NULL;
1327 }
1328
1329 LogFlowFuncLeaveRC(rc);
1330 return rc;
1331}
1332
1333/**
1334 * Returns a specific URI transfer, internal version.
1335 *
1336 * @returns URI transfer, or NULL if not found.
1337 * @param pURI URI clipboard context to return transfer for.
1338 * @param uIdx Index of the transfer to return.
1339 */
1340static PSHAREDCLIPBOARDURITRANSFER sharedClipboardURICtxGetTransferInternal(PSHAREDCLIPBOARDURICTX pURI, uint32_t uIdx)
1341{
1342 AssertReturn(uIdx == 0, NULL); /* Only one transfer allowed at the moment. */
1343 return RTListGetFirst(&pURI->List, SHAREDCLIPBOARDURITRANSFER, Node);
1344}
1345
1346/**
1347 * Returns a specific URI transfer.
1348 *
1349 * @returns URI transfer, or NULL if not found.
1350 * @param pURI URI clipboard context to return transfer for.
1351 * @param uIdx Index of the transfer to return.
1352 */
1353PSHAREDCLIPBOARDURITRANSFER SharedClipboardURICtxGetTransfer(PSHAREDCLIPBOARDURICTX pURI, uint32_t uIdx)
1354{
1355 return sharedClipboardURICtxGetTransferInternal(pURI, uIdx);
1356}
1357
1358/**
1359 * Returns the number of running URI transfers.
1360 *
1361 * @returns Number of running transfers.
1362 * @param pURI URI clipboard context to return number for.
1363 */
1364uint32_t SharedClipboardURICtxGetRunningTransfers(PSHAREDCLIPBOARDURICTX pURI)
1365{
1366 AssertPtrReturn(pURI, 0);
1367 return pURI->cRunning;
1368}
1369
1370/**
1371 * Returns the number of total URI transfers.
1372 *
1373 * @returns Number of total transfers.
1374 * @param pURI URI clipboard context to return number for.
1375 */
1376uint32_t SharedClipboardURICtxGetTotalTransfers(PSHAREDCLIPBOARDURICTX pURI)
1377{
1378 AssertPtrReturn(pURI, 0);
1379 return pURI->cTransfers;
1380}
1381
1382/**
1383 * Cleans up all associated transfers which are not needed (anymore).
1384 * This can be due to transfers which only have been announced but not / never being run.
1385 *
1386 * @param pURI URI clipboard context to cleanup transfers for.
1387 */
1388void SharedClipboardURICtxTransfersCleanup(PSHAREDCLIPBOARDURICTX pURI)
1389{
1390 AssertPtrReturnVoid(pURI);
1391
1392 LogFlowFunc(("cRunning=%RU32\n", pURI->cRunning));
1393
1394 /* Remove all transfers which are not in a running state (e.g. only announced). */
1395 PSHAREDCLIPBOARDURITRANSFER pTransfer, pTransferNext;
1396 RTListForEachSafe(&pURI->List, pTransfer, pTransferNext, SHAREDCLIPBOARDURITRANSFER, Node)
1397 {
1398 if (SharedClipboardURITransferGetStatus(pTransfer) != SHAREDCLIPBOARDURITRANSFERSTATUS_RUNNING)
1399 {
1400 SharedClipboardURITransferDestroy(pTransfer);
1401 RTListNodeRemove(&pTransfer->Node);
1402
1403 RTMemFree(pTransfer);
1404 pTransfer = NULL;
1405
1406 Assert(pURI->cTransfers);
1407 pURI->cTransfers--;
1408
1409 LogFlowFunc(("cTransfers=%RU32\n", pURI->cTransfers));
1410 }
1411 }
1412}
1413
1414/**
1415 * Returns whether the maximum of concurrent transfers of a specific URI context has been reached or not.
1416 *
1417 * @returns \c if maximum has been reached, \c false if not.
1418 * @param pURI URI clipboard context to determine value for.
1419 */
1420bool SharedClipboardURICtxTransfersMaximumReached(PSHAREDCLIPBOARDURICTX pURI)
1421{
1422 AssertPtrReturn(pURI, true);
1423
1424 LogFlowFunc(("cRunning=%RU32, cMaxRunning=%RU32\n", pURI->cRunning, pURI->cMaxRunning));
1425
1426 Assert(pURI->cRunning <= pURI->cMaxRunning);
1427 return pURI->cRunning == pURI->cMaxRunning;
1428}
1429
1430/**
1431 * Copies file system objinfo from IPRT to Shared Clipboard format.
1432 *
1433 * @param pDst The Shared Clipboard structure to convert data to.
1434 * @param pSrc The IPRT structure to convert data from.
1435 */
1436void SharedClipboardFsObjFromIPRT(PSHAREDCLIPBOARDFSOBJINFO pDst, PCRTFSOBJINFO pSrc)
1437{
1438 pDst->cbObject = pSrc->cbObject;
1439 pDst->cbAllocated = pSrc->cbAllocated;
1440 pDst->AccessTime = pSrc->AccessTime;
1441 pDst->ModificationTime = pSrc->ModificationTime;
1442 pDst->ChangeTime = pSrc->ChangeTime;
1443 pDst->BirthTime = pSrc->BirthTime;
1444 pDst->Attr.fMode = pSrc->Attr.fMode;
1445 /* Clear bits which we don't pass through for security reasons. */
1446 pDst->Attr.fMode &= ~(RTFS_UNIX_ISUID | RTFS_UNIX_ISGID | RTFS_UNIX_ISTXT);
1447 RT_ZERO(pDst->Attr.u);
1448 switch (pSrc->Attr.enmAdditional)
1449 {
1450 default:
1451 case RTFSOBJATTRADD_NOTHING:
1452 pDst->Attr.enmAdditional = SHAREDCLIPBOARDFSOBJATTRADD_NOTHING;
1453 break;
1454
1455 case RTFSOBJATTRADD_UNIX:
1456 pDst->Attr.enmAdditional = SHAREDCLIPBOARDFSOBJATTRADD_UNIX;
1457 pDst->Attr.u.Unix.uid = pSrc->Attr.u.Unix.uid;
1458 pDst->Attr.u.Unix.gid = pSrc->Attr.u.Unix.gid;
1459 pDst->Attr.u.Unix.cHardlinks = pSrc->Attr.u.Unix.cHardlinks;
1460 pDst->Attr.u.Unix.INodeIdDevice = pSrc->Attr.u.Unix.INodeIdDevice;
1461 pDst->Attr.u.Unix.INodeId = pSrc->Attr.u.Unix.INodeId;
1462 pDst->Attr.u.Unix.fFlags = pSrc->Attr.u.Unix.fFlags;
1463 pDst->Attr.u.Unix.GenerationId = pSrc->Attr.u.Unix.GenerationId;
1464 pDst->Attr.u.Unix.Device = pSrc->Attr.u.Unix.Device;
1465 break;
1466
1467 case RTFSOBJATTRADD_EASIZE:
1468 pDst->Attr.enmAdditional = SHAREDCLIPBOARDFSOBJATTRADD_EASIZE;
1469 pDst->Attr.u.EASize.cb = pSrc->Attr.u.EASize.cb;
1470 break;
1471 }
1472}
1473
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