VirtualBox

Ignore:
Timestamp:
May 14, 2019 11:36:25 AM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
130540
Message:

Shared Clipboard/URI: Update.

Location:
trunk/src/VBox/HostServices/SharedClipboard
Files:
2 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostServices/SharedClipboard/Makefile.kmk

    r78440 r78501  
    4545ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
    4646 VBoxSharedClipboard_SOURCES += \
     47        VBoxSharedClipboardSvc-uri.cpp \
     48        $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardPath.cpp \
     49        $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardCache.cpp \
    4750        $(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
    5052endif
    5153if1of ($(KBUILD_TARGET), linux solaris freebsd) ## @todo X11
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxClipboard.h

    r78151 r78501  
    11/* $Id$ */
    22/** @file
    3  * Shared Clipboard Service - Internal Header.
     3 * Shared Clipboard Service - Internal header.
    44 */
    55
     
    3636    uint32_t u32ClientID;
    3737
    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;
    4448
    4549    struct {
     
    6771 * The service functions. Locking is between the service thread and the platform dependent windows thread.
    6872 */
    69 void vboxSvcClipboardReportMsg (VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Msg, uint32_t u32Formats);
     73void vboxSvcClipboardReportMsg(VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Msg, uint32_t u32Formats);
    7074void vboxSvcClipboardCompleteReadData(VBOXCLIPBOARDCLIENTDATA *pClient, int rc, uint32_t cbActual);
    7175
     
    7377 * Platform dependent functions.
    7478 */
    75 int vboxClipboardInit (void);
    76 void vboxClipboardDestroy (void);
     79int vboxClipboardInit(void);
     80void vboxClipboardDestroy(void);
    7781
    78 int vboxClipboardConnect (VBOXCLIPBOARDCLIENTDATA *pClient, bool fHeadless);
    79 void vboxClipboardDisconnect (VBOXCLIPBOARDCLIENTDATA *pClient);
    80 void vboxClipboardFormatAnnounce (VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Formats);
    81 int vboxClipboardReadData (VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Format, void *pv, uint32_t cb, uint32_t *pcbActual);
    82 void vboxClipboardWriteData (VBOXCLIPBOARDCLIENTDATA *pClient, void *pv, uint32_t cb, uint32_t u32Format);
     82int vboxClipboardConnect(VBOXCLIPBOARDCLIENTDATA *pClient, bool fHeadless);
     83void vboxClipboardDisconnect(VBOXCLIPBOARDCLIENTDATA *pClient);
     84void vboxClipboardFormatAnnounce(VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Formats);
     85int vboxClipboardReadData(VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Format, void *pv, uint32_t cb, uint32_t *pcbActual);
     86void vboxClipboardWriteData(VBOXCLIPBOARDCLIENTDATA *pClient, void *pv, uint32_t cb, uint32_t u32Format);
    8387
    8488int vboxClipboardSync (VBOXCLIPBOARDCLIENTDATA *pClient);
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-win.cpp

    r78440 r78501  
    5252*   Internal Functions                                                                                                           *
    5353*********************************************************************************************************************************/
    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);
     54static int vboxClipboardWinSyncInternal(PVBOXCLIPBOARDCONTEXT pCtx);
    5855
    5956struct _VBOXCLIPBOARDCONTEXT
     
    122119
    123120    if (   u32Format == VBOX_SHARED_CLIPBOARD_FMT_HTML
    124         && IsWindowsHTML((const char *)pvSrc))
     121        && VBoxClipboardWinIsCFHTML((const char *)pvSrc))
    125122    {
    126123        /** @todo r=bird: Why the double conversion? */
    127124        char *pszBuf = NULL;
    128125        uint32_t cbBuf = 0;
    129         int rc = ConvertCFHtmlToMime((const char *)pvSrc, cbSrc, &pszBuf, &cbBuf);
     126        int rc = VBoxClipboardWinConvertCFHTMLToMIME((const char *)pvSrc, cbSrc, &pszBuf, &cbBuf);
    130127        if (RT_SUCCESS(rc))
    131128        {
     
    176173static LRESULT CALLBACK vboxClipboardWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    177174{
    178     LRESULT rc = 0;
     175    LRESULT lresultRc = 0;
    179176
    180177    const PVBOXCLIPBOARDCONTEXT pCtx    = &g_ctx;
     
    190187            {
    191188                /* 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);
    194191            }
    195192        } break;
     
    201198            if (VBoxClipboardWinIsNewAPI(&pWinCtx->newAPI))
    202199            {
    203                 rc = DefWindowProc(hwnd, msg, wParam, lParam);
     200                lresultRc = DefWindowProc(hwnd, msg, wParam, lParam);
    204201                break;
    205202            }
     
    221218                    /* Pass the message further. */
    222219                    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;
    228225                }
    229226            }
     
    237234            {
    238235                /* Clipboard was updated by another application, retrieve formats and report back. */
    239                 int vboxrc = vboxClipboardSyncInternal(pCtx);
     236                int vboxrc = vboxClipboardWinSyncInternal(pCtx);
    240237                AssertRC(vboxrc);
    241238            }
     
    244241            {
    245242                LogFunc(("WM_DRAWCLIPBOARD next %p\n", pWinCtx->hWndNextInChain));
     243
    246244                /* Pass the message to next windows in the clipboard chain. */
    247245                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;
    252250            }
    253251        } break;
     
    281279        case WM_RENDERFORMAT:
    282280        {
     281            LogFunc(("WM_RENDERFORMAT\n"));
     282
    283283            /* 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));
    318289
    319290            if (   fFormat       == VBOX_SHARED_CLIPBOARD_FMT_NONE
     
    322293                /* Unsupported clipboard format is requested. */
    323294                LogFunc(("WM_RENDERFORMAT unsupported format requested or client is not active\n"));
    324                 EmptyClipboard();
     295                VBoxClipboardWinClear();
    325296            }
    326297            else
    327298            {
    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)
    334305                    && pCtx->pClient->data.pv != NULL
    335306                    && pCtx->pClient->data.cb > 0
     
    367338                             * size is 'cb' and format is 'format'.
    368339                             */
    369                             HANDLE hClip = SetClipboardData(format, hMem);
     340                            HANDLE hClip = SetClipboardData(cfFormat, hMem);
    370341
    371342                            LogFunc(("vboxClipboardHostEvent hClip %p\n", hClip));
     
    399370             * windows is to be destroyed and therefore the guest side becomes inactive.
    400371             */
    401             int vboxrc = VBoxClipboardWinOpen(hwnd);
    402             if (RT_SUCCESS(vboxrc))
     372            int rc = VBoxClipboardWinOpen(hwnd);
     373            if (RT_SUCCESS(rc))
    403374            {
    404375                VBoxClipboardWinClear();
    405376                VBoxClipboardWinClose();
    406377            }
    407             else
    408             {
    409                 LogFlowFunc(("WM_RENDERALLFORMATS: error in open clipboard. hwnd: %x, rc: %Rrc\n", hwnd, vboxrc));
    410             }
    411378        } break;
    412379
    413380        case VBOX_CLIPBOARD_WM_SET_FORMATS:
    414381        {
    415             if (pCtx->pClient == NULL || pCtx->pClient->fMsgFormats)
     382            if (   pCtx->pClient == NULL
     383                || pCtx->pClient->fHostMsgFormats)
    416384            {
    417385                /* Host has pending formats message. Ignore the guest announcement,
     
    423391
    424392            /* 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))
    431399            {
    432400                VBoxClipboardWinClear();
    433401
    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                {
    439409                    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                {
    442413                    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);
    451420                }
    452421
    453422#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 */
    460424#endif
    461425                VBoxClipboardWinClose();
     
    480444        {
    481445            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;
    488452}
    489453
     
    575539 * @param   pCtx                Clipboard context to synchronize.
    576540 */
    577 static int vboxClipboardSyncInternal(PVBOXCLIPBOARDCONTEXT pCtx)
     541static int vboxClipboardWinSyncInternal(PVBOXCLIPBOARDCONTEXT pCtx)
    578542{
    579543    AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
     
    663627{
    664628    /* Sync the host clipboard content with the client. */
    665     return vboxClipboardSyncInternal(pClient->pCtx);
     629    return vboxClipboardWinSyncInternal(pClient->pCtx);
    666630}
    667631
     
    783747        else if (u32Format & VBOX_SHARED_CLIPBOARD_FMT_HTML)
    784748        {
    785             UINT format = RegisterClipboardFormat("HTML Format");
     749            UINT format = RegisterClipboardFormat(VBOX_CLIPBOARD_WIN_REGFMT_HTML);
    786750            if (format != 0)
    787751            {
     
    792756                    if (lp != NULL)
    793757                    {
    794                         LogFunc(("CF_HTML\n"));
    795 
     758                        /** @todo r=andy Add data overflow handling. */
    796759                        vboxClipboardGetData(VBOX_SHARED_CLIPBOARD_FMT_HTML, lp, GlobalSize(hClip),
    797760                                             pv, cb, pcbActual);
     
    813776        {
    814777            hClip = GetClipboardData(CF_HDROP);
    815             if (hClip != NULL)
     778            if (hClip != NULL) /* Do we have data in CF_HDROP format? */
    816779            {
    817780                LPVOID lp = GlobalLock(hClip);
    818781                if (lp)
    819782                {
    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);
    919786                    if (RT_SUCCESS(rc))
    920787                    {
    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! */
    932789                        {
    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. */
    942792                        }
     793
     794                        memcpy(pv, pvTemp, cbTemp);
     795
     796                        RTMemFree(pvTemp);
     797
     798                        *pcbActual = (uint32_t)cbTemp;
    943799                    }
    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);
    950800
    951801                    GlobalUnlock(hClip);
     
    982832
    983833        if (   u32Format == VBOX_SHARED_CLIPBOARD_FMT_HTML
    984             && !IsWindowsHTML((const char*)pv))
     834            && !VBoxClipboardWinIsCFHTML((const char*)pv))
    985835        {
    986836            /* check that this is not already CF_HTML */
    987837            uint32_t cbResult;
    988             int rc = ConvertMimeToCFHTML((const char *)pv, cb, &pszResult, &cbResult);
     838            int rc = VBoxClipboardWinConvertMIMEToCFHTML((const char *)pv, cb, &pszResult, &cbResult);
    989839            if (RT_SUCCESS(rc))
    990840            {
     
    1015865}
    1016866
    1017 
    1018 /**
    1019  * Extracts field value from CF_HTML struct
    1020  *
    1021  * @returns VBox status code
    1022  * @param   pszSrc      source in CF_HTML format
    1023  * @param   pszOption   Name of CF_HTML field
    1024  * @param   puValue     Where to return extracted value of CF_HTML field
    1025  */
    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 struct
    1047  *
    1048  * @param   pszSource   source string.
    1049  *
    1050  * @returns @c true if the @a pszSource string is in CF_HTML format
    1051  */
    1052 static bool IsWindowsHTML(const char *pszSource)
    1053 {
    1054     return    RTStrStr(pszSource, "Version:") != NULL
    1055            && 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 type
    1063  *
    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 > 0
    1086                 && offEnd > 0
    1087                 && offEnd > offStart
    1088                 && 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                     else
    1102                     {
    1103                         LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected EndFragment. rc = %Rrc\n", rc));
    1104                         RTMemFree(pszResult);
    1105                     }
    1106                 }
    1107                 else
    1108                 {
    1109                     LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected EndFragment\n"));
    1110                     rc = VERR_NO_MEMORY;
    1111                 }
    1112             }
    1113             else
    1114             {
    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         else
    1120         {
    1121             LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected EndFragment. rc = %Rrc\n", rc));
    1122             rc = VERR_INVALID_PARAMETER;
    1123         }
    1124     }
    1125     else
    1126     {
    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 allocates
    1142  *
    1143  * Calculations:
    1144  *   Header length = format Length + (2*(10 - 5('%010d'))('digits')) - 2('%s') = format length + 8
    1145  *   EndHtml       = Header length + fragment length
    1146  *   StartHtml     = 105(constant)
    1147  *   StartFragment = 141(constant) may vary if the header html content will be extended
    1148  *   EndFragment   = Header length + fragment length - 38(ending length)
    1149  *
    1150  * @param   pszSource   Source buffer that contains utf-16 string in mime html format
    1151  * @param   cb          Size of source buffer in bytes
    1152  * @param   ppszOutput  Where to return the allocated output buffer to put converted UTF-8
    1153  *                      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 terminator
    1155  *
    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 char
    1179     @StartFragment - pos after <!--StartFragment-->
    1180     @EndFragment - pos before <!--EndFragment-->
    1181     @note: all values includes CR\LF inserted into text
    1182     Calculations:
    1183     Header length = format Length + (3*6('digits')) - 2('%s') = format length + 16 (control value - 183)
    1184     EndHtml  = Header length + fragment length
    1185     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 length
    1193     /*  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_STRICT
    1222     /* 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 #endif
    1234 
    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  
    8686
    8787#include "VBoxClipboard.h"
     88#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
     89# include "VBoxSharedClipboardSvc-uri.h"
     90#endif
    8891
    8992
     
    200203{
    201204    /* Message priority is taken into account. */
    202     if (pClient->fMsgQuit)
     205    if (pClient->fHostMsgQuit)
    203206    {
    204207        LogFlowFunc(("vboxSvcClipboardReturnMsg: Quit\n"));
    205208        VBoxHGCMParmUInt32Set(&paParms[0], VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT);
    206209        VBoxHGCMParmUInt32Set(&paParms[1], 0);
    207         pClient->fMsgQuit = false;
    208     }
    209     else if (pClient->fMsgReadData)
     210        pClient->fHostMsgQuit = false;
     211    }
     212    else if (pClient->fHostMsgReadData)
    210213    {
    211214        uint32_t fFormat = 0;
     
    218221        else if (pClient->u32RequestedFormat & VBOX_SHARED_CLIPBOARD_FMT_HTML)
    219222            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
    220227        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        }
    222232        pClient->u32RequestedFormat &= ~fFormat;
    223233        VBoxHGCMParmUInt32Set(&paParms[0], VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA);
    224234        VBoxHGCMParmUInt32Set(&paParms[1], fFormat);
    225235        if (pClient->u32RequestedFormat == 0)
    226             pClient->fMsgReadData = false;
    227     }
    228     else if (pClient->fMsgFormats)
     236            pClient->fHostMsgReadData = false;
     237    }
     238    else if (pClient->fHostMsgFormats)
    229239    {
    230240        LogFlowFunc(("vboxSvcClipboardReturnMsg: Formats %02X\n", pClient->u32AvailableFormats));
    231241        VBoxHGCMParmUInt32Set(&paParms[0], VBOX_SHARED_CLIPBOARD_HOST_MSG_REPORT_FORMATS);
    232242        VBoxHGCMParmUInt32Set(&paParms[1], pClient->u32AvailableFormats);
    233         pClient->fMsgFormats = false;
     243        pClient->fHostMsgFormats = false;
    234244    }
    235245    else
     
    255265            {
    256266                LogFlowFunc(("Quit\n"));
    257                 pClient->fMsgQuit = true;
     267                pClient->fHostMsgQuit = true;
    258268            } break;
    259269            case VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA:
     
    268278                LogFlowFunc(("ReadData %02X\n", u32Formats));
    269279                pClient->u32RequestedFormat = u32Formats;
    270                 pClient->fMsgReadData = true;
     280                pClient->fHostMsgReadData = true;
    271281            } break;
    272282            case VBOX_SHARED_CLIPBOARD_HOST_MSG_REPORT_FORMATS:
     
    281291                LogFlowFunc(("Formats %02X\n", u32Formats));
    282292                pClient->u32AvailableFormats = u32Formats;
    283                 pClient->fMsgFormats = true;
     293                pClient->fHostMsgFormats = true;
    284294            } break;
    285295            default:
     
    683693        default:
    684694        {
     695#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
     696            rc = vboxClipboardSvcURIHandler(u32ClientID, pvClient, u32Function, cParms, paParms, tsArrival,
     697                                            &fAsynchronousProcessing);
     698#else
    685699            rc = VERR_NOT_IMPLEMENTED;
     700#endif
    686701        }
    687702    }
     
    772787
    773788        default:
    774             break;
     789        {
     790#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
     791            rc = vboxClipboardSvcURIHostHandler(u32Function, cParms, paParms);
     792#endif
     793        } break;
    775794    }
    776795
     
    786805{
    787806    SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTDATA, u32ClientID),  /* for validation purposes */
    788     SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTDATA, fMsgQuit),
    789     SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTDATA, fMsgReadData),
    790     SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTDATA, fMsgFormats),
     807    SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTDATA, fHostMsgQuit),
     808    SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTDATA, fHostMsgReadData),
     809    SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTDATA, fHostMsgFormats),
    791810    SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTDATA, u32RequestedFormat),
    792811    SSMFIELD_ENTRY_TERM()
     
    843862    bool fAsync: 1; /* Guest is waiting for a message. */
    844863
    845     bool fMsgQuit: 1;
    846     bool fMsgReadData: 1;
    847     bool fMsgFormats: 1;
     864    bool fHostMsgQuit: 1;
     865    bool fHostMsgReadData: 1;
     866    bool fHostMsgFormats: 1;
    848867
    849868    struct
     
    918937        AssertRCReturn(rc, rc);
    919938
    920         pClient->fMsgQuit           = savedState.fMsgQuit;
    921         pClient->fMsgReadData       = savedState.fMsgReadData;
    922         pClient->fMsgFormats        = savedState.fMsgFormats;
     939        pClient->fHostMsgQuit       = savedState.fHostMsgQuit;
     940        pClient->fHostMsgReadData   = savedState.fHostMsgReadData;
     941        pClient->fHostMsgFormats    = savedState.fHostMsgFormats;
    923942        pClient->u32RequestedFormat = savedState.u32RequestedFormat;
    924943    }
Note: See TracChangeset for help on using the changeset viewer.

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