VirtualBox

Ignore:
Timestamp:
Jun 19, 2023 9:11:37 AM (18 months ago)
Author:
vboxsync
Message:

Shared Clipboard: Unified root list entry code to also use the generic list entry code, a lot of updates for the cross OS transfer handling code, more updates for HTTP server transfer handling.

This also changed the handling of how that transfers are being initiated, as we needed to have this for X11: Before, transfers were initiated as soon as on side announced the URI list format -- now we postpone initiating the transfer until the receiving side requests the data as URI list.

bugref:9437

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/GuestHost/SharedClipboard/clipboard-win.cpp

    r98103 r100204  
    2626 */
    2727
    28 #define LOG_GROUP LOG_GROUP_SHARED_CLIPBOARD
    2928#include <VBox/GuestHost/SharedClipboard.h>
    3029
     
    4039#endif
    4140
     41#ifdef LOG_GROUP
     42# undef LOG_GROUP
     43#endif
     44#define LOG_GROUP LOG_GROUP_SHARED_CLIPBOARD
    4245#include <VBox/log.h>
    4346
     
    4851#include <VBox/GuestHost/SharedClipboard-win.h>
    4952#include <VBox/GuestHost/clipboard-helper.h>
     53
     54
     55#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
     56int SharedClipboardWinTransferDropFilesToStringList(DROPFILES *pDropFiles, char **ppszList, uint32_t *pcbList);
     57#endif
    5058
    5159
     
    833841 * a separate WM_RENDERFORMAT message.
    834842 *
    835  * @returns VBox status code. VERR_NOT_SUPPORTED if the format is not supported / handled.
     843 * @returns VBox status code.
     844 * @retval  VERR_NOT_SUPPORTED if *all* format(s) is/are not supported / handled.
    836845 * @param   pWinCtx             Windows context to use.
    837846 * @param   fFormats            Clipboard format(s) to announce.
     
    841850    LogFunc(("fFormats=0x%x\n", fFormats));
    842851
     852    /* Make sure that if VBOX_SHCL_FMT_URI_LIST is announced, we don't announced anything else.
     853     * This otherwise this will trigger a WM_DRAWCLIPBOARD or friends, which will result in fun bugs coming up. */
     854    AssertReturn((  !(fFormats & VBOX_SHCL_FMT_URI_LIST)
     855                  || (fFormats & VBOX_SHCL_FMT_URI_LIST) == VBOX_SHCL_FMT_URI_LIST), VERR_INVALID_PARAMETER);
    843856    /*
    844857     * Set the clipboard formats.
     
    846859    static struct
    847860    {
     861        /** VBox format to handle. */
    848862        uint32_t        fVBoxFormat;
     863        /** Native Windows format to use.
     864         *  Set to 0 if unused / needs special handling. */
    849865        UINT            uWinFormat;
    850         const char     *pszWinFormat;
     866        /** Own registered format. Set to NULL if not used / applicable. */
     867        const char     *pszRegFormat;
    851868        const char     *pszLog;
    852869    } s_aFormats[] =
    853870    {
    854871        { VBOX_SHCL_FMT_UNICODETEXT,    CF_UNICODETEXT, NULL,                 "CF_UNICODETEXT" },
     872#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
     873        /* We don't announce anything here for an URI list to the Windows clipboard, as we later have to
     874         * initialize our custom IDataObject and set it via OleSetClipboard(). */
     875        { VBOX_SHCL_FMT_URI_LIST,       0,              NULL,                 "SHCL_URI_LIST" },
     876#endif
    855877        { VBOX_SHCL_FMT_BITMAP,         CF_DIB,         NULL,                 "CF_DIB" },
    856         { VBOX_SHCL_FMT_HTML,           0,              SHCL_WIN_REGFMT_HTML, "SHCL_WIN_REGFMT_HTML" },
     878        { VBOX_SHCL_FMT_HTML,           0,              SHCL_WIN_REGFMT_HTML, "SHCL_WIN_REGFMT_HTML" }
    857879    };
     880
    858881    unsigned    cSuccessfullySet = 0;
    859882    SHCLFORMATS fFormatsLeft     = fFormats;
     
    863886        if (fFormatsLeft & s_aFormats[i].fVBoxFormat)
    864887        {
    865             LogFunc(("%s\n", s_aFormats[i].pszLog));
     888            LogRel2(("Shared Clipboard: Announcing format '%s' to clipboard\n", s_aFormats[i].pszLog));
    866889            fFormatsLeft &= ~s_aFormats[i].fVBoxFormat;
    867890
    868             /* Reg format if needed: */
    869             UINT uWinFormat = s_aFormats[i].uWinFormat;
     891            UINT uWinFormat = 0;
     892            if (s_aFormats[i].pszRegFormat) /* See if we have (special) registered format. */
     893            {
     894                uWinFormat = RegisterClipboardFormat(s_aFormats[i].pszRegFormat);
     895                AssertContinue(uWinFormat != 0);
     896            }
     897            else /* Native format. */
     898                uWinFormat = s_aFormats[i].uWinFormat;
     899
     900            /* Any native format set? If not, just skip it (as successful). */
    870901            if (!uWinFormat)
    871902            {
    872                 uWinFormat = RegisterClipboardFormat(s_aFormats[i].pszWinFormat);
    873                 AssertContinue(uWinFormat != 0);
     903                cSuccessfullySet++;
     904                continue;
    874905            }
    875906
     
    903934    else if (RT_SUCCESS(rc) && fFormatsLeft != 0)
    904935    {
    905         LogFunc(("Unsupported formats: %#x (%#x)\n", fFormatsLeft, fFormats));
     936        LogRel(("Shared Clipboard: Unable to announce unsupported/invalid formats: %#x (%#x)\n", fFormatsLeft, fFormats));
    906937        rc = VERR_NOT_SUPPORTED;
    907938    }
     
    917948 * a separate WM_RENDERFORMAT message.
    918949 *
    919  * @returns VBox status code. VERR_NOT_SUPPORTED if the format is not supported / handled.
     950 * @returns VBox status code.
    920951 * @param   pWinCtx     Windows context to use.
    921952 * @param   fFormats    Clipboard format(s) to announce.
     
    10031034
    10041035#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
    1005 
    1006 /**
    1007  * Creates an Shared Clipboard transfer by announcing transfer data  (via IDataObject) to Windows.
     1036/**
     1037 * Creates an Shared Clipboard transfer by announcing transfer data (via IDataObject) to Windows.
    10081038 *
    10091039 * This creates the necessary IDataObject + IStream implementations and initiates the actual transfers required for getting
     
    10121042 * @returns VBox status code.
    10131043 * @param   pWinCtx             Windows context to use.
    1014  * @param   pTransferCtxCtx     Transfer contextto use.
    1015  * @param   pTransfer           Shared Clipboard transfer to use.
    1016  */
    1017 int SharedClipboardWinTransferCreate(PSHCLWINCTX pWinCtx, PSHCLTRANSFER pTransfer)
    1018 {
    1019     AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
    1020 
    1021     LogFlowFunc(("pWinCtx=%p\n", pWinCtx));
    1022 
    1023     AssertReturn(pTransfer->pvUser == NULL, VERR_WRONG_ORDER);
     1044 * @param   pCtx                Shared Clipboard context to use.
     1045 *                              Needed for the data object to communicate with the main window thread.
     1046 * @param   pCallbacks          Callbacks table to use.
     1047 */
     1048int SharedClipboardWinTransferCreateAndSetDataObject(PSHCLWINCTX pWinCtx, PSHCLCONTEXT pCtx, PSHCLCALLBACKS pCallbacks)
     1049{
     1050    AssertPtrReturn(pWinCtx, VERR_INVALID_POINTER);
     1051    AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
     1052    AssertPtrReturn(pCallbacks, VERR_INVALID_POINTER);
    10241053
    10251054    /* Make sure to enter the critical section before setting the clipboard data, as otherwise WM_CLIPBOARDUPDATE
     
    10281057    if (RT_SUCCESS(rc))
    10291058    {
     1059        if (pWinCtx->pDataObjInFlight == NULL)
     1060        {
     1061            SharedClipboardWinDataObject *pObj = new SharedClipboardWinDataObject();
     1062            if (pObj)
     1063            {
     1064                rc = pObj->Init(pCtx);
     1065                if (RT_SUCCESS(rc))
     1066                {
     1067                    if (RT_SUCCESS(rc))
     1068                        pObj->SetCallbacks(pCallbacks);
     1069
     1070                    if (RT_SUCCESS(rc))
     1071                        pWinCtx->pDataObjInFlight = pObj;
     1072                }
     1073            }
     1074            else
     1075                rc = VERR_NO_MEMORY;
     1076        }
     1077
     1078        if (RT_SUCCESS(rc))
     1079        {
     1080            SharedClipboardWinClose();
     1081            /* Note: Clipboard must be closed first before calling OleSetClipboard(). */
     1082
     1083            /** @todo There is a potential race between SharedClipboardWinClose() and OleSetClipboard(),
     1084             *        where another application could own the clipboard (open), and thus the call to
     1085             *        OleSetClipboard() will fail. Needs (better) fixing. */
     1086            HRESULT hr = S_OK;
     1087
     1088            for (unsigned uTries = 0; uTries < 3; uTries++)
     1089            {
     1090                hr = OleSetClipboard(pWinCtx->pDataObjInFlight);
     1091                if (SUCCEEDED(hr))
     1092                {
     1093                    Assert(OleIsCurrentClipboard(pWinCtx->pDataObjInFlight) == S_OK); /* Sanity. */
     1094
     1095                    /*
     1096                     * Calling OleSetClipboard() changed the clipboard owner, which in turn will let us receive
     1097                     * a WM_CLIPBOARDUPDATE message. To not confuse ourselves with our own clipboard owner changes,
     1098                     * save a new window handle and deal with it in WM_CLIPBOARDUPDATE.
     1099                     */
     1100                    pWinCtx->hWndClipboardOwnerUs = GetClipboardOwner();
     1101
     1102                    LogFlowFunc(("hWndClipboardOwnerUs=%p\n", pWinCtx->hWndClipboardOwnerUs));
     1103                    break;
     1104                }
     1105
     1106                LogFlowFunc(("Failed with %Rhrc (try %u/3)\n", hr, uTries + 1));
     1107                RTThreadSleep(500); /* Wait a bit. */
     1108            }
     1109
     1110            if (FAILED(hr))
     1111            {
     1112                rc = VERR_ACCESS_DENIED; /** @todo Fudge; fix this. */
     1113                LogRel(("Shared Clipboard: Failed with %Rhrc when setting data object to clipboard\n", hr));
     1114            }
     1115        }
     1116
     1117        int rc2 = RTCritSectLeave(&pWinCtx->CritSect);
     1118        AssertRC(rc2);
     1119    }
     1120
     1121    LogFlowFuncLeaveRC(rc);
     1122    return rc;
     1123}
     1124
     1125#if 0
     1126/**
     1127 * Creates an Shared Clipboard transfer by announcing transfer data  (via IDataObject) to Windows.
     1128 *
     1129 * This creates the necessary IDataObject + IStream implementations and initiates the actual transfers required for getting
     1130 * the meta data. Whether or not the actual (file++) transfer(s) are happening is up to the user (at some point) later then.
     1131 *
     1132 * @returns VBox status code.
     1133 * @param   pWinCtx             Windows context to use.
     1134 * @param   pTransferCtxCtx     Transfer contextto use.
     1135 * @param   pTransfer           Shared Clipboard transfer to use.
     1136 */
     1137int SharedClipboardWinTransferCreate(PSHCLWINCTX pWinCtx, PSHCLTRANSFER pTransfer)
     1138{
     1139    AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
     1140
     1141    LogFlowFunc(("pWinCtx=%p\n", pWinCtx));
     1142
     1143    AssertReturn(pTransfer->pvUser == NULL, VERR_WRONG_ORDER);
     1144
     1145    /* Make sure to enter the critical section before setting the clipboard data, as otherwise WM_CLIPBOARDUPDATE
     1146     * might get called *before* we had the opportunity to set pWinCtx->hWndClipboardOwnerUs below. */
     1147    int rc = RTCritSectEnter(&pWinCtx->CritSect);
     1148    if (RT_SUCCESS(rc))
     1149    {
    10301150        SharedClipboardWinTransferCtx *pWinURITransferCtx = new SharedClipboardWinTransferCtx();
    10311151        if (pWinURITransferCtx)
     
    10341154            pTransfer->cbUser = sizeof(SharedClipboardWinTransferCtx);
    10351155
    1036             pWinURITransferCtx->pDataObj = new SharedClipboardWinDataObject(pTransfer);
     1156            pWinURITransferCtx->pDataObj = new SharedClipboardWinDataObject();
    10371157            if (pWinURITransferCtx->pDataObj)
    10381158            {
    1039                 rc = pWinURITransferCtx->pDataObj->Init();
     1159                rc = pWinURITransferCtx->pDataObj->Init(pCtx);
    10401160                if (RT_SUCCESS(rc))
    10411161                {
     
    10901210    return rc;
    10911211}
     1212#endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
    10921213
    10931214/**
     
    11331254 * @param   pTransfer           Transfer to get roots for.
    11341255 */
    1135 int SharedClipboardWinGetRoots(PSHCLWINCTX pWinCtx, PSHCLTRANSFER pTransfer)
     1256int SharedClipboardWinTransferGetRootsFromClipboard(PSHCLWINCTX pWinCtx, PSHCLTRANSFER pTransfer)
    11361257{
    11371258    AssertPtrReturn(pWinCtx,   VERR_INVALID_POINTER);
     
    11511272            if (hDrop)
    11521273            {
    1153                 char    *papszList = NULL;
     1274                char    *pszList = NULL;
    11541275                uint32_t cbList;
    1155                 rc = SharedClipboardWinDropFilesToStringList((DROPFILES *)hDrop, &papszList, &cbList);
     1276                rc = SharedClipboardWinTransferDropFilesToStringList((DROPFILES *)hDrop, &pszList, &cbList);
    11561277
    11571278                GlobalUnlock(hClip);
     
    11591280                if (RT_SUCCESS(rc))
    11601281                {
    1161                     rc = ShClTransferRootsSet(pTransfer,
    1162                                               papszList, cbList + 1 /* Include termination */);
    1163                     RTStrFree(papszList);
     1282                    rc = ShClTransferRootsInitFromStringList(pTransfer, pszList, cbList);
     1283                    RTStrFree(pszList);
    11641284                }
    11651285            }
     
    11791299
    11801300/**
    1181  * Converts a DROPFILES (HDROP) structure to a string list, separated by \r\n.
     1301 * Converts a DROPFILES (HDROP) structure to a string list, separated by SHCL_TRANSFER_URI_LIST_SEP_STR.
    11821302 * Does not do any locking on the input data.
    11831303 *
    11841304 * @returns VBox status code.
    11851305 * @param   pDropFiles          Pointer to DROPFILES structure to convert.
    1186  * @param   papszList           Where to store the allocated string list.
     1306 * @param   ppszList            Where to store the allocated string list on success.
     1307 *                              Needs to be free'd with RTStrFree().
    11871308 * @param   pcbList             Where to store the size (in bytes) of the allocated string list.
    1188  */
    1189 int SharedClipboardWinDropFilesToStringList(DROPFILES *pDropFiles, char **papszList, uint32_t *pcbList)
     1309 *                              Includes zero terminator.
     1310 */
     1311int SharedClipboardWinTransferDropFilesToStringList(DROPFILES *pDropFiles, char **ppszList, uint32_t *pcbList)
    11901312{
    11911313    AssertPtrReturn(pDropFiles, VERR_INVALID_POINTER);
    1192     AssertPtrReturn(papszList,  VERR_INVALID_POINTER);
     1314    AssertPtrReturn(ppszList,   VERR_INVALID_POINTER);
    11931315    AssertPtrReturn(pcbList,    VERR_INVALID_POINTER);
    11941316
     
    12931415        /* Add separation between filenames.
    12941416         * Note: Also do this for the last element of the list. */
    1295         rc = RTStrAAppendExN(&pszFiles, 1 /* cPairs */, "\r\n", 2 /* Bytes */);
     1417        rc = RTStrAAppendExN(&pszFiles, 1 /* cPairs */, SHCL_TRANSFER_URI_LIST_SEP_STR, 2 /* Bytes */);
    12961418        if (RT_SUCCESS(rc))
    1297             cchFiles += 2; /* Include \r\n */
     1419            cchFiles += 2; /* Include SHCL_TRANSFER_URI_LIST_SEP_STR */
    12981420    }
    12991421
     
    13061428                     cFiles, cchFiles, cbFiles, pszFiles));
    13071429
    1308         *papszList = pszFiles;
     1430        *ppszList = pszFiles;
    13091431        *pcbList   = cbFiles;
    13101432    }
     
    13181440    return rc;
    13191441}
    1320 
    13211442#endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
    13221443
Note: See TracChangeset for help on using the changeset viewer.

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