VirtualBox

Changeset 81269 in vbox


Ignore:
Timestamp:
Oct 14, 2019 6:28:34 PM (5 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
133964
Message:

Shared Clipboard/Transfers: Implemented transfer cancellation support for the Windows shell.

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/GuestHost/SharedClipboard-win.h

    r81259 r81269  
    170170    enum Status
    171171    {
     172        /** The object is uninitialized (not ready). */
    172173        Uninitialized = 0,
    173         Initialized
     174        /** The object is initialized and ready to use. */
     175        Initialized,
     176        /** The operation has been successfully completed. */
     177        Completed,
     178        /** The operation has been canceled. */
     179        Canceled,
     180        /** An (unrecoverable) error occurred. */
     181        Error
    174182    };
    175183
     
    218226    static DECLCALLBACK(int) readThread(RTTHREAD ThreadSelf, void *pvUser);
    219227
    220     static const char* ClipboardFormatToString(CLIPFORMAT fmt);
     228    static void logFormat(CLIPFORMAT fmt);
    221229
    222230protected:
     
    249257    typedef std::vector<FSOBJENTRY> FsObjEntryList;
    250258
     259    /** The object's current status. */
    251260    Status                      m_enmStatus;
     261    /** The object's current reference count. */
    252262    LONG                        m_lRefCount;
     263    /** How many formats have been registered. */
    253264    ULONG                       m_cFormats;
    254265    LPFORMATETC                 m_pFormatEtc;
    255266    LPSTGMEDIUM                 m_pStgMedium;
     267    /** Pointer to the associated transfer object being handled. */
    256268    PSHCLTRANSFER               m_pTransfer;
     269    /** Current stream object being used. */
    257270    IStream                    *m_pStream;
     271    /** Current object index being handled by the data object.
     272     *  This is needed to create the next IStream object for e.g. the next upcoming file/dir/++ in the transfer. */
    258273    ULONG                       m_uObjIdx;
    259274    /** List of (cached) file system objects. */
     
    265280    /** Event being triggered when the transfer has been completed. */
    266281    RTSEMEVENT                  m_EventTransferComplete;
     282    /** Registered format for CFSTR_FILEDESCRIPTORA. */
    267283    UINT                        m_cfFileDescriptorA;
     284    /** Registered format for CFSTR_FILEDESCRIPTORW. */
    268285    UINT                        m_cfFileDescriptorW;
     286    /** Registered format for CFSTR_FILECONTENTS. */
    269287    UINT                        m_cfFileContents;
     288    /** Registered format for CFSTR_PERFORMEDDROPEFFECT. */
     289    UINT                        m_cfPerformedDropEffect;
    270290};
    271291
  • trunk/src/VBox/GuestHost/SharedClipboard/ClipboardDataObjectImpl-win.cpp

    r81260 r81269  
    5858    HRESULT hr;
    5959
    60     ULONG cFixedFormats = 2; /* CFSTR_FILEDESCRIPTORA + CFSTR_FILECONTENTS */
     60    ULONG cFixedFormats = 3; /* CFSTR_FILEDESCRIPTORA + CFSTR_FILECONTENTS + CFSTR_PERFORMEDDROPEFFECT */
    6161#ifdef VBOX_CLIPBOARD_WITH_UNICODE_SUPPORT
    6262    cFixedFormats++; /* CFSTR_FILEDESCRIPTORW */
     
    9292        registerFormat(&m_pFormatEtc[uIdx++], m_cfFileContents, TYMED_ISTREAM, 0 /* lIndex */);
    9393
     94        /* We want to know from the target what the outcome of the operation was to react accordingly (e.g. abort a transfer). */
     95        LogFlowFunc(("Registering CFSTR_PERFORMEDDROPEFFECT ...\n"));
     96        m_cfPerformedDropEffect = RegisterClipboardFormat(CFSTR_PERFORMEDDROPEFFECT);
     97        registerFormat(&m_pFormatEtc[uIdx++], m_cfPerformedDropEffect, TYMED_HGLOBAL, -1 /* lIndex */, DVASPECT_CONTENT);
     98
    9499        /*
    95100         * Registration of dynamic formats needed?
     
    403408                    AssertRC(rc2);
    404409
    405                     LogRel2(("Shared Clipboard: Transfer complete\n"));
     410                    switch (pThis->m_enmStatus)
     411                    {
     412                        case Completed:
     413                            LogRel2(("Shared Clipboard: Transfer complete\n"));
     414                            break;
     415
     416                        case Canceled:
     417                            LogRel2(("Shared Clipboard: Transfer canceled\n"));
     418                            break;
     419
     420                        case Error:
     421                            LogRel2(("Shared Clipboard: Transfer error occurred\n"));
     422                            break;
     423
     424                        default:
     425                            break;
     426                    }
    406427                }
    407428                else
     
    650671        }
    651672    }
     673    else if (pFormatEtc->cfFormat == m_cfPerformedDropEffect)
     674    {
     675        HGLOBAL hGlobal = GlobalAlloc(GHND, sizeof(DWORD));
     676
     677        DWORD* pdwDropEffect = (DWORD*)GlobalLock(hGlobal);
     678        *pdwDropEffect = DROPEFFECT_COPY;
     679
     680        GlobalUnlock(hGlobal);
     681
     682        pMedium->tymed          = TYMED_HGLOBAL;
     683        pMedium->hGlobal        = hGlobal;
     684        pMedium->pUnkForRelease = NULL;
     685    }
    652686
    653687    if (   FAILED(hr)
     
    686720{
    687721    LogFlowFunc(("\n"));
    688     return (lookupFormatEtc(pFormatEtc, NULL /* puIndex */)) ? S_OK : DV_E_FORMATETC;
     722    return lookupFormatEtc(pFormatEtc, NULL /* puIndex */) ? S_OK : DV_E_FORMATETC;
    689723}
    690724
     
    701735STDMETHODIMP SharedClipboardWinDataObject::SetData(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium, BOOL fRelease)
    702736{
    703     RT_NOREF(pFormatEtc, pMedium, fRelease);
    704     LogFlowFunc(("\n"));
     737    if (   pFormatEtc == NULL
     738        || pMedium    == NULL)
     739        return E_INVALIDARG;
     740
     741    if (pFormatEtc->lindex != -1)
     742        return DV_E_LINDEX;
     743
     744    if (pFormatEtc->tymed != TYMED_HGLOBAL)
     745        return DV_E_TYMED;
     746
     747    if (pFormatEtc->dwAspect != DVASPECT_CONTENT)
     748        return DV_E_DVASPECT;
     749
     750    LogFlowFunc(("cfFormat=%RU16, lookupFormatEtc=%RTbool\n",
     751                 pFormatEtc->cfFormat, lookupFormatEtc(pFormatEtc, NULL /* puIndex */)));
     752
     753    /* CFSTR_PERFORMEDDROPEFFECT is used by the drop target (caller of this IDataObject) to communicate
     754     * the outcome of the overall operation. */
     755    if (   pFormatEtc->cfFormat == m_cfPerformedDropEffect
     756        && pMedium->tymed       == TYMED_HGLOBAL)
     757    {
     758        DWORD dwEffect = *(DWORD *)GlobalLock(pMedium->hGlobal);
     759        GlobalUnlock(pMedium->hGlobal);
     760
     761        LogFlowFunc(("dwEffect=%RI32\n", dwEffect));
     762
     763        /* Did the user cancel the operation via UI (shell)? This also might happen when overwriting an existing file
     764         * and the user doesn't want to allow this. */
     765        if (dwEffect == DROPEFFECT_NONE)
     766        {
     767            LogRel2(("Shared Clipboard: Transfer canceled by user interaction\n"));
     768
     769            OnTransferCanceled();
     770        }
     771        /** @todo Detect move / overwrite actions here. */
     772
     773        if (fRelease)
     774            ReleaseStgMedium(pMedium);
     775
     776        return S_OK;
     777    }
    705778
    706779    return E_NOTIMPL;
     
    791864    LogFlowFunc(("m_uObjIdx=%RU32 (total: %zu)\n", m_uObjIdx, m_lstEntries.size()));
    792865
    793     const bool fComplete = m_uObjIdx == m_lstEntries.size() - 1 /* Object index is zero-based */;
    794     if (fComplete)
    795     {
    796         if (m_EventTransferComplete != NIL_RTSEMEVENT)
    797         {
    798             int rc2 = RTSemEventSignal(m_EventTransferComplete);
    799             AssertRC(rc2);
    800         }
    801     }
    802 
    803     LogFlowFuncLeaveRC(rc);
    804 }
    805 
    806 void SharedClipboardWinDataObject::OnTransferCanceled(void)
    807 {
    808     LogFlowFuncEnter();
     866    if (RT_SUCCESS(rc))
     867    {
     868        const bool fComplete = m_uObjIdx == m_lstEntries.size() - 1 /* Object index is zero-based */;
     869        if (fComplete)
     870        {
     871            m_enmStatus = Completed;
     872        }
     873        else
     874            AssertFailed();
     875    }
     876    else
     877        m_enmStatus = Error;
    809878
    810879    if (m_EventTransferComplete != NIL_RTSEMEVENT)
     
    814883    }
    815884
     885    LogFlowFuncLeaveRC(rc);
     886}
     887
     888void SharedClipboardWinDataObject::OnTransferCanceled(void)
     889{
     890    LogFlowFuncEnter();
     891
     892    m_enmStatus = Canceled;
     893
     894    if (m_EventTransferComplete != NIL_RTSEMEVENT)
     895    {
     896        int rc2 = RTSemEventSignal(m_EventTransferComplete);
     897        AssertRC(rc2);
     898    }
     899
    816900    LogFlowFuncLeave();
    817901}
    818902
    819903/* static */
    820 const char* SharedClipboardWinDataObject::ClipboardFormatToString(CLIPFORMAT fmt)
    821 {
    822 #if 0
     904void SharedClipboardWinDataObject::logFormat(CLIPFORMAT fmt)
     905{
    823906    char szFormat[128];
    824907    if (GetClipboardFormatName(fmt, szFormat, sizeof(szFormat)))
    825         LogFlowFunc(("wFormat=%RI16, szName=%s\n", fmt, szFormat));
    826 #endif
    827 
    828     switch (fmt)
    829     {
    830 
    831     case 1:
    832         return "CF_TEXT";
    833     case 2:
    834         return "CF_BITMAP";
    835     case 3:
    836         return "CF_METAFILEPICT";
    837     case 4:
    838         return "CF_SYLK";
    839     case 5:
    840         return "CF_DIF";
    841     case 6:
    842         return "CF_TIFF";
    843     case 7:
    844         return "CF_OEMTEXT";
    845     case 8:
    846         return "CF_DIB";
    847     case 9:
    848         return "CF_PALETTE";
    849     case 10:
    850         return "CF_PENDATA";
    851     case 11:
    852         return "CF_RIFF";
    853     case 12:
    854         return "CF_WAVE";
    855     case 13:
    856         return "CF_UNICODETEXT";
    857     case 14:
    858         return "CF_ENHMETAFILE";
    859     case 15:
    860         return "CF_HDROP";
    861     case 16:
    862         return "CF_LOCALE";
    863     case 17:
    864         return "CF_DIBV5";
    865     case 18:
    866         return "CF_MAX";
    867     case 49158:
    868         return "FileName";
    869     case 49159:
    870         return "FileNameW";
    871     case 49161:
    872         return "DATAOBJECT";
    873     case 49171:
    874         return "Ole Private Data";
    875     case 49314:
    876         return "Shell Object Offsets";
    877     case 49316:
    878         return "File Contents";
    879     case 49317:
    880         return "File Group Descriptor";
    881     case 49323:
    882         return "Preferred Drop Effect";
    883     case 49380:
    884         return "Shell Object Offsets";
    885     case 49382:
    886         return "FileContents";
    887     case 49383:
    888         return "FileGroupDescriptor";
    889     case 49389:
    890         return "Preferred DropEffect";
    891     case 49268:
    892         return "Shell IDList Array";
    893     case 49619:
    894         return "RenPrivateFileAttachments";
    895     default:
    896         break;
    897     }
    898 
    899     return "unknown";
     908    {
     909        LogFlowFunc(("clipFormat=%RI16 -> %s\n", fmt, szFormat));
     910    }
     911    else
     912        LogFlowFunc(("clipFormat=%RI16 is unknown\n", fmt));
    900913}
    901914
     
    912925            //&& pFormatEtc->dwAspect == m_pFormatEtc[i].dwAspect)
    913926        {
    914             LogRel3(("Shared Clipboard: Format found: tyMed=%RI32, cfFormat=%RI16, sFormats=%s, dwAspect=%RI32, ulIndex=%RU32\n",
    915                       pFormatEtc->tymed, pFormatEtc->cfFormat, SharedClipboardWinDataObject::ClipboardFormatToString(m_pFormatEtc[i].cfFormat),
    916                       pFormatEtc->dwAspect, i));
     927            LogRel2(("Shared Clipboard: Format found: tyMed=%RI32, cfFormat=%RI16, dwAspect=%RI32, ulIndex=%RU32\n",
     928                     pFormatEtc->tymed, pFormatEtc->cfFormat, pFormatEtc->dwAspect, i));
    917929            if (puIndex)
    918930                *puIndex = i;
     
    921933    }
    922934
    923     LogRel3(("Shared Clipboard: Format NOT found: tyMed=%RI32, cfFormat=%RI16, sFormats=%s, dwAspect=%RI32\n",
    924              pFormatEtc->tymed, pFormatEtc->cfFormat, SharedClipboardWinDataObject::ClipboardFormatToString(pFormatEtc->cfFormat),
    925              pFormatEtc->dwAspect));
     935    LogRel2(("Shared Clipboard: Format NOT found: tyMed=%RI32, cfFormat=%RI16, dwAspect=%RI32\n",
     936             pFormatEtc->tymed, pFormatEtc->cfFormat, pFormatEtc->dwAspect));
     937
     938    logFormat(pFormatEtc->cfFormat);
    926939
    927940    return false;
     
    940953    pFormatEtc->ptd      = pTargetDevice;
    941954
    942     LogFlowFunc(("Registered format=%ld, sFormat=%s\n",
    943                  pFormatEtc->cfFormat, SharedClipboardWinDataObject::ClipboardFormatToString(pFormatEtc->cfFormat)));
    944 }
    945 
     955    LogFlowFunc(("Registered format=%ld\n", pFormatEtc->cfFormat));
     956
     957    logFormat(pFormatEtc->cfFormat);
     958}
     959
  • trunk/src/VBox/GuestHost/SharedClipboard/ClipboardEnumFormatEtcImpl-win.cpp

    r80664 r81269  
    4444        for (ULONG i = 0; i < cFormats; i++)
    4545        {
    46             LogFlowFunc(("Format %RU32: cfFormat=%RI16, sFormat=%s, tyMed=%RU32, dwAspect=%RU32\n",
    47                          i, pFormatEtc[i].cfFormat, SharedClipboardWinDataObject::ClipboardFormatToString(pFormatEtc[i].cfFormat),
    48                          pFormatEtc[i].tymed, pFormatEtc[i].dwAspect));
     46            LogFlowFunc(("Format %RU32: cfFormat=%RI16, tyMed=%RU32, dwAspect=%RU32\n",
     47                         i, pFormatEtc[i].cfFormat, pFormatEtc[i].tymed, pFormatEtc[i].dwAspect));
     48
     49            SharedClipboardWinDataObject::logFormat(pFormatEtc[i].cfFormat);
     50
    4951            SharedClipboardWinEnumFormatEtc::CopyFormat(&m_pFormatEtc[i], &pFormatEtc[i]);
    5052        }
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