Changeset 79270 in vbox for trunk/src/VBox
- Timestamp:
- Jun 21, 2019 10:28:42 AM (6 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 1 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/WINNT/VBoxTray/Makefile.kmk
r78974 r79270 66 66 $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardURIList.cpp \ 67 67 $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardURIObject.cpp \ 68 $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/clipboard-common.cpp 68 $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/clipboard-common.cpp \ 69 $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/clipboard-uri.cpp 69 70 endif 70 71 endif -
trunk/src/VBox/GuestHost/SharedClipboard/clipboard-common.cpp
r79267 r79270 27 27 #include <VBox/log.h> 28 28 #include <VBox/GuestHost/clipboard-helper.h> 29 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST30 # include <VBox/GuestHost/SharedClipboard-uri.h>31 #endif32 33 34 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST35 static int sharedClipboardURITransferThreadCreate(PSHAREDCLIPBOARDURITRANSFER pTransfer);36 static int sharedClipboardURITransferThreadDestroy(PSHAREDCLIPBOARDURITRANSFER pTransfer, RTMSINTERVAL uTimeoutMs);37 static int sharedClipboardURITransferReadThread(RTTHREAD hThread, void *pvUser);38 static int sharedClipboardURITransferWriteThread(RTTHREAD hThread, void *pvUser);39 static PSHAREDCLIPBOARDURITRANSFER sharedClipboardURICtxGetTransferInternal(PSHAREDCLIPBOARDURICTX pURI, uint32_t uIdx);40 41 static void sharedClipboardURITransferMetaDataDestroyInternal(PSHAREDCLIPBOARDURITRANSFER pTransfer);42 #endif43 29 44 30 … … 423 409 #endif /* LOG_ENABLED */ 424 410 425 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST426 int SharedClipboardURIDataHdrAlloc(PVBOXCLIPBOARDDATAHDR *ppDataHdr)427 {428 int rc;429 430 PVBOXCLIPBOARDDATAHDR pDataHdr = (PVBOXCLIPBOARDDATAHDR)RTMemAllocZ(sizeof(VBOXCLIPBOARDDATAHDR));431 if (pDataHdr)432 {433 PSHAREDCLIPBOARDMETADATAFMTDATA pMetaDataFmt434 = (PSHAREDCLIPBOARDMETADATAFMTDATA)RTMemAllocZ(sizeof(SHAREDCLIPBOARDMETADATAFMTDATA));435 if (pMetaDataFmt)436 {437 char *pszFmt = NULL;438 rc = RTStrAAppend(&pszFmt, "VBoxShClURIList");439 if (RT_SUCCESS(rc))440 {441 pMetaDataFmt->uVer = 1;442 pMetaDataFmt->pvFmt = pszFmt;443 pMetaDataFmt->cbFmt = (uint32_t)strlen(pszFmt) + 1 /* Include terminating zero */;444 445 pDataHdr->pvMetaFmt = pMetaDataFmt;446 pDataHdr->cbMetaFmt = sizeof(SHAREDCLIPBOARDMETADATAFMTDATA) + pMetaDataFmt->cbFmt;447 448 *ppDataHdr = pDataHdr;449 }450 }451 else452 rc = VERR_NO_MEMORY;453 454 if (RT_FAILURE(rc))455 {456 RTMemFree(pDataHdr);457 pDataHdr = NULL;458 }459 }460 else461 rc = VERR_NO_MEMORY;462 463 LogFlowFuncLeaveRC(rc);464 return rc;465 }466 467 /**468 * Frees a VBOXCLIPBOARDDATAHDR structure.469 *470 * @param pDataChunk VBOXCLIPBOARDDATAHDR structure to free.471 */472 void SharedClipboardURIDataHdrFree(PVBOXCLIPBOARDDATAHDR pDataHdr)473 {474 if (!pDataHdr)475 return;476 477 LogFlowFuncEnter();478 479 SharedClipboardURIDataHdrDestroy(pDataHdr);480 481 RTMemFree(pDataHdr);482 pDataHdr = NULL;483 }484 485 /**486 * Duplicates (allocates) a VBOXCLIPBOARDDATAHDR structure.487 *488 * @returns Duplicated VBOXCLIPBOARDDATAHDR structure on success.489 * @param pDataHdr VBOXCLIPBOARDDATAHDR to duplicate.490 */491 PVBOXCLIPBOARDDATAHDR SharedClipboardURIDataHdrDup(PVBOXCLIPBOARDDATAHDR pDataHdr)492 {493 AssertPtrReturn(pDataHdr, NULL);494 495 PVBOXCLIPBOARDDATAHDR pDataHdrDup = (PVBOXCLIPBOARDDATAHDR)RTMemAlloc(sizeof(VBOXCLIPBOARDDATAHDR));496 if (pDataHdrDup)497 {498 *pDataHdrDup = *pDataHdr;499 500 if (pDataHdr->pvMetaFmt)501 {502 pDataHdrDup->pvMetaFmt = RTMemDup(pDataHdr->pvMetaFmt, pDataHdr->cbMetaFmt);503 pDataHdrDup->cbMetaFmt = pDataHdr->cbMetaFmt;504 }505 506 if (pDataHdr->pvChecksum)507 {508 pDataHdrDup->pvChecksum = RTMemDup(pDataHdr->pvChecksum, pDataHdr->cbChecksum);509 pDataHdrDup->cbChecksum = pDataHdr->cbChecksum;510 }511 }512 513 return pDataHdrDup;514 }515 516 /**517 * Returns the size (in bytes) of the announced meta data.518 *519 * @returns Announced meta data size in bytes.520 * @param pDataHdr Data header struct to get announced meta data size for.521 */522 uint32_t SharedClipboardURIDataHdrGetMetaDataSize(PVBOXCLIPBOARDDATAHDR pDataHdr)523 {524 AssertPtrReturn(pDataHdr, 0);525 526 return pDataHdr->cbMeta;527 }528 529 /**530 * Initializes an URI data header struct.531 *532 * @returns VBox status code.533 * @param pDataHdr Data header struct to initialize.534 */535 int SharedClipboardURIDataHdrInit(PVBOXCLIPBOARDDATAHDR pDataHdr)536 {537 AssertPtrReturn(pDataHdr, VERR_INVALID_POINTER);538 539 SharedClipboardURIDataHdrReset(pDataHdr);540 541 return VINF_SUCCESS;542 }543 544 /**545 * Destroys an URI data header struct.546 *547 * @param pDataHdr Data header struct to destroy.548 */549 void SharedClipboardURIDataHdrDestroy(PVBOXCLIPBOARDDATAHDR pDataHdr)550 {551 if (!pDataHdr)552 return;553 554 LogFlowFuncEnter();555 556 if (pDataHdr->pvMetaFmt)557 {558 Assert(pDataHdr->cbMetaFmt);559 560 RTMemFree(pDataHdr->pvMetaFmt);561 pDataHdr->pvMetaFmt = NULL;562 pDataHdr->cbMetaFmt = 0;563 }564 565 if (pDataHdr->pvChecksum)566 {567 Assert(pDataHdr->cbChecksum);568 569 RTMemFree(pDataHdr->pvChecksum);570 pDataHdr->pvChecksum = NULL;571 pDataHdr->cbChecksum = 0;572 }573 }574 575 /**576 * Resets a VBOXCLIPBOARDDATAHDR structture.577 *578 * @returns VBox status code.579 * @param pDataHdr VBOXCLIPBOARDDATAHDR structture to reset.580 */581 void SharedClipboardURIDataHdrReset(PVBOXCLIPBOARDDATAHDR pDataHdr)582 {583 AssertPtrReturnVoid(pDataHdr);584 585 LogFlowFuncEnter();586 587 RT_BZERO(pDataHdr, sizeof(VBOXCLIPBOARDDATAHDR));588 }589 590 /**591 * Returns whether a given clipboard data header is valid or not.592 *593 * @returns \c true if valid, \c false if not.594 * @param pDataHdr Clipboard data header to validate.595 */596 bool SharedClipboardURIDataHdrIsValid(PVBOXCLIPBOARDDATAHDR pDataHdr)597 {598 RT_NOREF(pDataHdr);599 return true; /** @todo Implement this. */600 }601 602 /**603 * Creates (allocates) and initializes a VBOXCLIPBOARDDATACHUNK structure.604 *605 * @param ppDirData Where to return the created VBOXCLIPBOARDDATACHUNK structure on success.606 */607 int SharedClipboardURIDataChunkAlloc(PVBOXCLIPBOARDDATACHUNK *ppDataChunk)608 {609 PVBOXCLIPBOARDDATACHUNK pDataChunk = (PVBOXCLIPBOARDDATACHUNK)RTMemAlloc(sizeof(VBOXCLIPBOARDDATACHUNK));610 if (!pDataChunk)611 return VERR_NO_MEMORY;612 613 int rc = SharedClipboardURIDataChunkInit(pDataChunk);614 if (RT_SUCCESS(rc))615 *ppDataChunk = pDataChunk;616 617 return rc;618 }619 620 /**621 * Frees a VBOXCLIPBOARDDATACHUNK structure.622 *623 * @param pDataChunk VBOXCLIPBOARDDATACHUNK structure to free.624 */625 void SharedClipboardURIDataChunkFree(PVBOXCLIPBOARDDATACHUNK pDataChunk)626 {627 if (!pDataChunk)628 return;629 630 SharedClipboardURIDataChunkDestroy(pDataChunk);631 RTMemFree(pDataChunk);632 }633 634 /**635 * Initializes a VBOXCLIPBOARDDATACHUNK structure.636 *637 * @param pDataChunk VBOXCLIPBOARDDATACHUNK structure to initialize.638 */639 int SharedClipboardURIDataChunkInit(PVBOXCLIPBOARDDATACHUNK pDataChunk)640 {641 RT_BZERO(pDataChunk, sizeof(VBOXCLIPBOARDDATACHUNK));642 643 return VINF_SUCCESS;644 }645 646 /**647 * Initializes a VBOXCLIPBOARDDATACHUNK structure.648 *649 * @param pDataChunk VBOXCLIPBOARDDATACHUNK structure to destroy.650 */651 void SharedClipboardURIDataChunkDestroy(PVBOXCLIPBOARDDATACHUNK pDataChunk)652 {653 if (pDataChunk->pvData)654 {655 RTMemFree(pDataChunk->pvData);656 pDataChunk->pvData = NULL;657 pDataChunk->cbData = 0;658 }659 660 if (pDataChunk->pvChecksum)661 {662 RTMemFree(pDataChunk->pvChecksum);663 pDataChunk->pvChecksum = NULL;664 pDataChunk->cbChecksum = 0;665 }666 }667 668 /**669 * Returns whether a given clipboard data chunk is valid or not.670 *671 * @returns \c true if valid, \c false if not.672 * @param pDataChunk Clipboard data chunk to validate.673 */674 bool SharedClipboardURIDataChunkIsValid(PVBOXCLIPBOARDDATACHUNK pDataChunk)675 {676 RT_NOREF(pDataChunk);677 678 /** @todo Verify checksum. */679 680 return true; /** @todo Implement this. */681 }682 683 /**684 * Creates (allocates) and initializes a VBOXCLIPBOARDDIRDATA structure.685 *686 * @param ppDirData Where to return the created VBOXCLIPBOARDDIRDATA structure on success.687 */688 int SharedClipboardURIDirDataAlloc(PVBOXCLIPBOARDDIRDATA *ppDirData)689 {690 PVBOXCLIPBOARDDIRDATA pDirData = (PVBOXCLIPBOARDDIRDATA)RTMemAlloc(sizeof(VBOXCLIPBOARDDIRDATA));691 if (!pDirData)692 return VERR_NO_MEMORY;693 694 int rc = SharedClipboardURIDirDataInit(pDirData);695 if (RT_SUCCESS(rc))696 *ppDirData = pDirData;697 698 return rc;699 }700 701 /**702 * Frees a VBOXCLIPBOARDDIRDATA structure.703 *704 * @param pDirData Where to return the created VBOXCLIPBOARDDIRDATA structure on success.705 */706 void SharedClipboardURIDirDataFree(PVBOXCLIPBOARDDIRDATA pDirData)707 {708 if (!pDirData)709 return;710 711 SharedClipboardURIDirDataDestroy(pDirData);712 RTMemFree(pDirData);713 }714 715 /**716 * Initializes a VBOXCLIPBOARDDIRDATA structure.717 *718 * @param pDirData VBOXCLIPBOARDDIRDATA structure to initialize.719 */720 int SharedClipboardURIDirDataInit(PVBOXCLIPBOARDDIRDATA pDirData)721 {722 RT_BZERO(pDirData, sizeof(VBOXCLIPBOARDDIRDATA));723 724 return VINF_SUCCESS;725 }726 727 /**728 * Destroys a VBOXCLIPBOARDDIRDATA structure.729 *730 * @param pDirData VBOXCLIPBOARDDIRDATA structure to destroy.731 */732 void SharedClipboardURIDirDataDestroy(PVBOXCLIPBOARDDIRDATA pDirData)733 {734 if (!pDirData)735 return;736 737 if (pDirData->pszPath)738 {739 Assert(pDirData->cbPath);740 RTStrFree(pDirData->pszPath);741 pDirData->pszPath = NULL;742 }743 }744 745 /**746 * Duplicates (allocates) a VBOXCLIPBOARDDIRDATA structure.747 *748 * @returns Duplicated VBOXCLIPBOARDDIRDATA structure on success.749 * @param pDirData VBOXCLIPBOARDDIRDATA to duplicate.750 */751 PVBOXCLIPBOARDDIRDATA SharedClipboardURIDirDataDup(PVBOXCLIPBOARDDIRDATA pDirData)752 {753 AssertPtrReturn(pDirData, NULL);754 755 PVBOXCLIPBOARDDIRDATA pDirDataDup = (PVBOXCLIPBOARDDIRDATA)RTMemAllocZ(sizeof(VBOXCLIPBOARDDIRDATA));756 if (pDirDataDup)757 {758 *pDirDataDup = *pDirData;759 760 if (pDirData->pszPath)761 {762 pDirDataDup->pszPath = RTStrDup(pDirData->pszPath);763 if (pDirDataDup->pszPath)764 pDirDataDup->cbPath = pDirData->cbPath;765 }766 }767 768 return pDirDataDup;769 }770 771 /**772 * Returns whether given clipboard directory data is valid or not.773 *774 * @returns \c true if valid, \c false if not.775 * @param pDirData Clipboard directory data to validate.776 */777 bool SharedClipboardURIDirDataIsValid(PVBOXCLIPBOARDDIRDATA pDirData)778 {779 if ( !pDirData->cbPath780 || pDirData->cbPath > RTPATH_MAX)781 return false;782 783 if (!RTStrIsValidEncoding(pDirData->pszPath))784 return false;785 786 return true;787 }788 789 /**790 * Initializes a VBOXCLIPBOARDFILEHDR structure.791 *792 * @param pDirData VBOXCLIPBOARDFILEHDR structure to initialize.793 */794 int SharedClipboardURIFileHdrInit(PVBOXCLIPBOARDFILEHDR pFileHdr)795 {796 RT_BZERO(pFileHdr, sizeof(VBOXCLIPBOARDFILEHDR));797 798 return VINF_SUCCESS;799 }800 801 /**802 * Destroys a VBOXCLIPBOARDFILEHDR structure.803 *804 * @param pFileHdr VBOXCLIPBOARDFILEHDR structure to destroy.805 */806 void SharedClipboardURIFileHdrDestroy(PVBOXCLIPBOARDFILEHDR pFileHdr)807 {808 if (!pFileHdr)809 return;810 811 if (pFileHdr->pszFilePath)812 {813 Assert(pFileHdr->pszFilePath);814 RTStrFree(pFileHdr->pszFilePath);815 pFileHdr->pszFilePath = NULL;816 }817 }818 819 /**820 * Duplicates (allocates) a VBOXCLIPBOARDFILEHDR structure.821 *822 * @returns Duplicated VBOXCLIPBOARDFILEHDR structure on success.823 * @param pFileHdr VBOXCLIPBOARDFILEHDR to duplicate.824 */825 PVBOXCLIPBOARDFILEHDR SharedClipboardURIFileHdrDup(PVBOXCLIPBOARDFILEHDR pFileHdr)826 {827 AssertPtrReturn(pFileHdr, NULL);828 829 PVBOXCLIPBOARDFILEHDR pFileHdrDup = (PVBOXCLIPBOARDFILEHDR)RTMemAllocZ(sizeof(VBOXCLIPBOARDFILEHDR));830 if (pFileHdrDup)831 {832 *pFileHdrDup = *pFileHdr;833 834 if (pFileHdr->pszFilePath)835 {836 pFileHdrDup->pszFilePath = RTStrDup(pFileHdr->pszFilePath);837 if (pFileHdrDup->pszFilePath)838 pFileHdrDup->cbFilePath = pFileHdrDup->cbFilePath;839 }840 }841 842 return pFileHdrDup;843 }844 845 /**846 * Returns whether a given clipboard file header is valid or not.847 *848 * @returns \c true if valid, \c false if not.849 * @param pFileHdr Clipboard file header to validate.850 * @param pDataHdr Data header to use for validation.851 */852 bool SharedClipboardURIFileHdrIsValid(PVBOXCLIPBOARDFILEHDR pFileHdr, PVBOXCLIPBOARDDATAHDR pDataHdr)853 {854 if ( !pFileHdr->cbFilePath855 || pFileHdr->cbFilePath > RTPATH_MAX)856 return false;857 858 if (!RTStrIsValidEncoding(pFileHdr->pszFilePath))859 return false;860 861 if (pFileHdr->cbSize > pDataHdr->cbTotal)862 return false;863 864 return true;865 }866 867 /**868 * Destroys a VBOXCLIPBOARDFILEDATA structure.869 *870 * @param pFileData VBOXCLIPBOARDFILEDATA structure to destroy.871 */872 void SharedClipboardURIFileDataDestroy(PVBOXCLIPBOARDFILEDATA pFileData)873 {874 if (!pFileData)875 return;876 877 if (pFileData->pvData)878 {879 Assert(pFileData->cbData);880 RTMemFree(pFileData->pvData);881 pFileData->pvData = NULL;882 }883 }884 885 /**886 * Duplicates (allocates) a VBOXCLIPBOARDFILEDATA structure.887 *888 * @returns Duplicated VBOXCLIPBOARDFILEDATA structure on success.889 * @param pFileData VBOXCLIPBOARDFILEDATA to duplicate.890 */891 PVBOXCLIPBOARDFILEDATA SharedClipboardURIFileDataDup(PVBOXCLIPBOARDFILEDATA pFileData)892 {893 AssertPtrReturn(pFileData, NULL);894 895 PVBOXCLIPBOARDFILEDATA pFileDataDup = (PVBOXCLIPBOARDFILEDATA)RTMemAllocZ(sizeof(VBOXCLIPBOARDFILEDATA));896 if (pFileDataDup)897 {898 *pFileDataDup = *pFileData;899 900 if (pFileData->pvData)901 {902 pFileDataDup->pvData = RTMemDup(pFileData->pvData, pFileData->cbData);903 if (pFileDataDup->pvData)904 pFileDataDup->cbData = pFileDataDup->cbData;905 }906 907 if (pFileData->pvChecksum)908 {909 pFileDataDup->pvChecksum = RTMemDup(pFileData->pvChecksum, pFileData->cbChecksum);910 if (pFileDataDup->pvChecksum)911 pFileDataDup->cbChecksum = pFileData->cbChecksum;912 }913 }914 915 return pFileDataDup;916 }917 918 /**919 * Returns whether given clipboard file data is valid or not.920 *921 * @returns \c true if valid, \c false if not.922 * @param pFileData Clipboard file data to validate.923 * @param pDataHdr Data header to use for validation.924 */925 bool SharedClipboardURIFileDataIsValid(PVBOXCLIPBOARDFILEDATA pFileData, PVBOXCLIPBOARDDATAHDR pDataHdr)926 {927 RT_NOREF(pFileData, pDataHdr);928 return true;929 }930 931 /**932 * Initializes an URI object context.933 *934 * @returns VBox status code.935 * @param pObjCtx URI object context to initialize.936 */937 int SharedClipboardURIObjCtxInit(PSHAREDCLIPBOARDCLIENTURIOBJCTX pObjCtx)938 {939 AssertPtrReturn(pObjCtx, VERR_INVALID_POINTER);940 941 LogFlowFuncEnter();942 943 pObjCtx->pObj = NULL;944 945 return VINF_SUCCESS;946 }947 948 /**949 * Destroys an URI object context.950 *951 * @param pObjCtx URI object context to destroy.952 */953 void SharedClipboardURIObjCtxDestroy(PSHAREDCLIPBOARDCLIENTURIOBJCTX pObjCtx)954 {955 AssertPtrReturnVoid(pObjCtx);956 957 LogFlowFuncEnter();958 959 if (pObjCtx->pObj)960 {961 pObjCtx->pObj->Close();962 /* Note: Do *not* delete pObj here -- the associated URI list will do this. */963 }964 965 pObjCtx->pObj = NULL;966 }967 968 /**969 * Returns the URI object context's URI object.970 *971 * @returns Pointer to the URI object context's URI object.972 * @param pObjCtx URI object context to return the URI object for.973 */974 SharedClipboardURIObject *SharedClipboardURIObjCtxGetObj(PSHAREDCLIPBOARDCLIENTURIOBJCTX pObjCtx)975 {976 AssertPtrReturn(pObjCtx, NULL);977 return pObjCtx->pObj;978 }979 980 /**981 * Returns if an URI object context is valid or not.982 *983 * @returns \c true if valid, \c false if not.984 * @param pObjCtx URI object context to check.985 */986 bool SharedClipboardURIObjCtxIsValid(PSHAREDCLIPBOARDCLIENTURIOBJCTX pObjCtx)987 {988 return ( pObjCtx989 && pObjCtx->pObj990 && pObjCtx->pObj->IsComplete() == false991 && pObjCtx->pObj->IsOpen());992 }993 994 /**995 * Initializes an URI clipboard transfer struct.996 *997 * @returns VBox status code.998 * @param enmDir Transfer direction.999 * @param ppTransfer Where to return the created URI transfer struct.1000 * Must be destroyed by SharedClipboardURITransferDestroy().1001 */1002 int SharedClipboardURITransferCreate(SHAREDCLIPBOARDURITRANSFERDIR enmDir, PSHAREDCLIPBOARDURITRANSFER *ppTransfer)1003 {1004 AssertPtrReturn(ppTransfer, VERR_INVALID_POINTER);1005 1006 LogFlowFuncEnter();1007 1008 PSHAREDCLIPBOARDURITRANSFER pTransfer = (PSHAREDCLIPBOARDURITRANSFER)RTMemAlloc(sizeof(SHAREDCLIPBOARDURITRANSFER));1009 if (!pTransfer)1010 return VERR_NO_MEMORY;1011 1012 int rc = VINF_SUCCESS;1013 1014 pTransfer->State.enmDir = enmDir;1015 1016 pTransfer->State.pHeader = NULL;1017 pTransfer->State.pMeta = NULL;1018 pTransfer->pArea = NULL; /* Will be created later if needed. */1019 1020 pTransfer->Thread.hThread = NIL_RTTHREAD;1021 pTransfer->Thread.fCancelled = false;1022 pTransfer->Thread.fStarted = false;1023 1024 pTransfer->pvUser = NULL;1025 pTransfer->cbUser = 0;1026 1027 pTransfer->pURIList = new SharedClipboardURIList();1028 if (!pTransfer->pURIList)1029 {1030 RTMemFree(pTransfer);1031 return VERR_NO_MEMORY;1032 }1033 1034 rc = SharedClipboardURIObjCtxInit(&pTransfer->ObjCtx);1035 if (RT_SUCCESS(rc))1036 {1037 *ppTransfer = pTransfer;1038 }1039 1040 LogFlowFuncLeaveRC(rc);1041 return rc;1042 }1043 1044 /**1045 * Destroys an URI clipboard transfer context struct.1046 *1047 * @returns VBox status code.1048 * @param pURI URI clipboard transfer to destroy.1049 */1050 int SharedClipboardURITransferDestroy(PSHAREDCLIPBOARDURITRANSFER pTransfer)1051 {1052 if (!pTransfer)1053 return VINF_SUCCESS;1054 1055 LogFlowFuncEnter();1056 1057 int rc = sharedClipboardURITransferThreadDestroy(pTransfer, 30 * 1000 /* Timeout in ms */);1058 if (RT_FAILURE(rc))1059 return rc;1060 1061 SharedClipboardURIDataHdrDestroy(pTransfer->State.pHeader);1062 SharedClipboardMetaDataDestroy(pTransfer->State.pMeta);1063 1064 if (pTransfer->pURIList)1065 {1066 delete pTransfer->pURIList;1067 pTransfer->pURIList = NULL;1068 }1069 1070 if (pTransfer->pProvider)1071 {1072 delete pTransfer->pProvider;1073 pTransfer->pProvider = NULL;1074 }1075 1076 SharedClipboardURIObjCtxDestroy(&pTransfer->ObjCtx);1077 1078 RTMemFree(pTransfer);1079 pTransfer = NULL;1080 1081 LogFlowFuncLeave();1082 1083 return VINF_SUCCESS;1084 }1085 1086 /**1087 * Prepares everything needed for a read / write transfer to begin.1088 *1089 * @returns VBox status code.1090 * @param pTransfer URI clipboard transfer to prepare.1091 */1092 int SharedClipboardURITransferPrepare(PSHAREDCLIPBOARDURITRANSFER pTransfer)1093 {1094 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);1095 1096 LogFlowFuncEnter();1097 1098 AssertPtrReturn(pTransfer->State.pMeta, VERR_WRONG_ORDER);1099 AssertPtrReturn(pTransfer->pURIList, VERR_WRONG_ORDER);1100 1101 PSHAREDCLIPBOARDMETADATA pMeta = pTransfer->State.pMeta;1102 AssertPtrReturn(pMeta, VERR_WRONG_ORDER);1103 1104 int rc;1105 1106 LogFlowFunc(("enmDir=%RU32\n", pTransfer->State.enmDir));1107 1108 if (pTransfer->State.enmDir == SHAREDCLIPBOARDURITRANSFERDIR_READ)1109 {1110 rc = pTransfer->pURIList->SetFromURIData(SharedClipboardMetaDataRaw(pMeta),1111 SharedClipboardMetaDataGetUsed(pMeta),1112 SHAREDCLIPBOARDURILIST_FLAGS_NONE);1113 /** @todo Verify pvMetaFmt. */1114 1115 sharedClipboardURITransferMetaDataDestroyInternal(pTransfer);1116 }1117 else if (pTransfer->State.enmDir == SHAREDCLIPBOARDURITRANSFERDIR_WRITE)1118 {1119 rc = pTransfer->pURIList->AppendURIPathsFromList((char *)SharedClipboardMetaDataRaw(pMeta),1120 SharedClipboardMetaDataGetUsed(pMeta),1121 SHAREDCLIPBOARDURILIST_FLAGS_KEEP_OPEN);1122 if (RT_SUCCESS(rc))1123 {1124 PVBOXCLIPBOARDDATAHDR pHeader;1125 rc = SharedClipboardURIDataHdrAlloc(&pHeader);1126 if (RT_SUCCESS(rc))1127 {1128 /* The total size also contains the size of the meta data. */1129 uint64_t cbTotal = pMeta->cbUsed;1130 cbTotal += pTransfer->pURIList->GetTotalBytes();1131 1132 pHeader->cbTotal = cbTotal;1133 pHeader->cbMeta = (uint32_t)SharedClipboardMetaDataGetUsed(pMeta);1134 pHeader->cObjects = pTransfer->pURIList->GetTotalCount();1135 1136 SharedClipboardURIDataHdrDestroy(pTransfer->State.pHeader);1137 1138 if (RT_SUCCESS(rc))1139 {1140 LogFlowFunc(("Writing cbTotal=%RU64, cbMeta=%RU32, cObj=%RU64\n",1141 pHeader->cbTotal, pHeader->cbMeta, pHeader->cObjects));1142 1143 pTransfer->State.pHeader = pHeader;1144 }1145 else1146 SharedClipboardURIDataHdrFree(pHeader);1147 }1148 }1149 }1150 else1151 {1152 rc = VERR_NOT_IMPLEMENTED;1153 AssertFailed();1154 }1155 1156 if (RT_SUCCESS(rc))1157 {1158 /** @todo Add checksum support. */1159 }1160 1161 LogFlowFuncLeaveRC(rc);1162 return rc;1163 }1164 1165 /**1166 * Creates an URI provider for a given transfer.1167 *1168 * @returns VBox status code.1169 * @param pTransfer Transfer to create URI provider for.1170 * @param pProviderCtx Provider creation context to use for provider creation.1171 */1172 int SharedClipboardURITransferProviderCreate(PSHAREDCLIPBOARDURITRANSFER pTransfer,1173 PSHAREDCLIPBOARDPROVIDERCREATIONCTX pProviderCtx)1174 {1175 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);1176 AssertPtrReturn(pProviderCtx, VERR_INVALID_POINTER);1177 1178 LogFlowFuncEnter();1179 1180 int rc;1181 1182 pTransfer->pProvider = SharedClipboardProvider::Create(pProviderCtx);1183 if (pTransfer->pProvider)1184 {1185 rc = VINF_SUCCESS;1186 }1187 else1188 rc = VERR_NO_MEMORY;1189 1190 LogFlowFuncLeaveRC(rc);1191 return rc;1192 }1193 1194 /**1195 * Resets an clipboard URI transfer.1196 *1197 * @param pTransfer URI clipboard transfer to reset.1198 */1199 void SharedClipboardURITransferReset(PSHAREDCLIPBOARDURITRANSFER pTransfer)1200 {1201 AssertPtrReturnVoid(pTransfer);1202 1203 LogFlowFuncEnter();1204 1205 /** @todo Anything else to do here? */1206 1207 if (pTransfer->pProvider)1208 pTransfer->pProvider->Reset();1209 1210 if (pTransfer->pURIList)1211 pTransfer->pURIList->Clear();1212 1213 SharedClipboardURIObjCtxDestroy(&pTransfer->ObjCtx);1214 }1215 1216 /**1217 * Returns the clipboard area for a clipboard URI transfer.1218 *1219 * @returns Current clipboard area, or NULL if none.1220 * @param pTransfer URI clipboard transfer to return clipboard area for.1221 */1222 SharedClipboardArea *SharedClipboardURITransferGetArea(PSHAREDCLIPBOARDURITRANSFER pTransfer)1223 {1224 AssertPtrReturn(pTransfer, NULL);1225 1226 return pTransfer->pArea;1227 }1228 1229 /**1230 * Returns the current object context of a clipboard URI transfer.1231 *1232 * @returns Current object context, or NULL if none.1233 * @param pTransfer URI clipboard transfer to return object context for.1234 */1235 PSHAREDCLIPBOARDCLIENTURIOBJCTX SharedClipboardURITransferGetCurrentObjCtx(PSHAREDCLIPBOARDURITRANSFER pTransfer)1236 {1237 /* At the moment we only have one object context per transfer at a time. */1238 return &pTransfer->ObjCtx;1239 }1240 1241 /**1242 * Returns the current URI object for a clipboard URI transfer.1243 *1244 * @returns Current URI object, or NULL if none.1245 * @param pTransfer URI clipboard transfer to return current URI object for.1246 */1247 const SharedClipboardURIObject *SharedClipboardURITransferGetCurrentObject(PSHAREDCLIPBOARDURITRANSFER pTransfer)1248 {1249 AssertPtrReturn(pTransfer, NULL);1250 1251 if (pTransfer->pURIList)1252 return pTransfer->pURIList->First();1253 1254 return NULL;1255 }1256 1257 /**1258 * Returns the provider for a clipboard URI transfer.1259 *1260 * @returns Current provider, or NULL if none.1261 * @param pTransfer URI clipboard transfer to return provider for.1262 */1263 SharedClipboardProvider *SharedClipboardURITransferGetProvider(PSHAREDCLIPBOARDURITRANSFER pTransfer)1264 {1265 AssertPtrReturn(pTransfer, NULL);1266 1267 return pTransfer->pProvider;1268 }1269 1270 /**1271 * Returns the URI list for a clipboard URI transfer.1272 *1273 * @returns Pointer to URI list.1274 * @param pTransfer URI clipboard transfer to return URI list for.1275 */1276 SharedClipboardURIList *SharedClipboardURITransferGetList(PSHAREDCLIPBOARDURITRANSFER pTransfer)1277 {1278 AssertPtrReturn(pTransfer, NULL);1279 1280 return pTransfer->pURIList;1281 }1282 1283 /**1284 * Returns the current URI object for a clipboard URI transfer.1285 *1286 * @returns Pointer to URI object.1287 * @param pTransfer URI clipboard transfer to return URI object for.1288 */1289 SharedClipboardURIObject *SharedClipboardURITransferGetObject(PSHAREDCLIPBOARDURITRANSFER pTransfer, uint64_t uIdx)1290 {1291 AssertPtrReturn(pTransfer, NULL);1292 1293 if (!pTransfer->pURIList)1294 return NULL;1295 1296 return pTransfer->pURIList->At(uIdx);1297 }1298 1299 /**1300 * Runs (starts) an URI transfer, either in synchronous or asynchronous (threaded) mode.1301 *1302 * @returns VBox status code.1303 * @param pTransfer URI clipboard transfer to run.1304 * @param fAsync Whether to run the transfer synchronously or asynchronously.1305 */1306 int SharedClipboardURITransferRun(PSHAREDCLIPBOARDURITRANSFER pTransfer, bool fAsync)1307 {1308 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);1309 1310 int rc;1311 1312 LogFlowFunc(("fAsync=%RTbool\n", fAsync));1313 1314 if (fAsync)1315 {1316 rc = sharedClipboardURITransferThreadCreate(pTransfer);1317 }1318 else1319 {1320 if (pTransfer->State.enmDir == SHAREDCLIPBOARDURITRANSFERDIR_READ)1321 rc = SharedClipboardURITransferRead(pTransfer);1322 else if (pTransfer->State.enmDir == SHAREDCLIPBOARDURITRANSFERDIR_WRITE)1323 rc = SharedClipboardURITransferWrite(pTransfer);1324 else1325 rc = VERR_NOT_IMPLEMENTED;1326 }1327 1328 LogFlowFuncLeaveRC(rc);1329 return rc;1330 }1331 1332 /**1333 * Sets or unsets the callback table to be used for a clipboard URI transfer.1334 *1335 * @returns VBox status code.1336 * @param pTransfer URI clipboard transfer to set callbacks for.1337 * @param pCallbacks Pointer to callback table to set. Specify NULL to unset existing callbacks.1338 */1339 void SharedClipboardURITransferSetCallbacks(PSHAREDCLIPBOARDURITRANSFER pTransfer, PSHAREDCLIPBOARDURITRANSFERCALLBACKS pCallbacks)1340 {1341 AssertPtrReturnVoid(pTransfer);1342 /* pCallbacks might be NULL to unset callbacks. */1343 1344 LogFlowFunc(("pCallbacks=%p\n", pCallbacks));1345 1346 if (pCallbacks)1347 {1348 pTransfer->Callbacks = *pCallbacks;1349 }1350 else1351 RT_ZERO(pTransfer->Callbacks);1352 }1353 1354 /**1355 * Creates a thread for a clipboard URI transfer.1356 *1357 * @returns VBox status code.1358 * @param pTransfer URI clipboard transfer to create thread for.1359 */1360 static int sharedClipboardURITransferThreadCreate(PSHAREDCLIPBOARDURITRANSFER pTransfer)1361 {1362 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);1363 1364 PFNRTTHREAD pfnRTThread = NULL;1365 1366 if (pTransfer->State.enmDir == SHAREDCLIPBOARDURITRANSFERDIR_READ)1367 pfnRTThread = sharedClipboardURITransferReadThread;1368 else if (pTransfer->State.enmDir == SHAREDCLIPBOARDURITRANSFERDIR_WRITE)1369 pfnRTThread = sharedClipboardURITransferWriteThread;1370 1371 AssertPtrReturn(pfnRTThread, VERR_NOT_SUPPORTED);1372 1373 /* Spawn a worker thread, so that we don't block the window thread for too long. */1374 int rc = RTThreadCreate(&pTransfer->Thread.hThread, pfnRTThread,1375 pTransfer /* pvUser */, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE,1376 "shclp");1377 if (RT_SUCCESS(rc))1378 {1379 int rc2 = RTThreadUserWait(pTransfer->Thread.hThread, 30 * 1000 /* Timeout in ms */);1380 AssertRC(rc2);1381 1382 if (!pTransfer->Thread.fStarted) /* Did the thread fail to start? */1383 rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */1384 }1385 1386 LogFlowFuncLeaveRC(rc);1387 return rc;1388 }1389 1390 /**1391 * Destroys a thread of a clipboard URI transfer.1392 *1393 * @returns VBox status code.1394 * @param pTransfer URI clipboard transfer to destroy thread for.1395 * @param uTimeoutMs Timeout (in ms) to wait for thread creation.1396 */1397 static int sharedClipboardURITransferThreadDestroy(PSHAREDCLIPBOARDURITRANSFER pTransfer, RTMSINTERVAL uTimeoutMs)1398 {1399 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);1400 1401 if (pTransfer->Thread.hThread == NIL_RTTHREAD)1402 return VINF_SUCCESS;1403 1404 int rcThread = VERR_WRONG_ORDER;1405 int rc = RTThreadWait(pTransfer->Thread.hThread, uTimeoutMs, &rcThread);1406 1407 LogFlowFunc(("Waiting for thread resulted in %Rrc (thread exited with %Rrc)\n", rc, rcThread));1408 1409 return rc;1410 }1411 1412 /**1413 * Reads all URI objects using the connected provider.1414 *1415 * @returns VBox status code.1416 * @param pTransfer Transfer to read objects for.1417 */1418 int SharedClipboardURITransferRead(PSHAREDCLIPBOARDURITRANSFER pTransfer)1419 {1420 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);1421 1422 LogFlowFuncEnter();1423 1424 int rc = SharedClipboardURITransferMetaDataRead(pTransfer, NULL /* pcbRead */);1425 if (RT_SUCCESS(rc))1426 {1427 rc = SharedClipboardURITransferReadObjects(pTransfer);1428 if (RT_SUCCESS(rc))1429 {1430 if (pTransfer->Callbacks.pfnTransferComplete)1431 {1432 SHAREDCLIPBOARDURITRANSFERCALLBACKDATA callbackData = { pTransfer, pTransfer->Callbacks.pvUser };1433 pTransfer->Callbacks.pfnTransferComplete(&callbackData, rc);1434 }1435 }1436 }1437 1438 if (RT_FAILURE(rc))1439 {1440 if (pTransfer->Callbacks.pfnTransferError)1441 {1442 SHAREDCLIPBOARDURITRANSFERCALLBACKDATA callbackData = { pTransfer, pTransfer->Callbacks.pvUser };1443 pTransfer->Callbacks.pfnTransferError(&callbackData, rc);1444 }1445 }1446 1447 LogFlowFuncLeaveRC(rc);1448 return rc;1449 }1450 1451 /**1452 * Reads all URI objects using the connected provider.1453 *1454 * @returns VBox status code.1455 * @param pTransfer Transfer to read objects for.1456 */1457 int SharedClipboardURITransferReadObjects(PSHAREDCLIPBOARDURITRANSFER pTransfer)1458 {1459 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);1460 1461 LogFlowFuncEnter();1462 1463 int rc = VERR_NOT_IMPLEMENTED;1464 1465 LogFlowFuncLeaveRC(rc);1466 return rc;1467 }1468 1469 /**1470 * Thread for transferring (reading) URI objects from source to the target.1471 * For target to source transfers we utilize our own IDataObject / IStream implementations.1472 *1473 * @returns VBox status code.1474 * @param hThread Thread handle.1475 * @param pvUser User arguments; is PSHAREDCLIPBOARDURITRANSFER.1476 */1477 static int sharedClipboardURITransferReadThread(RTTHREAD hThread, void *pvUser)1478 {1479 AssertPtrReturn(pvUser, VERR_INVALID_POINTER);1480 1481 LogFlowFuncEnter();1482 1483 /* At the moment we only support one transfer at a time. */1484 PSHAREDCLIPBOARDURITRANSFER pTransfer = (PSHAREDCLIPBOARDURITRANSFER)pvUser;1485 AssertPtr(pTransfer->pProvider);1486 1487 int rc = VINF_SUCCESS;1488 1489 if (RT_SUCCESS(rc))1490 pTransfer->Thread.fStarted = true;1491 1492 int rc2 = RTThreadUserSignal(hThread);1493 const bool fSignalled = RT_SUCCESS(rc2);1494 1495 if (RT_SUCCESS(rc))1496 rc = SharedClipboardURITransferRead(pTransfer);1497 1498 if (!fSignalled)1499 {1500 rc2 = RTThreadUserSignal(hThread);1501 AssertRC(rc2);1502 }1503 1504 LogFlowFuncLeaveRC(rc);1505 return rc;1506 }1507 1508 /**1509 * Creates the internal meta data buffer of an URI clipboard transfer.1510 *1511 * @returns VBox status code.1512 * @param pTransfer URI clipboard transfer to create internal meta data for.1513 * @param cbSize Size (in bytes) of meta data buffer to create. An existing meta data buffer1514 * will be resized accordingly.1515 */1516 static int sharedClipboardURITransferMetaDataCreateInternal(PSHAREDCLIPBOARDURITRANSFER pTransfer, uint32_t cbSize)1517 {1518 int rc;1519 1520 LogFlowFuncEnter();1521 1522 if (pTransfer->State.pMeta == NULL)1523 {1524 pTransfer->State.pMeta = (PSHAREDCLIPBOARDMETADATA)RTMemAlloc(sizeof(SHAREDCLIPBOARDMETADATA));1525 if (pTransfer->State.pMeta)1526 {1527 /** @todo Make meta data format handling more flexible. */1528 rc = SharedClipboardMetaDataInit(pTransfer->State.pMeta, SHAREDCLIPBOARDMETADATAFMT_URI_LIST);1529 }1530 else1531 rc = VERR_NO_MEMORY;1532 }1533 else1534 rc = SharedClipboardMetaDataResize(pTransfer->State.pMeta, cbSize);1535 1536 LogFlowFuncLeaveRC(rc);1537 return rc;1538 }1539 1540 /**1541 * Destroys a clipboard URI transfer's internal meta data.1542 *1543 * @param pTransfer URI clipboard transfer to destroy internal meta data of.1544 */1545 static void sharedClipboardURITransferMetaDataDestroyInternal(PSHAREDCLIPBOARDURITRANSFER pTransfer)1546 {1547 if (!pTransfer->State.pMeta)1548 return;1549 1550 LogFlowFuncEnter();1551 1552 /* We're done processing the meta data, so just destroy it. */1553 SharedClipboardMetaDataDestroy(pTransfer->State.pMeta);1554 1555 RTMemFree(pTransfer->State.pMeta);1556 pTransfer->State.pMeta = NULL;1557 }1558 1559 /**1560 * Adds meta data for a clipboard URI transfer, internal version.1561 *1562 * @returns VBox status code.1563 * @param pTransfer URI clipboard transfer to set meta data for.1564 * @param pvMeta Pointer to meta data buffer.1565 * @param cbMeta Size (in bytes) of meta data buffer.1566 */1567 static int sharedClipboardURITransferMetaDataAddInternal(PSHAREDCLIPBOARDURITRANSFER pTransfer,1568 const void *pvMeta, uint32_t cbMeta)1569 {1570 LogFlowFunc(("pvMeta=%p, cbMeta=%RU32\n", pvMeta, cbMeta));1571 1572 int rc = SharedClipboardMetaDataAdd(pTransfer->State.pMeta, pvMeta, cbMeta);1573 1574 LogFlowFuncLeaveRC(rc);1575 return rc;1576 }1577 1578 /**1579 * Adds meta data for a clipboard URI transfer.1580 *1581 * @returns VBox status code.1582 * @param pTransfer URI clipboard transfer to set meta data for.1583 * @param pvMeta Pointer to meta data buffer.1584 * @param cbMeta Size (in bytes) of meta data buffer.1585 */1586 int SharedClipboardURITransferMetaDataAdd(PSHAREDCLIPBOARDURITRANSFER pTransfer, const void *pvMeta, uint32_t cbMeta)1587 {1588 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);1589 1590 LogFlowFuncEnter();1591 1592 int rc = sharedClipboardURITransferMetaDataCreateInternal(pTransfer, cbMeta);1593 if (RT_SUCCESS(rc))1594 rc = sharedClipboardURITransferMetaDataAddInternal(pTransfer, pvMeta, cbMeta);1595 1596 LogFlowFuncLeaveRC(rc);1597 return rc;1598 }1599 1600 /**1601 * Returns whether the meta data is in a complete state (e.g. completetely read / written) or not.1602 *1603 * @returns \c true if meta data is complete, \c false if not.1604 * @param pTransfer URI clipboard transfer to get completion status of meta data for.1605 */1606 bool SharedClipboardURITransferMetaDataIsComplete(PSHAREDCLIPBOARDURITRANSFER pTransfer)1607 {1608 AssertPtrReturn(pTransfer->State.pHeader, false);1609 AssertPtrReturn(pTransfer->State.pMeta, false);1610 1611 return SharedClipboardMetaDataGetUsed(pTransfer->State.pMeta) == pTransfer->State.pHeader->cbMeta;1612 }1613 1614 /**1615 * Reads meta for a clipboard URI transfer.1616 *1617 * @returns VBox status code.1618 * @param pTransfer URI clipboard transfer to read meta data for.1619 * @param pcbRead How much meta data (in bytes) was read on success.1620 */1621 int SharedClipboardURITransferMetaDataRead(PSHAREDCLIPBOARDURITRANSFER pTransfer, uint32_t *pcbRead)1622 {1623 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);1624 1625 LogFlowFuncEnter();1626 1627 /* Destroy any former meta data. */1628 SharedClipboardMetaDataDestroy(pTransfer->State.pMeta);1629 1630 uint32_t cbReadTotal = 0;1631 1632 int rc = pTransfer->pProvider->ReadDataHdr(&pTransfer->State.pHeader);1633 if (RT_SUCCESS(rc))1634 {1635 uint32_t cbMeta = _4K; /** @todo Improve. */1636 void *pvMeta = RTMemAlloc(cbMeta);1637 1638 if (pvMeta)1639 {1640 uint32_t cbMetaToRead = pTransfer->State.pHeader->cbMeta;1641 while (cbMetaToRead)1642 {1643 uint32_t cbMetaRead;1644 rc = pTransfer->pProvider->ReadDataChunk(pTransfer->State.pHeader, pvMeta, cbMeta, 0 /* fFlags */, &cbMetaRead);1645 if (RT_SUCCESS(rc))1646 rc = sharedClipboardURITransferMetaDataAddInternal(pTransfer, pvMeta, cbMeta);1647 1648 if (RT_FAILURE(rc))1649 break;1650 1651 Assert(cbMetaToRead >= cbMetaRead);1652 cbMetaToRead -= cbMetaRead;1653 1654 cbReadTotal += cbReadTotal;1655 }1656 1657 RTMemFree(pvMeta);1658 1659 if (RT_SUCCESS(rc))1660 {1661 if (pcbRead)1662 *pcbRead = cbReadTotal;1663 }1664 }1665 else1666 rc = VERR_NO_MEMORY;1667 }1668 1669 LogFlowFuncLeaveRC(rc);1670 return rc;1671 }1672 1673 /**1674 * Writes the actual meta data.1675 *1676 * @returns IPRT status code.1677 * @param pTransfer Transfer to write meta data for.1678 * @param pcbWritten How much bytes were written on success. Optional.1679 */1680 int SharedClipboardURITransferMetaDataWrite(PSHAREDCLIPBOARDURITRANSFER pTransfer, uint32_t *pcbWritten)1681 {1682 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);1683 1684 AssertPtr(pTransfer->pProvider);1685 1686 LogFlowFuncEnter();1687 1688 AssertPtrReturn(pTransfer->State.pHeader, VERR_WRONG_ORDER);1689 AssertPtrReturn(pTransfer->State.pMeta, VERR_WRONG_ORDER);1690 1691 uint32_t cbWrittenTotal = 0;1692 1693 int rc = pTransfer->pProvider->WriteDataHdr(pTransfer->State.pHeader);1694 if (RT_SUCCESS(rc))1695 {1696 /* Sanity. */1697 Assert(pTransfer->State.pHeader->cbMeta == pTransfer->State.pMeta->cbUsed);1698 1699 uint32_t cbMetaToWrite = pTransfer->State.pHeader->cbMeta;1700 while (cbMetaToWrite)1701 {1702 uint32_t cbMetaWritten;1703 rc = pTransfer->pProvider->WriteDataChunk(pTransfer->State.pHeader, (uint8_t *)pTransfer->State.pMeta->pvMeta + cbWrittenTotal,1704 cbMetaToWrite, 0 /* fFlags */, &cbMetaWritten);1705 if (RT_FAILURE(rc))1706 break;1707 1708 Assert(cbMetaToWrite >= cbMetaWritten);1709 cbMetaToWrite -= cbMetaWritten;1710 1711 cbWrittenTotal += cbMetaWritten;1712 Assert(cbWrittenTotal <= pTransfer->State.pHeader->cbMeta);1713 }1714 1715 if (RT_SUCCESS(rc))1716 {1717 if (pcbWritten)1718 *pcbWritten = cbWrittenTotal;1719 }1720 }1721 1722 LogFlowFuncLeaveRC(rc);1723 return rc;1724 }1725 1726 /**1727 * Writes all URI objects using the connected provider.1728 *1729 * @returns VBox status code.1730 * @param pTransfer Transfer to write objects for.1731 */1732 int SharedClipboardURITransferWriteObjects(PSHAREDCLIPBOARDURITRANSFER pTransfer)1733 {1734 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);1735 1736 LogFlowFuncEnter();1737 1738 int rc = VINF_SUCCESS;1739 1740 AssertPtrReturn(pTransfer->pURIList, VERR_WRONG_ORDER);1741 AssertPtrReturn(pTransfer->pProvider, VERR_WRONG_ORDER);1742 1743 while (!pTransfer->pURIList->IsEmpty())1744 {1745 SharedClipboardURIObject *pObj = pTransfer->pURIList->First();1746 AssertPtrBreakStmt(pObj, rc = VERR_INVALID_POINTER);1747 1748 switch (pObj->GetType())1749 {1750 case SharedClipboardURIObject::Type_Directory:1751 {1752 RTCString strPath = pObj->GetDestPathAbs();1753 LogFlowFunc(("strDir=%s (%zu), fMode=0x%x\n",1754 strPath.c_str(), strPath.length(), pObj->GetMode()));1755 1756 VBOXCLIPBOARDDIRDATA dirData;1757 SharedClipboardURIDirDataInit(&dirData);1758 1759 dirData.pszPath = RTStrDup(strPath.c_str());1760 dirData.cbPath = (uint32_t)strlen(dirData.pszPath) + 1 /* Include termination */;1761 1762 rc = pTransfer->pProvider->WriteDirectory(&dirData);1763 1764 SharedClipboardURIDirDataDestroy(&dirData);1765 break;1766 }1767 1768 case SharedClipboardURIObject::Type_File:1769 {1770 AssertBreakStmt(pObj->IsOpen(), rc = VERR_INVALID_STATE);1771 1772 RTCString strPath = pObj->GetDestPathAbs();1773 1774 LogFlowFunc(("strFile=%s (%zu), cbSize=%RU64, fMode=0x%x\n", strPath.c_str(), strPath.length(),1775 pObj->GetSize(), pObj->GetMode()));1776 1777 VBOXCLIPBOARDFILEHDR fileHdr;1778 SharedClipboardURIFileHdrInit(&fileHdr);1779 1780 fileHdr.pszFilePath = RTStrDup(strPath.c_str());1781 fileHdr.cbFilePath = (uint32_t)strlen(fileHdr.pszFilePath) + 1 /* Include termination */;1782 fileHdr.cbSize = pObj->GetSize();1783 fileHdr.fFlags = 0;1784 fileHdr.fMode = pObj->GetMode();1785 1786 rc = pTransfer->pProvider->WriteFileHdr(&fileHdr);1787 SharedClipboardURIFileHdrDestroy(&fileHdr);1788 1789 if (RT_FAILURE(rc))1790 break;1791 1792 uint32_t cbData = _64K; /** @todo Improve. */1793 void *pvData = RTMemAlloc(cbData);1794 1795 AssertPtrBreakStmt(pvData, rc = VERR_NO_MEMORY);1796 1797 while (!pObj->IsComplete())1798 {1799 uint32_t cbRead;1800 rc = pObj->Read(pvData, cbData, &cbRead);1801 if (RT_SUCCESS(rc))1802 {1803 rc = pTransfer->pProvider->WriteFileData(pvData, cbRead);1804 }1805 1806 if (RT_FAILURE(rc))1807 break;1808 }1809 1810 RTMemFree(pvData);1811 pvData = NULL;1812 break;1813 }1814 1815 default:1816 AssertFailed();1817 break;1818 }1819 1820 if (RT_FAILURE(rc))1821 break;1822 1823 /* Only remove current object on success. */1824 pTransfer->pURIList->RemoveFirst();1825 }1826 1827 LogFlowFuncLeaveRC(rc);1828 return rc;1829 }1830 1831 /**1832 * Thread for transferring (writing) URI objects from source to the target.1833 * For target to source transfers we utilize our own IDataObject / IStream implementations.1834 *1835 * @returns VBox status code.1836 * @param hThread Thread handle.1837 * @param pvUser User arguments; is PSHAREDCLIPBOARDURITRANSFER.1838 */1839 static int sharedClipboardURITransferWriteThread(RTTHREAD hThread, void *pvUser)1840 {1841 AssertPtrReturn(pvUser, VERR_INVALID_POINTER);1842 1843 LogFlowFuncEnter();1844 1845 /* At the moment we only support one transfer at a time. */1846 PSHAREDCLIPBOARDURITRANSFER pTransfer = (PSHAREDCLIPBOARDURITRANSFER)pvUser;1847 AssertPtr(pTransfer->pProvider);1848 1849 int rc = VINF_SUCCESS;1850 1851 if (RT_SUCCESS(rc))1852 pTransfer->Thread.fStarted = true;1853 1854 int rc2 = RTThreadUserSignal(hThread);1855 const bool fSignalled = RT_SUCCESS(rc2);1856 1857 if (RT_SUCCESS(rc))1858 rc = SharedClipboardURITransferWrite(pTransfer);1859 1860 if (!fSignalled)1861 {1862 rc2 = RTThreadUserSignal(hThread);1863 AssertRC(rc2);1864 }1865 1866 LogFlowFuncLeaveRC(rc);1867 return rc;1868 }1869 1870 /**1871 * Main function to write a clipboard URI transfer.1872 *1873 * @returns VBox status code.1874 * @param pURI URI clipboard context to write.1875 */1876 int SharedClipboardURITransferWrite(PSHAREDCLIPBOARDURITRANSFER pTransfer)1877 {1878 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);1879 1880 LogFlowFuncEnter();1881 1882 int rc = SharedClipboardURITransferMetaDataWrite(pTransfer, NULL /* pcbWritten */);1883 if (RT_SUCCESS(rc))1884 {1885 rc = SharedClipboardURITransferWriteObjects(pTransfer);1886 if (RT_SUCCESS(rc))1887 {1888 if (pTransfer->Callbacks.pfnTransferComplete)1889 {1890 SHAREDCLIPBOARDURITRANSFERCALLBACKDATA callbackData = { pTransfer, pTransfer->Callbacks.pvUser };1891 pTransfer->Callbacks.pfnTransferComplete(&callbackData, rc);1892 }1893 }1894 }1895 1896 if (RT_FAILURE(rc))1897 {1898 if (pTransfer->Callbacks.pfnTransferError)1899 {1900 SHAREDCLIPBOARDURITRANSFERCALLBACKDATA callbackData = { pTransfer, pTransfer->Callbacks.pvUser };1901 pTransfer->Callbacks.pfnTransferError(&callbackData, rc);1902 }1903 }1904 1905 LogFlowFuncLeaveRC(rc);1906 return rc;1907 }1908 1909 /**1910 * Initializes a clipboard URI transfer.1911 *1912 * @returns VBox status code.1913 * @param pURI URI clipboard context to initialize.1914 */1915 int SharedClipboardURICtxInit(PSHAREDCLIPBOARDURICTX pURI)1916 {1917 AssertPtrReturn(pURI, VERR_INVALID_POINTER);1918 1919 LogFlowFuncEnter();1920 1921 int rc = RTCritSectInit(&pURI->CritSect);1922 if (RT_SUCCESS(rc))1923 {1924 RTListInit(&pURI->List);1925 1926 pURI->cTransfers = 0;1927 pURI->cMaxTransfers = 1; /* For now we only support one transfer per client at a time. */1928 1929 #ifdef DEBUG_andy1930 pURI->cMaxTransfers = UINT32_MAX;1931 #endif1932 1933 SharedClipboardURICtxReset(pURI);1934 }1935 1936 return VINF_SUCCESS;1937 }1938 1939 /**1940 * Destroys an URI clipboard information context struct.1941 *1942 * @param pURI URI clipboard context to destroy.1943 */1944 void SharedClipboardURICtxDestroy(PSHAREDCLIPBOARDURICTX pURI)1945 {1946 AssertPtrReturnVoid(pURI);1947 1948 RTCritSectDelete(&pURI->CritSect);1949 1950 PSHAREDCLIPBOARDURITRANSFER pTransfer, pTransferNext;1951 RTListForEachSafe(&pURI->List, pTransfer, pTransferNext, SHAREDCLIPBOARDURITRANSFER, Node)1952 {1953 SharedClipboardURITransferDestroy(pTransfer);1954 RTListNodeRemove(&pTransfer->Node);1955 }1956 1957 LogFlowFuncEnter();1958 }1959 1960 /**1961 * Resets an clipboard URI transfer.1962 *1963 * @param pURI URI clipboard context to reset.1964 */1965 void SharedClipboardURICtxReset(PSHAREDCLIPBOARDURICTX pURI)1966 {1967 AssertPtrReturnVoid(pURI);1968 1969 LogFlowFuncEnter();1970 1971 PSHAREDCLIPBOARDURITRANSFER pTransfer;1972 RTListForEach(&pURI->List, pTransfer, SHAREDCLIPBOARDURITRANSFER, Node)1973 SharedClipboardURITransferReset(pTransfer);1974 }1975 1976 /**1977 * Adds a new URI transfer to an clipboard URI transfer.1978 *1979 * @returns VBox status code.1980 * @param pURI URI clipboard context to add transfer to.1981 * @param pTransfer Pointer to URI clipboard transfer to add.1982 */1983 int SharedClipboardURICtxTransferAdd(PSHAREDCLIPBOARDURICTX pURI, PSHAREDCLIPBOARDURITRANSFER pTransfer)1984 {1985 AssertPtrReturn(pURI, VERR_INVALID_POINTER);1986 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);1987 1988 LogFlowFuncEnter();1989 1990 if (pURI->cTransfers == pURI->cMaxTransfers)1991 return VERR_SHCLPB_MAX_TRANSFERS_REACHED;1992 1993 RTListAppend(&pURI->List, &pTransfer->Node);1994 pURI->cTransfers++;1995 1996 return VINF_SUCCESS;1997 }1998 1999 /**2000 * Removes an URI transfer from a clipboard URI transfer.2001 *2002 * @returns VBox status code.2003 * @param pURI URI clipboard context to remove transfer from.2004 * @param pTransfer Pointer to URI clipboard transfer to remove.2005 */2006 int SharedClipboardURICtxTransferRemove(PSHAREDCLIPBOARDURICTX pURI, PSHAREDCLIPBOARDURITRANSFER pTransfer)2007 {2008 AssertPtrReturn(pURI, VERR_INVALID_POINTER);2009 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);2010 2011 LogFlowFuncEnter();2012 2013 /* Sanity. */2014 AssertReturn(pURI->cTransfers, VERR_WRONG_ORDER);2015 2016 int rc = SharedClipboardURITransferDestroy(pTransfer);2017 if (RT_SUCCESS(rc))2018 {2019 2020 RTListNodeRemove(&pTransfer->Node);2021 Assert(pURI->cTransfers);2022 pURI->cTransfers--;2023 }2024 2025 LogFlowFuncLeaveRC(rc);2026 return rc;2027 }2028 2029 /**2030 * Returns a specific URI transfer, internal version.2031 *2032 * @returns URI transfer, or NULL if not found.2033 * @param pURI URI clipboard context to return transfer for.2034 * @param uIdx Index of the transfer to return.2035 */2036 static PSHAREDCLIPBOARDURITRANSFER sharedClipboardURICtxGetTransferInternal(PSHAREDCLIPBOARDURICTX pURI, uint32_t uIdx)2037 {2038 AssertReturn(uIdx == 0, NULL); /* Only one transfer allowed at the moment. */2039 return RTListGetFirst(&pURI->List, SHAREDCLIPBOARDURITRANSFER, Node);2040 }2041 2042 /**2043 * Returns a specific URI transfer.2044 *2045 * @returns URI transfer, or NULL if not found.2046 * @param pURI URI clipboard context to return transfer for.2047 * @param uIdx Index of the transfer to return.2048 */2049 PSHAREDCLIPBOARDURITRANSFER SharedClipboardURICtxGetTransfer(PSHAREDCLIPBOARDURICTX pURI, uint32_t uIdx)2050 {2051 return sharedClipboardURICtxGetTransferInternal(pURI, uIdx);2052 }2053 2054 /**2055 * Returns the number of active URI transfers.2056 *2057 * @returns VBox status code.2058 * @param pURI URI clipboard context to return number for.2059 */2060 uint32_t SharedClipboardURICtxGetActiveTransfers(PSHAREDCLIPBOARDURICTX pURI)2061 {2062 AssertPtrReturn(pURI, 0);2063 return pURI->cTransfers;2064 }2065 2066 /**2067 * Returns whether the maximum of concurrent transfers of a specific URI context has been reached or not.2068 *2069 * @returns \c if maximum has been reached, \c false if not.2070 * @param pURI URI clipboard context to determine value for.2071 */2072 bool SharedClipboardURICtxMaximumTransfersReached(PSHAREDCLIPBOARDURICTX pURI)2073 {2074 AssertPtrReturn(pURI, true);2075 2076 LogFlowFunc(("cTransfers=%RU32\n", pURI->cTransfers));2077 2078 Assert(pURI->cTransfers <= pURI->cMaxTransfers);2079 return pURI->cTransfers == pURI->cMaxTransfers;2080 }2081 #endif /* VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */2082 -
trunk/src/VBox/HostServices/SharedClipboard/Makefile.kmk
r79181 r79270 54 54 $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardProvider-HostService.cpp \ 55 55 $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardURIList.cpp \ 56 $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardURIObject.cpp 56 $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardURIObject.cpp \ 57 $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/clipboard-uri.cpp 57 58 VBoxSharedClipboard_SOURCES.win += \ 58 59 $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardDataObjectImpl-win.cpp \
Note:
See TracChangeset
for help on using the changeset viewer.