VirtualBox

source: vbox/trunk/src/VBox/GuestHost/SharedClipboard/clipboard-transfers-provider-local.cpp@ 100620

Last change on this file since 100620 was 100527, checked in by vboxsync, 18 months ago

Shared Clipboard: shclTransferIfaceLocalListEntryInit() is not a callback. bugref:9437

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 24.6 KB
Line 
1/* $Id: clipboard-transfers-provider-local.cpp 100527 2023-07-11 18:08:15Z vboxsync $ */
2/** @file
3 * Shared Clipboard - Transfers interface implementation for local file systems.
4 */
5
6/*
7 * Copyright (C) 2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#define LOG_GROUP LOG_GROUP_SHARED_CLIPBOARD
33#include <VBox/GuestHost/SharedClipboard-transfers.h>
34
35#include <iprt/dir.h>
36#include <iprt/err.h>
37#include <iprt/file.h>
38#include <iprt/path.h>
39#include <iprt/string.h>
40
41
42/**
43 * Adds a file to a transfer list header.
44 *
45 * @returns VBox status code.
46 * @param pHdr List header to add file to.
47 * @param pszPath Path of file to add.
48 */
49static int shclTransferLocalListHdrAddFile(PSHCLLISTHDR pHdr, const char *pszPath)
50{
51 AssertPtrReturn(pHdr, VERR_INVALID_POINTER);
52 AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
53
54 uint64_t cbSize = 0;
55 int rc = RTFileQuerySizeByPath(pszPath, &cbSize);
56 if (RT_SUCCESS(rc))
57 {
58 pHdr->cbTotalSize += cbSize;
59 pHdr->cEntries++;
60 }
61
62 LogFlowFuncLeaveRC(rc);
63 return rc;
64}
65
66/**
67 * Builds a transfer list header, internal version.
68 *
69 * @returns VBox status code.
70 * @param pHdr Where to store the build list header.
71 * @param pcszPathAbs Absolute path to use for building the transfer list.
72 */
73static int shclTransferLocalListHdrFromDir(PSHCLLISTHDR pHdr, const char *pcszPathAbs)
74{
75 AssertPtrReturn(pcszPathAbs, VERR_INVALID_POINTER);
76
77 LogFlowFunc(("pcszPathAbs=%s\n", pcszPathAbs));
78
79 RTFSOBJINFO objInfo;
80 int rc = RTPathQueryInfo(pcszPathAbs, &objInfo, RTFSOBJATTRADD_NOTHING);
81 if (RT_SUCCESS(rc))
82 {
83 if (RTFS_IS_DIRECTORY(objInfo.Attr.fMode))
84 {
85 RTDIR hDir;
86 rc = RTDirOpen(&hDir, pcszPathAbs);
87 if (RT_SUCCESS(rc))
88 {
89 size_t cbDirEntry = 0;
90 PRTDIRENTRYEX pDirEntry = NULL;
91 do
92 {
93 /* Retrieve the next directory entry. */
94 rc = RTDirReadExA(hDir, &pDirEntry, &cbDirEntry, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
95 if (RT_FAILURE(rc))
96 {
97 if (rc == VERR_NO_MORE_FILES)
98 rc = VINF_SUCCESS;
99 break;
100 }
101
102 switch (pDirEntry->Info.Attr.fMode & RTFS_TYPE_MASK)
103 {
104 case RTFS_TYPE_DIRECTORY:
105 {
106 /* Skip "." and ".." entries. */
107 if (RTDirEntryExIsStdDotLink(pDirEntry))
108 break;
109
110 pHdr->cEntries++;
111 break;
112 }
113 case RTFS_TYPE_FILE:
114 {
115 char *pszSrc = RTPathJoinA(pcszPathAbs, pDirEntry->szName);
116 if (pszSrc)
117 {
118 rc = shclTransferLocalListHdrAddFile(pHdr, pszSrc);
119 RTStrFree(pszSrc);
120 }
121 else
122 rc = VERR_NO_MEMORY;
123 break;
124 }
125 case RTFS_TYPE_SYMLINK:
126 {
127 /** @todo Not implemented yet. */
128 }
129
130 default:
131 break;
132 }
133
134 } while (RT_SUCCESS(rc));
135
136 RTDirReadExAFree(&pDirEntry, &cbDirEntry);
137 RTDirClose(hDir);
138 }
139 }
140 else if (RTFS_IS_FILE(objInfo.Attr.fMode))
141 {
142 rc = shclTransferLocalListHdrAddFile(pHdr, pcszPathAbs);
143 }
144 else if (RTFS_IS_SYMLINK(objInfo.Attr.fMode))
145 {
146 /** @todo Not implemented yet. */
147 }
148 else
149 rc = VERR_NOT_SUPPORTED;
150 }
151
152 LogFlowFuncLeaveRC(rc);
153 return rc;
154}
155
156/**
157 * Creates a new list handle (local only).
158 *
159 * @returns New List handle on success, or NIL_SHCLLISTHANDLE on error.
160 * @param pTransfer Clipboard transfer to create new list handle for.
161 */
162DECLINLINE(SHCLLISTHANDLE) shClTransferLocalListHandleNew(PSHCLTRANSFER pTransfer)
163{
164 return pTransfer->uListHandleNext++; /** @todo Good enough for now. Improve this later. */
165}
166
167/**
168 * Queries information about a local list entry.
169 *
170 * @returns VBox status code.
171 * @param pszPathRootAbs Absolute root path to use for the entry.
172 * @param pListEntry List entry to query information for.
173 * @param pFsObjInfo Where to store the queried information on success.
174 */
175static int shClTransferLocalListEntryQueryFsInfo(const char *pszPathRootAbs, PSHCLLISTENTRY pListEntry, PSHCLFSOBJINFO pFsObjInfo)
176{
177 AssertPtrReturn(pszPathRootAbs, VERR_INVALID_POINTER);
178 AssertPtrReturn(pListEntry, VERR_INVALID_POINTER);
179
180 const char *pszSrcPathAbs = RTPathJoinA(pszPathRootAbs, pListEntry->pszName);
181 AssertPtrReturn(pszSrcPathAbs, VERR_NO_MEMORY);
182
183 RTFSOBJINFO fsObjInfo;
184 int rc = RTPathQueryInfo(pszSrcPathAbs, &fsObjInfo, RTFSOBJATTRADD_NOTHING);
185 if (RT_SUCCESS(rc))
186 rc = ShClFsObjInfoFromIPRT(pFsObjInfo, &fsObjInfo);
187
188 return rc;
189}
190
191/** @copydoc SHCLTXPROVIDERIFACE::pfnRootListRead */
192static DECLCALLBACK(int) shclTransferIfaceLocalRootListRead(PSHCLTXPROVIDERCTX pCtx)
193{
194 LogFlowFuncEnter();
195
196 int rc = VINF_SUCCESS;
197
198 PSHCLLISTENTRY pEntry;
199 RTListForEach(&pCtx->pTransfer->lstRoots.lstEntries, pEntry, SHCLLISTENTRY, Node)
200 {
201 AssertBreakStmt(pEntry->cbInfo == sizeof(SHCLFSOBJINFO), rc = VERR_WRONG_ORDER);
202 rc = shClTransferLocalListEntryQueryFsInfo(pCtx->pTransfer->pszPathRootAbs, pEntry, (PSHCLFSOBJINFO)pEntry->pvInfo);
203 if (RT_FAILURE(rc)) /* Currently this is an all-or-nothing op. */
204 break;
205 }
206
207 LogFlowFuncLeaveRC(rc);
208 return rc;
209}
210
211/** @copydoc SHCLTXPROVIDERIFACE::pfnListOpen */
212static DECLCALLBACK(int) shclTransferIfaceLocalListOpen(PSHCLTXPROVIDERCTX pCtx, PSHCLLISTOPENPARMS pOpenParms,
213 PSHCLLISTHANDLE phList)
214{
215 LogFlowFunc(("pszPath=%s\n", pOpenParms->pszPath));
216
217 int rc;
218
219 PSHCLTRANSFER const pTransfer = pCtx->pTransfer;
220 AssertPtr(pTransfer);
221
222 PSHCLLISTHANDLEINFO pInfo
223 = (PSHCLLISTHANDLEINFO)RTMemAllocZ(sizeof(SHCLLISTHANDLEINFO));
224 if (pInfo)
225 {
226 rc = ShClTransferListHandleInfoInit(pInfo);
227 if (RT_SUCCESS(rc))
228 {
229 rc = ShClTransferResolvePathAbs(pTransfer, pOpenParms->pszPath, 0 /* fFlags */, &pInfo->pszPathLocalAbs);
230 if (RT_SUCCESS(rc))
231 {
232 RTFSOBJINFO objInfo;
233 rc = RTPathQueryInfo(pInfo->pszPathLocalAbs, &objInfo, RTFSOBJATTRADD_NOTHING);
234 if (RT_SUCCESS(rc))
235 {
236 if (RTFS_IS_DIRECTORY(objInfo.Attr.fMode))
237 {
238 rc = RTDirOpen(&pInfo->u.Local.hDir, pInfo->pszPathLocalAbs);
239 if (RT_SUCCESS(rc))
240 {
241 pInfo->enmType = SHCLOBJTYPE_DIRECTORY;
242
243 LogRel2(("Shared Clipboard: Opening directory '%s'\n", pInfo->pszPathLocalAbs));
244 }
245 else
246 LogRel(("Shared Clipboard: Opening directory '%s' failed with %Rrc\n", pInfo->pszPathLocalAbs, rc));
247
248 }
249 else if (RTFS_IS_FILE(objInfo.Attr.fMode))
250 {
251 rc = RTFileOpen(&pInfo->u.Local.hFile, pInfo->pszPathLocalAbs,
252 RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE);
253 if (RT_SUCCESS(rc))
254 {
255 pInfo->enmType = SHCLOBJTYPE_FILE;
256
257 LogRel2(("Shared Clipboard: Opening file '%s'\n", pInfo->pszPathLocalAbs));
258 }
259 else
260 LogRel(("Shared Clipboard: Opening file '%s' failed with %Rrc\n", pInfo->pszPathLocalAbs, rc));
261 }
262 else
263 rc = VERR_NOT_SUPPORTED;
264
265 if (RT_SUCCESS(rc))
266 {
267 pInfo->hList = shClTransferLocalListHandleNew(pTransfer);
268
269 RTListAppend(&pTransfer->lstHandles, &pInfo->Node);
270 pTransfer->cListHandles++;
271
272 if (phList)
273 *phList = pInfo->hList;
274
275 LogFlowFunc(("pszPathLocalAbs=%s, hList=%RU64, cListHandles=%RU32\n",
276 pInfo->pszPathLocalAbs, pInfo->hList, pTransfer->cListHandles));
277 }
278 else
279 {
280 if (RTFS_IS_DIRECTORY(objInfo.Attr.fMode))
281 {
282 if (RTDirIsValid(pInfo->u.Local.hDir))
283 RTDirClose(pInfo->u.Local.hDir);
284 }
285 else if (RTFS_IS_FILE(objInfo.Attr.fMode))
286 {
287 if (RTFileIsValid(pInfo->u.Local.hFile))
288 RTFileClose(pInfo->u.Local.hFile);
289 }
290 }
291 }
292 }
293 }
294
295 if (RT_FAILURE(rc))
296 {
297 ShClTransferListHandleInfoDestroy(pInfo);
298
299 RTMemFree(pInfo);
300 pInfo = NULL;
301 }
302 }
303 else
304 rc = VERR_NO_MEMORY;
305
306 LogFlowFuncLeaveRC(rc);
307 return rc;
308}
309
310/** @copydoc SHCLTXPROVIDERIFACE::pfnListClose */
311static DECLCALLBACK(int) shclTransferIfaceLocalListClose(PSHCLTXPROVIDERCTX pCtx, SHCLLISTHANDLE hList)
312{
313 LogFlowFuncEnter();
314
315 int rc = VINF_SUCCESS;
316
317 PSHCLTRANSFER const pTransfer = pCtx->pTransfer;
318 AssertPtr(pTransfer);
319
320 PSHCLLISTHANDLEINFO pInfo = ShClTransferListGetByHandle(pTransfer, hList);
321 if (pInfo)
322 {
323 switch (pInfo->enmType)
324 {
325 case SHCLOBJTYPE_DIRECTORY:
326 {
327 if (RTDirIsValid(pInfo->u.Local.hDir))
328 {
329 RTDirClose(pInfo->u.Local.hDir);
330 pInfo->u.Local.hDir = NIL_RTDIR;
331 }
332 break;
333 }
334
335 default:
336 rc = VERR_NOT_SUPPORTED;
337 break;
338 }
339
340 RTListNodeRemove(&pInfo->Node);
341
342 Assert(pTransfer->cListHandles);
343 pTransfer->cListHandles--;
344
345 RTMemFree(pInfo);
346 }
347 else
348 rc = VERR_NOT_FOUND;
349
350 LogFlowFuncLeaveRC(rc);
351 return rc;
352}
353
354/** @copydoc SHCLTXPROVIDERIFACE::pfnListHdrRead */
355static DECLCALLBACK(int) shclTransferIfaceLocalListHdrRead(PSHCLTXPROVIDERCTX pCtx,
356 SHCLLISTHANDLE hList, PSHCLLISTHDR pListHdr)
357{
358 LogFlowFuncEnter();
359
360 PSHCLTRANSFER const pTransfer = pCtx->pTransfer;
361 AssertPtr(pTransfer);
362
363 int rc;
364
365 PSHCLLISTHANDLEINFO pInfo = ShClTransferListGetByHandle(pTransfer, hList);
366 if (pInfo)
367 {
368 rc = ShClTransferListHdrInit(pListHdr);
369 if (RT_SUCCESS(rc))
370 {
371 switch (pInfo->enmType)
372 {
373 case SHCLOBJTYPE_DIRECTORY:
374 {
375 LogFlowFunc(("DirAbs: %s\n", pInfo->pszPathLocalAbs));
376
377 rc = shclTransferLocalListHdrFromDir(pListHdr, pInfo->pszPathLocalAbs);
378 break;
379 }
380
381 case SHCLOBJTYPE_FILE:
382 {
383 LogFlowFunc(("FileAbs: %s\n", pInfo->pszPathLocalAbs));
384
385 pListHdr->cEntries = 1;
386
387 RTFSOBJINFO objInfo;
388 rc = RTFileQueryInfo(pInfo->u.Local.hFile, &objInfo, RTFSOBJATTRADD_NOTHING);
389 if (RT_SUCCESS(rc))
390 {
391 pListHdr->cbTotalSize = objInfo.cbObject;
392 }
393 break;
394 }
395
396 /* We don't support symlinks (yet). */
397
398 default:
399 rc = VERR_NOT_SUPPORTED;
400 break;
401 }
402 }
403
404 LogFlowFunc(("cTotalObj=%RU64, cbTotalSize=%RU64\n", pListHdr->cEntries, pListHdr->cbTotalSize));
405 }
406 else
407 rc = VERR_NOT_FOUND;
408
409 LogFlowFuncLeaveRC(rc);
410 return rc;
411}
412
413/**
414 * Initializes a local list entry.
415 *
416 * @returns VBox status code.
417 * @param pEntry List entry to init.
418 * @param pszName File name to use.
419 * @param pObjInfo Object information to use.
420 */
421static int shclTransferIfaceLocalListEntryInit(PSHCLLISTENTRY pEntry, const char *pszName, PRTFSOBJINFO pObjInfo)
422{
423 PSHCLFSOBJINFO pFsObjInfo = (PSHCLFSOBJINFO)RTMemAllocZ(sizeof(SHCLFSOBJINFO));
424 AssertPtrReturn(pFsObjInfo, VERR_NO_MEMORY);
425
426 int rc = ShClFsObjInfoFromIPRT(pFsObjInfo, pObjInfo);
427 if (RT_SUCCESS(rc))
428 {
429 rc = ShClTransferListEntryInitEx(pEntry, VBOX_SHCL_INFO_F_FSOBJINFO, pszName, pFsObjInfo, sizeof(SHCLFSOBJINFO));
430 /* pEntry has taken ownership of pFsObjInfo on success. */
431 }
432
433 if (RT_FAILURE(rc))
434 {
435 RTMemFree(pFsObjInfo);
436 pFsObjInfo = NULL;
437 }
438
439 if (RT_FAILURE(rc))
440 LogRel(("Shared Clipboard: Initializing list entry '%s' failed: %Rrc\n", pszName, rc));
441
442 return rc;
443}
444
445/** @copydoc SHCLTXPROVIDERIFACE::pfnListEntryRead */
446static DECLCALLBACK(int) shclTransferIfaceLocalListEntryRead(PSHCLTXPROVIDERCTX pCtx,
447 SHCLLISTHANDLE hList, PSHCLLISTENTRY pEntry)
448{
449 LogFlowFuncEnter();
450
451 int rc;
452
453 PSHCLTRANSFER const pTransfer = pCtx->pTransfer;
454 AssertPtr(pTransfer);
455
456 PSHCLLISTHANDLEINFO pInfo = ShClTransferListGetByHandle(pTransfer, hList);
457 if (pInfo)
458 {
459 switch (pInfo->enmType)
460 {
461 case SHCLOBJTYPE_DIRECTORY:
462 {
463 LogFlowFunc(("\tDirectory: %s\n", pInfo->pszPathLocalAbs));
464
465 for (;;)
466 {
467 bool fSkipEntry = false; /* Whether to skip an entry in the enumeration. */
468
469 size_t cbDirEntry = 0;
470 PRTDIRENTRYEX pDirEntry = NULL;
471 rc = RTDirReadExA(pInfo->u.Local.hDir, &pDirEntry, &cbDirEntry, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
472 if (RT_SUCCESS(rc))
473 {
474 switch (pDirEntry->Info.Attr.fMode & RTFS_TYPE_MASK)
475 {
476 case RTFS_TYPE_DIRECTORY:
477 {
478 /* Skip "." and ".." entries. */
479 if (RTDirEntryExIsStdDotLink(pDirEntry))
480 {
481 fSkipEntry = true;
482 break;
483 }
484
485 LogFlowFunc(("Directory: %s\n", pDirEntry->szName));
486 break;
487 }
488
489 case RTFS_TYPE_FILE:
490 {
491 LogFlowFunc(("File: %s\n", pDirEntry->szName));
492 break;
493 }
494
495 case RTFS_TYPE_SYMLINK:
496 {
497 rc = VERR_NOT_IMPLEMENTED; /** @todo Not implemented yet. */
498 break;
499 }
500
501 default:
502 break;
503 }
504
505 if ( RT_SUCCESS(rc)
506 && !fSkipEntry)
507 rc = shclTransferIfaceLocalListEntryInit(pEntry, pDirEntry->szName, &pDirEntry->Info);
508
509 RTDirReadExAFree(&pDirEntry, &cbDirEntry);
510 }
511
512 if ( !fSkipEntry /* Do we have a valid entry? Bail out. */
513 || RT_FAILURE(rc))
514 {
515 break;
516 }
517 }
518
519 break;
520 }
521
522 case SHCLOBJTYPE_FILE:
523 {
524 LogFlowFunc(("\tSingle file: %s\n", pInfo->pszPathLocalAbs));
525
526 RTFSOBJINFO objInfo;
527 rc = RTFileQueryInfo(pInfo->u.Local.hFile, &objInfo, RTFSOBJATTRADD_NOTHING);
528 if (RT_SUCCESS(rc))
529 rc = shclTransferIfaceLocalListEntryInit(pEntry, pInfo->pszPathLocalAbs, &objInfo);
530
531 break;
532 }
533
534 default:
535 rc = VERR_NOT_SUPPORTED;
536 break;
537 }
538 }
539 else
540 rc = VERR_NOT_FOUND;
541
542 LogFlowFuncLeaveRC(rc);
543 return rc;
544}
545
546/** @copydoc SHCLTXPROVIDERIFACE::pfnObjOpen */
547static DECLCALLBACK(int) shclTransferIfaceLocalObjOpen(PSHCLTXPROVIDERCTX pCtx,
548 PSHCLOBJOPENCREATEPARMS pCreateParms, PSHCLOBJHANDLE phObj)
549{
550 LogFlowFuncEnter();
551
552 int rc;
553
554 PSHCLTRANSFER const pTransfer = pCtx->pTransfer;
555 AssertPtr(pTransfer);
556
557 PSHCLTRANSFEROBJ pInfo = (PSHCLTRANSFEROBJ)RTMemAllocZ(sizeof(SHCLTRANSFEROBJ));
558 if (pInfo)
559 {
560 rc = ShClTransferObjInit(pInfo);
561 if (RT_SUCCESS(rc))
562 {
563 uint64_t fOpen = 0; /* Shut up GCC. */
564 rc = ShClTransferConvertFileCreateFlags(pCreateParms->fCreate, &fOpen);
565 if (RT_SUCCESS(rc))
566 {
567 rc = ShClTransferResolvePathAbs(pTransfer, pCreateParms->pszPath, 0 /* fFlags */,
568 &pInfo->pszPathLocalAbs);
569 if (RT_SUCCESS(rc))
570 {
571 rc = RTFileOpen(&pInfo->u.Local.hFile, pInfo->pszPathLocalAbs, fOpen);
572 if (RT_SUCCESS(rc))
573 LogRel2(("Shared Clipboard: Opened file '%s'\n", pInfo->pszPathLocalAbs));
574 else
575 LogRel(("Shared Clipboard: Error opening file '%s': rc=%Rrc\n", pInfo->pszPathLocalAbs, rc));
576 }
577 }
578 }
579
580 if (RT_SUCCESS(rc))
581 {
582 pInfo->hObj = pTransfer->uObjHandleNext++;
583 pInfo->enmType = SHCLOBJTYPE_FILE;
584
585 RTListAppend(&pTransfer->lstObj, &pInfo->Node);
586 pTransfer->cObjHandles++;
587
588 LogFlowFunc(("cObjHandles=%RU32\n", pTransfer->cObjHandles));
589
590 *phObj = pInfo->hObj;
591 }
592 else
593 {
594 ShClTransferObjDestroy(pInfo);
595 RTMemFree(pInfo);
596 }
597 }
598 else
599 rc = VERR_NO_MEMORY;
600
601 LogFlowFuncLeaveRC(rc);
602 return rc;
603}
604
605/** @copydoc SHCLTXPROVIDERIFACE::pfnObjClose */
606static DECLCALLBACK(int) shclTransferIfaceLocalObjClose(PSHCLTXPROVIDERCTX pCtx, SHCLOBJHANDLE hObj)
607{
608 LogFlowFuncEnter();
609
610 int rc;
611
612 PSHCLTRANSFER const pTransfer = pCtx->pTransfer;
613 AssertPtr(pTransfer);
614
615 PSHCLTRANSFEROBJ pInfo = ShClTransferObjGet(pTransfer, hObj);
616 if (pInfo)
617 {
618 switch (pInfo->enmType)
619 {
620 case SHCLOBJTYPE_DIRECTORY:
621 {
622 rc = RTDirClose(pInfo->u.Local.hDir);
623 if (RT_SUCCESS(rc))
624 {
625 pInfo->u.Local.hDir = NIL_RTDIR;
626
627 LogRel2(("Shared Clipboard: Closed directory '%s'\n", pInfo->pszPathLocalAbs));
628 }
629 else
630 LogRel(("Shared Clipboard: Closing directory '%s' failed with %Rrc\n", pInfo->pszPathLocalAbs, rc));
631 break;
632 }
633
634 case SHCLOBJTYPE_FILE:
635 {
636 rc = RTFileClose(pInfo->u.Local.hFile);
637 if (RT_SUCCESS(rc))
638 {
639 pInfo->u.Local.hFile = NIL_RTFILE;
640
641 LogRel2(("Shared Clipboard: Closed file '%s'\n", pInfo->pszPathLocalAbs));
642 }
643 else
644 LogRel(("Shared Clipboard: Closing file '%s' failed with %Rrc\n", pInfo->pszPathLocalAbs, rc));
645 break;
646 }
647
648 default:
649 rc = VERR_NOT_IMPLEMENTED;
650 break;
651 }
652
653 RTListNodeRemove(&pInfo->Node);
654
655 Assert(pTransfer->cObjHandles);
656 pTransfer->cObjHandles--;
657
658 ShClTransferObjDestroy(pInfo);
659
660 RTMemFree(pInfo);
661 pInfo = NULL;
662 }
663 else
664 rc = VERR_NOT_FOUND;
665
666 LogFlowFuncLeaveRC(rc);
667 return rc;
668}
669
670/** @copydoc SHCLTXPROVIDERIFACE::pfnObjRead */
671static DECLCALLBACK(int) shclTransferIfaceLocalObjRead(PSHCLTXPROVIDERCTX pCtx,
672 SHCLOBJHANDLE hObj, void *pvData, uint32_t cbData,
673 uint32_t fFlags, uint32_t *pcbRead)
674{
675 RT_NOREF(fFlags);
676
677 LogFlowFuncEnter();
678
679 int rc;
680
681 PSHCLTRANSFER const pTransfer = pCtx->pTransfer;
682 AssertPtr(pTransfer);
683
684 PSHCLTRANSFEROBJ pInfo = ShClTransferObjGet(pTransfer, hObj);
685 if (pInfo)
686 {
687 switch (pInfo->enmType)
688 {
689 case SHCLOBJTYPE_FILE:
690 {
691 size_t cbRead;
692 rc = RTFileRead(pInfo->u.Local.hFile, pvData, cbData, &cbRead);
693 if (RT_SUCCESS(rc))
694 {
695 if (pcbRead)
696 *pcbRead = (uint32_t)cbRead;
697 }
698 break;
699 }
700
701 default:
702 rc = VERR_NOT_SUPPORTED;
703 break;
704 }
705 }
706 else
707 rc = VERR_NOT_FOUND;
708
709 LogFlowFuncLeaveRC(rc);
710 return rc;
711}
712
713/** @copydoc SHCLTXPROVIDERIFACE::pfnObjWrite */
714static DECLCALLBACK(int) shclTransferIfaceLocalObjWrite(PSHCLTXPROVIDERCTX pCtx,
715 SHCLOBJHANDLE hObj, void *pvData, uint32_t cbData, uint32_t fFlags,
716 uint32_t *pcbWritten)
717{
718 RT_NOREF(fFlags);
719
720 LogFlowFuncEnter();
721
722 int rc;
723
724 PSHCLTRANSFER const pTransfer = pCtx->pTransfer;
725 AssertPtr(pTransfer);
726
727 PSHCLTRANSFEROBJ pInfo = ShClTransferObjGet(pTransfer, hObj);
728 if (pInfo)
729 {
730 switch (pInfo->enmType)
731 {
732 case SHCLOBJTYPE_FILE:
733 {
734 rc = RTFileWrite(pInfo->u.Local.hFile, pvData, cbData, (size_t *)pcbWritten);
735 break;
736 }
737
738 default:
739 rc = VERR_NOT_SUPPORTED;
740 break;
741 }
742 }
743 else
744 rc = VERR_NOT_FOUND;
745
746 LogFlowFuncLeaveRC(rc);
747 return rc;
748}
749
750/**
751 * Queries (assigns) the local provider to an interface.
752 *
753 * The local provider is being used for accessing files on local file systems.
754 *
755 * @returns Interface pointer assigned to the provider.
756 * @param pProvider Provider to assign interface to.
757 */
758PSHCLTXPROVIDERIFACE ShClTransferProviderLocalQueryInterface(PSHCLTXPROVIDER pProvider)
759{
760 pProvider->Interface.pfnRootListRead = shclTransferIfaceLocalRootListRead;
761 pProvider->Interface.pfnListOpen = shclTransferIfaceLocalListOpen;
762 pProvider->Interface.pfnListClose = shclTransferIfaceLocalListClose;
763 pProvider->Interface.pfnListHdrRead = shclTransferIfaceLocalListHdrRead;
764 pProvider->Interface.pfnListEntryRead = shclTransferIfaceLocalListEntryRead;
765 pProvider->Interface.pfnObjOpen = shclTransferIfaceLocalObjOpen;
766 pProvider->Interface.pfnObjClose = shclTransferIfaceLocalObjClose;
767 pProvider->Interface.pfnObjRead = shclTransferIfaceLocalObjRead;
768 pProvider->Interface.pfnObjWrite = shclTransferIfaceLocalObjWrite;
769
770 return &pProvider->Interface;
771}
772
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