Changeset 78501 in vbox for trunk/src/VBox/HostServices/SharedClipboard
- Timestamp:
- May 14, 2019 11:36:25 AM (6 years ago)
- svn:sync-xref-src-repo-rev:
- 130540
- Location:
- trunk/src/VBox/HostServices/SharedClipboard
- Files:
-
- 2 added
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostServices/SharedClipboard/Makefile.kmk
r78440 r78501 45 45 ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 46 46 VBoxSharedClipboard_SOURCES += \ 47 VBoxSharedClipboardSvc-uri.cpp \ 48 $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardPath.cpp \ 49 $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardCache.cpp \ 47 50 $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardURIList.cpp \ 48 $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardURIObject.cpp \ 49 $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardPath.cpp 51 $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardURIObject.cpp 50 52 endif 51 53 if1of ($(KBUILD_TARGET), linux solaris freebsd) ## @todo X11 -
trunk/src/VBox/HostServices/SharedClipboard/VBoxClipboard.h
r78151 r78501 1 1 /* $Id$ */ 2 2 /** @file 3 * Shared Clipboard Service - Internal Header.3 * Shared Clipboard Service - Internal header. 4 4 */ 5 5 … … 36 36 uint32_t u32ClientID; 37 37 38 bool fAsync; /* Guest is waiting for a message. */ 39 bool fReadPending; /* The guest is waiting for data from the host */ 40 41 bool fMsgQuit; 42 bool fMsgReadData; 43 bool fMsgFormats; 38 /** The guest is waiting for a message. */ 39 bool fAsync; 40 /** The guest is waiting for data from the host */ 41 bool fReadPending; 42 /** Whether the host host has sent a quit message. */ 43 bool fHostMsgQuit; 44 /** Whether the host host has requested reading clipboard data from the guest. */ 45 bool fHostMsgReadData; 46 /** Whether the host host has reported its available formats. */ 47 bool fHostMsgFormats; 44 48 45 49 struct { … … 67 71 * The service functions. Locking is between the service thread and the platform dependent windows thread. 68 72 */ 69 void vboxSvcClipboardReportMsg 73 void vboxSvcClipboardReportMsg(VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Msg, uint32_t u32Formats); 70 74 void vboxSvcClipboardCompleteReadData(VBOXCLIPBOARDCLIENTDATA *pClient, int rc, uint32_t cbActual); 71 75 … … 73 77 * Platform dependent functions. 74 78 */ 75 int vboxClipboardInit 76 void vboxClipboardDestroy 79 int vboxClipboardInit(void); 80 void vboxClipboardDestroy(void); 77 81 78 int vboxClipboardConnect 79 void vboxClipboardDisconnect 80 void vboxClipboardFormatAnnounce 81 int vboxClipboardReadData 82 void vboxClipboardWriteData 82 int vboxClipboardConnect(VBOXCLIPBOARDCLIENTDATA *pClient, bool fHeadless); 83 void vboxClipboardDisconnect(VBOXCLIPBOARDCLIENTDATA *pClient); 84 void vboxClipboardFormatAnnounce(VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Formats); 85 int vboxClipboardReadData(VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Format, void *pv, uint32_t cb, uint32_t *pcbActual); 86 void vboxClipboardWriteData(VBOXCLIPBOARDCLIENTDATA *pClient, void *pv, uint32_t cb, uint32_t u32Format); 83 87 84 88 int vboxClipboardSync (VBOXCLIPBOARDCLIENTDATA *pClient); -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-win.cpp
r78440 r78501 52 52 * Internal Functions * 53 53 *********************************************************************************************************************************/ 54 static int ConvertCFHtmlToMime(const char *pszSource, const uint32_t cch, char **ppszOutput, uint32_t *pch); 55 static int ConvertMimeToCFHTML(const char *pszSource, size_t cb, char **ppszOutput, uint32_t *pcbOutput); 56 static bool IsWindowsHTML(const char *source); 57 static int vboxClipboardSyncInternal(PVBOXCLIPBOARDCONTEXT pCtx); 54 static int vboxClipboardWinSyncInternal(PVBOXCLIPBOARDCONTEXT pCtx); 58 55 59 56 struct _VBOXCLIPBOARDCONTEXT … … 122 119 123 120 if ( u32Format == VBOX_SHARED_CLIPBOARD_FMT_HTML 124 && IsWindowsHTML((const char *)pvSrc))121 && VBoxClipboardWinIsCFHTML((const char *)pvSrc)) 125 122 { 126 123 /** @todo r=bird: Why the double conversion? */ 127 124 char *pszBuf = NULL; 128 125 uint32_t cbBuf = 0; 129 int rc = ConvertCFHtmlToMime((const char *)pvSrc, cbSrc, &pszBuf, &cbBuf);126 int rc = VBoxClipboardWinConvertCFHTMLToMIME((const char *)pvSrc, cbSrc, &pszBuf, &cbBuf); 130 127 if (RT_SUCCESS(rc)) 131 128 { … … 176 173 static LRESULT CALLBACK vboxClipboardWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 177 174 { 178 LRESULT rc = 0;175 LRESULT lresultRc = 0; 179 176 180 177 const PVBOXCLIPBOARDCONTEXT pCtx = &g_ctx; … … 190 187 { 191 188 /* Clipboard was updated by another application, retrieve formats and report back. */ 192 int vboxrc = vboxClipboardSyncInternal(pCtx);193 AssertRC( vboxrc);189 int rc = vboxClipboardWinSyncInternal(pCtx); 190 AssertRC(rc); 194 191 } 195 192 } break; … … 201 198 if (VBoxClipboardWinIsNewAPI(&pWinCtx->newAPI)) 202 199 { 203 rc = DefWindowProc(hwnd, msg, wParam, lParam);200 lresultRc = DefWindowProc(hwnd, msg, wParam, lParam); 204 201 break; 205 202 } … … 221 218 /* Pass the message further. */ 222 219 DWORD_PTR dwResult; 223 rc = SendMessageTimeout(pWinCtx->hWndNextInChain, WM_CHANGECBCHAIN, wParam, lParam, 0,224 VBOX_CLIPBOARD_CBCHAIN_TIMEOUT_MS,225 &dwResult);226 if (! rc)227 rc = (LRESULT)dwResult;220 lresultRc = SendMessageTimeout(pWinCtx->hWndNextInChain, WM_CHANGECBCHAIN, wParam, lParam, 0, 221 VBOX_CLIPBOARD_CBCHAIN_TIMEOUT_MS, 222 &dwResult); 223 if (!lresultRc) 224 lresultRc = (LRESULT)dwResult; 228 225 } 229 226 } … … 237 234 { 238 235 /* Clipboard was updated by another application, retrieve formats and report back. */ 239 int vboxrc = vboxClipboard SyncInternal(pCtx);236 int vboxrc = vboxClipboardWinSyncInternal(pCtx); 240 237 AssertRC(vboxrc); 241 238 } … … 244 241 { 245 242 LogFunc(("WM_DRAWCLIPBOARD next %p\n", pWinCtx->hWndNextInChain)); 243 246 244 /* Pass the message to next windows in the clipboard chain. */ 247 245 DWORD_PTR dwResult; 248 rc = SendMessageTimeout(pWinCtx->hWndNextInChain, msg, wParam, lParam, 0, VBOX_CLIPBOARD_CBCHAIN_TIMEOUT_MS,249 &dwResult);250 if (! rc)251 rc = dwResult;246 lresultRc = SendMessageTimeout(pWinCtx->hWndNextInChain, msg, wParam, lParam, 0, VBOX_CLIPBOARD_CBCHAIN_TIMEOUT_MS, 247 &dwResult); 248 if (!lresultRc) 249 lresultRc = dwResult; 252 250 } 253 251 } break; … … 281 279 case WM_RENDERFORMAT: 282 280 { 281 LogFunc(("WM_RENDERFORMAT\n")); 282 283 283 /* Insert the requested clipboard format data into the clipboard. */ 284 VBOXCLIPBOARDFORMAT fFormat = VBOX_SHARED_CLIPBOARD_FMT_NONE; 285 286 UINT format = (UINT)wParam; 287 288 LogFunc(("WM_RENDERFORMAT: Format %u\n", format)); 289 290 switch (format) 291 { 292 case CF_UNICODETEXT: 293 fFormat |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT; 294 break; 295 296 case CF_DIB: 297 fFormat |= VBOX_SHARED_CLIPBOARD_FMT_BITMAP; 298 break; 299 300 default: 301 if (format >= 0xC000) 302 { 303 TCHAR szFormatName[256]; /** @todo r=andy Unicode, 256 is enough? */ 304 int cActual = GetClipboardFormatName(format, szFormatName, sizeof(szFormatName) / sizeof (TCHAR)); 305 if (cActual) 306 { 307 if (RTStrCmp(szFormatName, "HTML Format") == 0) 308 fFormat |= VBOX_SHARED_CLIPBOARD_FMT_HTML; 309 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 310 if ( RTStrCmp(szFormatName, CFSTR_FILEDESCRIPTOR) == 0 311 || RTStrCmp(szFormatName, CFSTR_FILECONTENTS) == 0) 312 fFormat |= VBOX_SHARED_CLIPBOARD_FMT_URI_LIST; 313 #endif 314 } 315 } 316 break; 317 } 284 const UINT cfFormat = (UINT)wParam; 285 286 const VBOXCLIPBOARDFORMAT fFormat = VBoxClipboardWinClipboardFormatToVBox(cfFormat); 287 288 LogFunc(("WM_RENDERFORMAT: cfFormat=%u -> fFormat=0x%x\n", cfFormat, fFormat)); 318 289 319 290 if ( fFormat == VBOX_SHARED_CLIPBOARD_FMT_NONE … … 322 293 /* Unsupported clipboard format is requested. */ 323 294 LogFunc(("WM_RENDERFORMAT unsupported format requested or client is not active\n")); 324 EmptyClipboard();295 VBoxClipboardWinClear(); 325 296 } 326 297 else 327 298 { 328 int vboxrc = vboxClipboardReadDataFromClient(pCtx, fFormat);329 330 LogFunc(("vboxClipboardReadDataFromClient vboxrc = %d, pv %p, cb %d, u32Format %d\n",331 vboxrc, pCtx->pClient->data.pv, pCtx->pClient->data.cb, pCtx->pClient->data.u32Format));332 333 if ( RT_SUCCESS ( vboxrc)299 int rc = vboxClipboardReadDataFromClient(pCtx, fFormat); 300 301 LogFunc(("vboxClipboardReadDataFromClient rc = %Rrc, pv %p, cb %d, u32Format %d\n", 302 rc, pCtx->pClient->data.pv, pCtx->pClient->data.cb, pCtx->pClient->data.u32Format)); 303 304 if ( RT_SUCCESS (rc) 334 305 && pCtx->pClient->data.pv != NULL 335 306 && pCtx->pClient->data.cb > 0 … … 367 338 * size is 'cb' and format is 'format'. 368 339 */ 369 HANDLE hClip = SetClipboardData( format, hMem);340 HANDLE hClip = SetClipboardData(cfFormat, hMem); 370 341 371 342 LogFunc(("vboxClipboardHostEvent hClip %p\n", hClip)); … … 399 370 * windows is to be destroyed and therefore the guest side becomes inactive. 400 371 */ 401 int vboxrc = VBoxClipboardWinOpen(hwnd);402 if (RT_SUCCESS( vboxrc))372 int rc = VBoxClipboardWinOpen(hwnd); 373 if (RT_SUCCESS(rc)) 403 374 { 404 375 VBoxClipboardWinClear(); 405 376 VBoxClipboardWinClose(); 406 377 } 407 else408 {409 LogFlowFunc(("WM_RENDERALLFORMATS: error in open clipboard. hwnd: %x, rc: %Rrc\n", hwnd, vboxrc));410 }411 378 } break; 412 379 413 380 case VBOX_CLIPBOARD_WM_SET_FORMATS: 414 381 { 415 if (pCtx->pClient == NULL || pCtx->pClient->fMsgFormats) 382 if ( pCtx->pClient == NULL 383 || pCtx->pClient->fHostMsgFormats) 416 384 { 417 385 /* Host has pending formats message. Ignore the guest announcement, … … 423 391 424 392 /* Announce available formats. Do not insert data, they will be inserted in WM_RENDER*. */ 425 uint32_t u32Formats = (uint32_t)lParam;426 427 LogFunc(("VBOX_CLIPBOARD_WM_SET_FORMATS: u32Formats=%02X\n", u32Formats));428 429 int vboxrc = VBoxClipboardWinOpen(hwnd);430 if (RT_SUCCESS( vboxrc))393 VBOXCLIPBOARDFORMATS fFormats = (uint32_t)lParam; 394 395 LogFunc(("VBOX_CLIPBOARD_WM_SET_FORMATS: fFormats=%02X\n", fFormats)); 396 397 int rc = VBoxClipboardWinOpen(hwnd); 398 if (RT_SUCCESS(rc)) 431 399 { 432 400 VBoxClipboardWinClear(); 433 401 434 LogFunc(("VBOX_CLIPBOARD_WM_SET_FORMATS emptied clipboard\n")); 435 436 HANDLE hClip = NULL; 437 438 if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT) 402 HANDLE hClip = NULL; 403 UINT cfFormat = 0; 404 405 /** @todo r=andy Only one clipboard format can be set at once, at least on Windows. */ 406 407 if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT) 408 { 439 409 hClip = SetClipboardData(CF_UNICODETEXT, NULL); 440 441 if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP) 410 } 411 else if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP) 412 { 442 413 hClip = SetClipboardData(CF_DIB, NULL); 443 444 if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_HTML) 445 { 446 UINT format = RegisterClipboardFormat ("HTML Format"); 447 if (format != 0) 448 { 449 hClip = SetClipboardData (format, NULL); 450 } 414 } 415 else if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_HTML) 416 { 417 cfFormat = RegisterClipboardFormat(VBOX_CLIPBOARD_WIN_REGFMT_HTML); 418 if (cfFormat) 419 hClip = SetClipboardData(cfFormat, NULL); 451 420 } 452 421 453 422 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 454 if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_URI_LIST) 455 { 456 UINT format = RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR); 457 if (format) 458 hClip = SetClipboardData(format, NULL); 459 } 423 /** @todo */ 460 424 #endif 461 425 VBoxClipboardWinClose(); … … 480 444 { 481 445 LogFunc(("WM_ %p\n", msg)); 482 rc = DefWindowProc(hwnd, msg, wParam, lParam);483 } 484 } 485 486 LogFunc(("WM_ rc %d\n", rc));487 return rc;446 lresultRc = DefWindowProc(hwnd, msg, wParam, lParam); 447 } 448 } 449 450 LogFunc(("WM_ rc %d\n", lresultRc)); 451 return lresultRc; 488 452 } 489 453 … … 575 539 * @param pCtx Clipboard context to synchronize. 576 540 */ 577 static int vboxClipboard SyncInternal(PVBOXCLIPBOARDCONTEXT pCtx)541 static int vboxClipboardWinSyncInternal(PVBOXCLIPBOARDCONTEXT pCtx) 578 542 { 579 543 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); … … 663 627 { 664 628 /* Sync the host clipboard content with the client. */ 665 return vboxClipboard SyncInternal(pClient->pCtx);629 return vboxClipboardWinSyncInternal(pClient->pCtx); 666 630 } 667 631 … … 783 747 else if (u32Format & VBOX_SHARED_CLIPBOARD_FMT_HTML) 784 748 { 785 UINT format = RegisterClipboardFormat( "HTML Format");749 UINT format = RegisterClipboardFormat(VBOX_CLIPBOARD_WIN_REGFMT_HTML); 786 750 if (format != 0) 787 751 { … … 792 756 if (lp != NULL) 793 757 { 794 LogFunc(("CF_HTML\n")); 795 758 /** @todo r=andy Add data overflow handling. */ 796 759 vboxClipboardGetData(VBOX_SHARED_CLIPBOARD_FMT_HTML, lp, GlobalSize(hClip), 797 760 pv, cb, pcbActual); … … 813 776 { 814 777 hClip = GetClipboardData(CF_HDROP); 815 if (hClip != NULL) 778 if (hClip != NULL) /* Do we have data in CF_HDROP format? */ 816 779 { 817 780 LPVOID lp = GlobalLock(hClip); 818 781 if (lp) 819 782 { 820 /* Convert to a string list, separated by \r\n. */ 821 DROPFILES *pDropFiles = (DROPFILES *)hClip; 822 AssertPtr(pDropFiles); 823 824 /* Do we need to do Unicode stuff? */ 825 const bool fUnicode = RT_BOOL(pDropFiles->fWide); 826 827 /* Get the offset of the file list. */ 828 Assert(pDropFiles->pFiles >= sizeof(DROPFILES)); 829 830 /* Note: This is *not* pDropFiles->pFiles! DragQueryFile only 831 * will work with the plain storage medium pointer! */ 832 HDROP hDrop = (HDROP)(hClip); 833 834 /* First, get the file count. */ 835 /** @todo Does this work on Windows 2000 / NT4? */ 836 char *pszFiles = NULL; 837 uint32_t cchFiles = 0; 838 UINT cFiles = DragQueryFile(hDrop, UINT32_MAX /* iFile */, NULL /* lpszFile */, 0 /* cchFile */); 839 840 LogRel(("Shared Clipboard: Got %RU16 file(s), fUnicode=%RTbool\n", cFiles, fUnicode)); 841 842 for (UINT i = 0; i < cFiles; i++) 843 { 844 UINT cchFile = DragQueryFile(hDrop, i /* File index */, NULL /* Query size first */, 0 /* cchFile */); 845 Assert(cchFile); 846 847 if (RT_FAILURE(rc)) 848 break; 849 850 char *pszFileUtf8 = NULL; /* UTF-8 version. */ 851 UINT cchFileUtf8 = 0; 852 if (fUnicode) 853 { 854 /* Allocate enough space (including terminator). */ 855 WCHAR *pwszFile = (WCHAR *)RTMemAlloc((cchFile + 1) * sizeof(WCHAR)); 856 if (pwszFile) 857 { 858 const UINT cwcFileUtf16 = DragQueryFileW(hDrop, i /* File index */, 859 pwszFile, cchFile + 1 /* Include terminator */); 860 861 AssertMsg(cwcFileUtf16 == cchFile, ("cchFileUtf16 (%RU16) does not match cchFile (%RU16)\n", 862 cwcFileUtf16, cchFile)); 863 RT_NOREF(cwcFileUtf16); 864 865 rc = RTUtf16ToUtf8(pwszFile, &pszFileUtf8); 866 if (RT_SUCCESS(rc)) 867 { 868 cchFileUtf8 = (UINT)strlen(pszFileUtf8); 869 Assert(cchFileUtf8); 870 } 871 872 RTMemFree(pwszFile); 873 } 874 else 875 rc = VERR_NO_MEMORY; 876 } 877 else /* ANSI */ 878 { 879 /* Allocate enough space (including terminator). */ 880 pszFileUtf8 = (char *)RTMemAlloc((cchFile + 1) * sizeof(char)); 881 if (pszFileUtf8) 882 { 883 cchFileUtf8 = DragQueryFileA(hDrop, i /* File index */, 884 pszFileUtf8, cchFile + 1 /* Include terminator */); 885 886 AssertMsg(cchFileUtf8 == cchFile, ("cchFileUtf8 (%RU16) does not match cchFile (%RU16)\n", 887 cchFileUtf8, cchFile)); 888 } 889 else 890 rc = VERR_NO_MEMORY; 891 } 892 893 if (RT_SUCCESS(rc)) 894 { 895 LogFlowFunc(("\tFile: %s (cchFile=%RU16)\n", pszFileUtf8, cchFileUtf8)); 896 897 LogRel2(("Shared Clipboard: Adding host file '%s'\n", pszFileUtf8)); 898 899 rc = RTStrAAppendExN(&pszFiles, 1 /* cPairs */, pszFileUtf8, cchFileUtf8); 900 if (RT_SUCCESS(rc)) 901 cchFiles += cchFileUtf8; 902 } 903 else 904 LogRel(("Shared Clipboard: Error handling file entry #%u, rc=%Rrc\n", i, rc)); 905 906 if (pszFileUtf8) 907 RTStrFree(pszFileUtf8); 908 909 if (RT_FAILURE(rc)) 910 break; 911 912 /* Add separation between filenames. 913 * Note: Also do this for the last element of the list. */ 914 rc = RTStrAAppendExN(&pszFiles, 1 /* cPairs */, "\r\n", 2 /* Bytes */); 915 if (RT_SUCCESS(rc)) 916 cchFiles += 2; /* Include \r\n */ 917 } 918 783 void *pvTemp; 784 size_t cbTemp; 785 rc = VBoxClipboardWinDropFilesToStringList((DROPFILES *)lp, &pvTemp, &cbTemp); 919 786 if (RT_SUCCESS(rc)) 920 787 { 921 cchFiles += 1; /* Add string termination. */ 922 uint32_t cbFiles = cchFiles * sizeof(char); 923 924 LogFlowFunc(("cFiles=%u, cchFiles=%RU32, cbFiles=%RU32, pszFiles=0x%p\n", 925 cFiles, cchFiles, cbFiles, pszFiles)); 926 927 /* Translate the list into URI elements. */ 928 SharedClipboardURIList lstURI; 929 rc = lstURI.AppendNativePathsFromList(pszFiles, cbFiles, 930 SHAREDCLIPBOARDURILIST_FLAGS_ABSOLUTE_PATHS); 931 if (RT_SUCCESS(rc)) 788 if (cbTemp > cb) /** @todo Add overflow handling! */ 932 789 { 933 RTCString strRoot = lstURI.GetRootEntries(); 934 size_t cbRoot = strRoot.length() + 1; /* Include termination */ 935 936 if (cbRoot > cb) /** @todo Add overflow handling! */ 937 cbRoot = cb; /* Never copy more than the available buffer supplies. */ 938 939 memcpy(pv, strRoot.c_str(), cbRoot); 940 941 *pcbActual = (uint32_t)cbRoot; 790 AssertMsgFailed(("More data buffer needed -- fix this\n")); 791 cbTemp = cb; /* Never copy more than the available buffer supplies. */ 942 792 } 793 794 memcpy(pv, pvTemp, cbTemp); 795 796 RTMemFree(pvTemp); 797 798 *pcbActual = (uint32_t)cbTemp; 943 799 } 944 945 LogFlowFunc(("Building CF_HDROP list rc=%Rrc, pszFiles=0x%p, cFiles=%RU16, cchFiles=%RU32\n",946 rc, pszFiles, cFiles, cchFiles));947 948 if (pszFiles)949 RTStrFree(pszFiles);950 800 951 801 GlobalUnlock(hClip); … … 982 832 983 833 if ( u32Format == VBOX_SHARED_CLIPBOARD_FMT_HTML 984 && ! IsWindowsHTML((const char*)pv))834 && !VBoxClipboardWinIsCFHTML((const char*)pv)) 985 835 { 986 836 /* check that this is not already CF_HTML */ 987 837 uint32_t cbResult; 988 int rc = ConvertMimeToCFHTML((const char *)pv, cb, &pszResult, &cbResult);838 int rc = VBoxClipboardWinConvertMIMEToCFHTML((const char *)pv, cb, &pszResult, &cbResult); 989 839 if (RT_SUCCESS(rc)) 990 840 { … … 1015 865 } 1016 866 1017 1018 /**1019 * Extracts field value from CF_HTML struct1020 *1021 * @returns VBox status code1022 * @param pszSrc source in CF_HTML format1023 * @param pszOption Name of CF_HTML field1024 * @param puValue Where to return extracted value of CF_HTML field1025 */1026 static int GetHeaderValue(const char *pszSrc, const char *pszOption, uint32_t *puValue)1027 {1028 int rc = VERR_INVALID_PARAMETER;1029 1030 Assert(pszSrc);1031 Assert(pszOption);1032 1033 const char *pszOptionValue = RTStrStr(pszSrc, pszOption);1034 if (pszOptionValue)1035 {1036 size_t cchOption = strlen(pszOption);1037 Assert(cchOption);1038 1039 rc = RTStrToUInt32Ex(pszOptionValue + cchOption, NULL, 10, puValue);1040 }1041 return rc;1042 }1043 1044 1045 /**1046 * Check that the source string contains CF_HTML struct1047 *1048 * @param pszSource source string.1049 *1050 * @returns @c true if the @a pszSource string is in CF_HTML format1051 */1052 static bool IsWindowsHTML(const char *pszSource)1053 {1054 return RTStrStr(pszSource, "Version:") != NULL1055 && RTStrStr(pszSource, "StartHTML:") != NULL;1056 }1057 1058 1059 /**1060 * Converts clipboard data from CF_HTML format to MIME clipboard format.1061 *1062 * Returns allocated buffer that contains html converted to text/html mime type1063 *1064 * @returns VBox status code.1065 * @param pszSource The input.1066 * @param cch The length of the input.1067 * @param ppszOutput Where to return the result. Free using RTMemFree.1068 * @param pcbOutput Where to the return length of the result (bytes/chars).1069 */1070 static int ConvertCFHtmlToMime(const char *pszSource, const uint32_t cch, char **ppszOutput, uint32_t *pcbOutput)1071 {1072 Assert(pszSource);1073 Assert(cch);1074 Assert(ppszOutput);1075 Assert(pcbOutput);1076 1077 uint32_t offStart;1078 int rc = GetHeaderValue(pszSource, "StartFragment:", &offStart);1079 if (RT_SUCCESS(rc))1080 {1081 uint32_t offEnd;1082 rc = GetHeaderValue(pszSource, "EndFragment:", &offEnd);1083 if (RT_SUCCESS(rc))1084 {1085 if ( offStart > 01086 && offEnd > 01087 && offEnd > offStart1088 && offEnd <= cch)1089 {1090 uint32_t cchSubStr = offEnd - offStart;1091 char *pszResult = (char *)RTMemAlloc(cchSubStr + 1);1092 if (pszResult)1093 {1094 rc = RTStrCopyEx(pszResult, cchSubStr + 1, pszSource + offStart, cchSubStr);1095 if (RT_SUCCESS(rc))1096 {1097 *ppszOutput = pszResult;1098 *pcbOutput = (uint32_t)(cchSubStr + 1);1099 rc = VINF_SUCCESS;1100 }1101 else1102 {1103 LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected EndFragment. rc = %Rrc\n", rc));1104 RTMemFree(pszResult);1105 }1106 }1107 else1108 {1109 LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected EndFragment\n"));1110 rc = VERR_NO_MEMORY;1111 }1112 }1113 else1114 {1115 LogRelFlowFunc(("Error: CF_HTML out of bounds - offStart=%#x offEnd=%#x cch=%#x\n", offStart, offEnd, cch));1116 rc = VERR_INVALID_PARAMETER;1117 }1118 }1119 else1120 {1121 LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected EndFragment. rc = %Rrc\n", rc));1122 rc = VERR_INVALID_PARAMETER;1123 }1124 }1125 else1126 {1127 LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected StartFragment. rc = %Rrc\n", rc));1128 rc = VERR_INVALID_PARAMETER;1129 }1130 1131 return rc;1132 }1133 1134 1135 1136 /**1137 * Converts source UTF-8 MIME HTML clipboard data to UTF-8 CF_HTML format.1138 *1139 * This is just encapsulation work, slapping a header on the data.1140 *1141 * It allocates1142 *1143 * Calculations:1144 * Header length = format Length + (2*(10 - 5('%010d'))('digits')) - 2('%s') = format length + 81145 * EndHtml = Header length + fragment length1146 * StartHtml = 105(constant)1147 * StartFragment = 141(constant) may vary if the header html content will be extended1148 * EndFragment = Header length + fragment length - 38(ending length)1149 *1150 * @param pszSource Source buffer that contains utf-16 string in mime html format1151 * @param cb Size of source buffer in bytes1152 * @param ppszOutput Where to return the allocated output buffer to put converted UTF-81153 * CF_HTML clipboard data. This function allocates memory for this.1154 * @param pcbOutput Where to return the size of allocated result buffer in bytes/chars, including zero terminator1155 *1156 * @note output buffer should be free using RTMemFree()1157 * @note Everything inside of fragment can be UTF8. Windows allows it. Everything in header should be Latin1.1158 */1159 static int ConvertMimeToCFHTML(const char *pszSource, size_t cb, char **ppszOutput, uint32_t *pcbOutput)1160 {1161 Assert(ppszOutput);1162 Assert(pcbOutput);1163 Assert(pszSource);1164 Assert(cb);1165 1166 /* construct CF_HTML formatted string */1167 char *pszResult = NULL;1168 size_t cchFragment;1169 int rc = RTStrNLenEx(pszSource, cb, &cchFragment);1170 if (!RT_SUCCESS(rc))1171 {1172 LogRelFlowFunc(("Error: invalid source fragment. rc = %Rrc\n"));1173 return VERR_INVALID_PARAMETER;1174 }1175 1176 /*1177 @StartHtml - pos before <html>1178 @EndHtml - whole size of text excluding ending zero char1179 @StartFragment - pos after <!--StartFragment-->1180 @EndFragment - pos before <!--EndFragment-->1181 @note: all values includes CR\LF inserted into text1182 Calculations:1183 Header length = format Length + (3*6('digits')) - 2('%s') = format length + 16 (control value - 183)1184 EndHtml = Header length + fragment length1185 StartHtml = 105(constant)1186 StartFragment = 143(constant)1187 EndFragment = Header length + fragment length - 40(ending length)1188 */1189 static const char s_szFormatSample[] =1190 /* 0: */ "Version:1.0\r\n"1191 /* 13: */ "StartHTML:000000101\r\n"1192 /* 34: */ "EndHTML:%0000009u\r\n" // END HTML = Header length + fragment length1193 /* 53: */ "StartFragment:000000137\r\n"1194 /* 78: */ "EndFragment:%0000009u\r\n"1195 /* 101: */ "<html>\r\n"1196 /* 109: */ "<body>\r\n"1197 /* 117: */ "<!--StartFragment-->"1198 /* 137: */ "%s"1199 /* 137+2: */ "<!--EndFragment-->\r\n"1200 /* 157+2: */ "</body>\r\n"1201 /* 166+2: */ "</html>\r\n";1202 /* 175+2: */1203 AssertCompile(sizeof(s_szFormatSample) == 175 + 2 + 1);1204 1205 /* calculate parameters of CF_HTML header */1206 size_t cchHeader = sizeof(s_szFormatSample) - 1;1207 size_t offEndHtml = cchHeader + cchFragment;1208 size_t offEndFragment = cchHeader + cchFragment - 38; /* 175-137 = 38 */1209 pszResult = (char *)RTMemAlloc(offEndHtml + 1);1210 if (pszResult == NULL)1211 {1212 LogRelFlowFunc(("Error: Cannot allocate memory for result buffer. rc = %Rrc\n"));1213 return VERR_NO_MEMORY;1214 }1215 1216 /* format result CF_HTML string */1217 size_t cchFormatted = RTStrPrintf(pszResult, offEndHtml + 1,1218 s_szFormatSample, offEndHtml, offEndFragment, pszSource);1219 Assert(offEndHtml == cchFormatted); NOREF(cchFormatted);1220 1221 #ifdef VBOX_STRICT1222 /* Control calculations. check consistency.*/1223 static const char s_szStartFragment[] = "<!--StartFragment-->";1224 static const char s_szEndFragment[] = "<!--EndFragment-->";1225 1226 /* check 'StartFragment:' value */1227 const char *pszRealStartFragment = RTStrStr(pszResult, s_szStartFragment);1228 Assert(&pszRealStartFragment[sizeof(s_szStartFragment) - 1] - pszResult == 137);1229 1230 /* check 'EndFragment:' value */1231 const char *pszRealEndFragment = RTStrStr(pszResult, s_szEndFragment);1232 Assert((size_t)(pszRealEndFragment - pszResult) == offEndFragment);1233 #endif1234 1235 *ppszOutput = pszResult;1236 *pcbOutput = (uint32_t)cchFormatted + 1;1237 Assert(*pcbOutput == cchFormatted + 1);1238 1239 return VINF_SUCCESS;1240 }1241 -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc.cpp
r78442 r78501 86 86 87 87 #include "VBoxClipboard.h" 88 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 89 # include "VBoxSharedClipboardSvc-uri.h" 90 #endif 88 91 89 92 … … 200 203 { 201 204 /* Message priority is taken into account. */ 202 if (pClient->f MsgQuit)205 if (pClient->fHostMsgQuit) 203 206 { 204 207 LogFlowFunc(("vboxSvcClipboardReturnMsg: Quit\n")); 205 208 VBoxHGCMParmUInt32Set(&paParms[0], VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT); 206 209 VBoxHGCMParmUInt32Set(&paParms[1], 0); 207 pClient->f MsgQuit = false;208 } 209 else if (pClient->f MsgReadData)210 pClient->fHostMsgQuit = false; 211 } 212 else if (pClient->fHostMsgReadData) 210 213 { 211 214 uint32_t fFormat = 0; … … 218 221 else if (pClient->u32RequestedFormat & VBOX_SHARED_CLIPBOARD_FMT_HTML) 219 222 fFormat = VBOX_SHARED_CLIPBOARD_FMT_HTML; 223 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 224 else if (pClient->u32RequestedFormat & VBOX_SHARED_CLIPBOARD_FMT_URI_LIST) 225 fFormat = VBOX_SHARED_CLIPBOARD_FMT_URI_LIST; 226 #endif 220 227 else 221 AssertStmt(pClient->u32RequestedFormat == 0, pClient->u32RequestedFormat = 0); 228 { 229 LogRel2(("Clipboard: Unsupported format from guest (0x%x), skipping\n", fFormat)); 230 pClient->u32RequestedFormat = 0; 231 } 222 232 pClient->u32RequestedFormat &= ~fFormat; 223 233 VBoxHGCMParmUInt32Set(&paParms[0], VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA); 224 234 VBoxHGCMParmUInt32Set(&paParms[1], fFormat); 225 235 if (pClient->u32RequestedFormat == 0) 226 pClient->f MsgReadData = false;227 } 228 else if (pClient->f MsgFormats)236 pClient->fHostMsgReadData = false; 237 } 238 else if (pClient->fHostMsgFormats) 229 239 { 230 240 LogFlowFunc(("vboxSvcClipboardReturnMsg: Formats %02X\n", pClient->u32AvailableFormats)); 231 241 VBoxHGCMParmUInt32Set(&paParms[0], VBOX_SHARED_CLIPBOARD_HOST_MSG_REPORT_FORMATS); 232 242 VBoxHGCMParmUInt32Set(&paParms[1], pClient->u32AvailableFormats); 233 pClient->f MsgFormats = false;243 pClient->fHostMsgFormats = false; 234 244 } 235 245 else … … 255 265 { 256 266 LogFlowFunc(("Quit\n")); 257 pClient->f MsgQuit = true;267 pClient->fHostMsgQuit = true; 258 268 } break; 259 269 case VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA: … … 268 278 LogFlowFunc(("ReadData %02X\n", u32Formats)); 269 279 pClient->u32RequestedFormat = u32Formats; 270 pClient->f MsgReadData = true;280 pClient->fHostMsgReadData = true; 271 281 } break; 272 282 case VBOX_SHARED_CLIPBOARD_HOST_MSG_REPORT_FORMATS: … … 281 291 LogFlowFunc(("Formats %02X\n", u32Formats)); 282 292 pClient->u32AvailableFormats = u32Formats; 283 pClient->f MsgFormats = true;293 pClient->fHostMsgFormats = true; 284 294 } break; 285 295 default: … … 683 693 default: 684 694 { 695 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 696 rc = vboxClipboardSvcURIHandler(u32ClientID, pvClient, u32Function, cParms, paParms, tsArrival, 697 &fAsynchronousProcessing); 698 #else 685 699 rc = VERR_NOT_IMPLEMENTED; 700 #endif 686 701 } 687 702 } … … 772 787 773 788 default: 774 break; 789 { 790 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 791 rc = vboxClipboardSvcURIHostHandler(u32Function, cParms, paParms); 792 #endif 793 } break; 775 794 } 776 795 … … 786 805 { 787 806 SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTDATA, u32ClientID), /* for validation purposes */ 788 SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTDATA, f MsgQuit),789 SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTDATA, f MsgReadData),790 SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTDATA, f MsgFormats),807 SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTDATA, fHostMsgQuit), 808 SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTDATA, fHostMsgReadData), 809 SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTDATA, fHostMsgFormats), 791 810 SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTDATA, u32RequestedFormat), 792 811 SSMFIELD_ENTRY_TERM() … … 843 862 bool fAsync: 1; /* Guest is waiting for a message. */ 844 863 845 bool f MsgQuit: 1;846 bool f MsgReadData: 1;847 bool f MsgFormats: 1;864 bool fHostMsgQuit: 1; 865 bool fHostMsgReadData: 1; 866 bool fHostMsgFormats: 1; 848 867 849 868 struct … … 918 937 AssertRCReturn(rc, rc); 919 938 920 pClient->f MsgQuit = savedState.fMsgQuit;921 pClient->f MsgReadData = savedState.fMsgReadData;922 pClient->f MsgFormats = savedState.fMsgFormats;939 pClient->fHostMsgQuit = savedState.fHostMsgQuit; 940 pClient->fHostMsgReadData = savedState.fHostMsgReadData; 941 pClient->fHostMsgFormats = savedState.fHostMsgFormats; 923 942 pClient->u32RequestedFormat = savedState.u32RequestedFormat; 924 943 }
Note:
See TracChangeset
for help on using the changeset viewer.