VirtualBox

Changeset 78474 in vbox


Ignore:
Timestamp:
May 13, 2019 7:44:15 AM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
130509
Message:

Shared Clipboard/URI: Update.

Location:
trunk
Files:
7 edited

Legend:

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

    r78440 r78474  
    3333#include <iprt/win/windows.h>
    3434
     35#include <VBox/GuestHost/SharedClipboard.h>
     36
    3537# ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
    3638#  include <iprt/cpp/ministring.h> /* For RTCString. */
     39#  include <oleidl.h>
    3740# endif
    3841
     
    4144#endif
    4245
    43 #define VBOX_CLIPBOARD_WNDCLASS_NAME        "VBoxSharedClipboardClass"
    44 
    45 #define VBOX_CLIPBOARD_WIN_REGFMT_HTML      "VBox HTML Format"
     46#define VBOX_CLIPBOARD_WNDCLASS_NAME         "VBoxSharedClipboardClass"
     47
     48/** See: https://docs.microsoft.com/en-us/windows/desktop/dataxchg/html-clipboard-format
     49 *       Do *not* change the name, as this will break compatbility with other (legacy) applications! */
     50#define VBOX_CLIPBOARD_WIN_REGFMT_HTML       "HTML Format"
     51# ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
     52#  define VBOX_CLIPBOARD_WIN_REGFMT_URI_LIST "VBoxURIList"
     53#endif
    4654
    4755/** Default timeout (in ms) for passing down messages down the clipboard chain. */
     
    8088    bool                   fCBChainPingInProcess;
    8189} VBOXCLIPBOARDWINAPIOLD, *PVBOXCLIPBOARDWINAPIOLD;
     90
     91#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
     92class VBoxClipboardWinDataObject;
     93
     94/**
     95 * Structure for keeping URI clipboard information around.
     96 */
     97typedef struct _VBOXCLIPBOARDWINURI
     98{
     99    UINT cfFileGroupDescriptor;
     100    UINT cfFileContents;
     101    VBoxClipboardWinDataObject *pDataObj;
     102} VBOXCLIPBOARDWINURI, *PVBOXCLIPBOARDWINURI;
     103#endif
    82104
    83105typedef struct VBOXCLIPBOARDWINCTX
     
    91113    /** Structure for maintaining the old clipboard API. */
    92114    VBOXCLIPBOARDWINAPIOLD oldAPI;
     115#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
     116    /** Structure for keeping URI clipboard information around. */
     117    VBOXCLIPBOARDWINURI    URI;
     118#endif
    93119} VBOXCLIPBOARDWINCTX, *PVBOXCLIPBOARDWINCTX;
    94120
     
    101127int VBoxClipboardWinRemoveFromCBChain(PVBOXCLIPBOARDWINCTX pCtx);
    102128VOID CALLBACK VBoxClipboardWinChainPingProc(HWND hWnd, UINT uMsg, ULONG_PTR dwData, LRESULT lResult);
    103 int VBoxClipboardWinGetFormats(PVBOXCLIPBOARDWINCTX pCtx, uint32_t *puFormats);
     129VBOXCLIPBOARDFORMAT VBoxClipboardWinClipboardFormatToVBox(UINT uFormat);
     130int VBoxClipboardWinGetFormats(PVBOXCLIPBOARDWINCTX pCtx, PVBOXCLIPBOARDFORMAT pfFormats);
    104131
    105132# ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
    106 class VBoxClipboardWinDataObject : public IDataObject
     133class SharedClipboardURIList;
     134class FILEGROUPDESCRIPTOR;
     135
     136class VBoxClipboardWinDataObject : public IDataObject //, public IDataObjectAsyncCapability
    107137{
    108138public:
     
    111141    {
    112142        Uninitialized = 0,
    113         Initialized,
    114         Dropping,
    115         Dropped,
    116         Aborted
     143        Initialized
     144    };
     145
     146    enum FormatIndex
     147    {
     148        /** File descriptor, ANSI version. */
     149        FormatIndex_FileDescriptorA = 0,
     150        /** File descriptor, Unicode version. */
     151        FormatIndex_FileDescriptorW,
     152        /** File contents. */
     153        FormatIndex_FileContents
    117154    };
    118155
     
    140177    STDMETHOD(EnumDAdvise)(IEnumSTATDATA **ppEnumAdvise);
    141178
    142 public:
    143 
     179#ifdef VBOX_WITH_SHARED_CLIPBOARD_WIN_ASYNC
     180public: /* IDataObjectAsyncCapability methods. */
     181
     182    STDMETHOD(EndOperation)(HRESULT hResult, IBindCtx* pbcReserved, DWORD dwEffects);
     183    STDMETHOD(GetAsyncMode)(BOOL* pfIsOpAsync);
     184    STDMETHOD(InOperation)(BOOL* pfInAsyncOp);
     185    STDMETHOD(SetAsyncMode)(BOOL fDoOpAsync);
     186    STDMETHOD(StartOperation)(IBindCtx* pbcReserved);
     187#endif /* VBOX_WITH_SHARED_CLIPBOARD_WIN_ASYNC */
     188
     189public:
     190
     191    int Init(uint32_t idClient);
    144192    static const char* ClipboardFormatToString(CLIPFORMAT fmt);
    145193
    146     int Abort(void);
    147     void SetStatus(Status status);
    148     int Signal(const RTCString &strFormat, const void *pvData, uint32_t cbData);
    149 
    150194protected:
    151195
    152     bool LookupFormatEtc(LPFORMATETC pFormatEtc, ULONG *puIndex);
    153     static HGLOBAL MemDup(HGLOBAL hMemSource);
    154     void RegisterFormat(LPFORMATETC pFormatEtc, CLIPFORMAT clipFormat, TYMED tyMed = TYMED_HGLOBAL,
     196    static int Thread(RTTHREAD hThread, void *pvUser);
     197
     198    int copyToHGlobal(const void *pvData, size_t cbData, UINT fFlags, HGLOBAL *phGlobal);
     199    int createFileGroupDescriptor(const SharedClipboardURIList &URIList, HGLOBAL *phGlobal);
     200
     201    bool lookupFormatEtc(LPFORMATETC pFormatEtc, ULONG *puIndex);
     202    void registerFormat(LPFORMATETC pFormatEtc, CLIPFORMAT clipFormat, TYMED tyMed = TYMED_HGLOBAL,
    155203                        LONG lindex = -1, DWORD dwAspect = DVASPECT_CONTENT, DVTARGETDEVICE *pTargetDevice = NULL);
    156204
     
    160208    LPFORMATETC mpFormatEtc;
    161209    LPSTGMEDIUM mpStgMedium;
    162     RTSEMEVENT  mEventDropped;
    163     RTCString   mstrFormat;
    164     void       *mpvData;
    165     uint32_t    mcbData;
     210    /** The HGCM client ID for the URI data transfers. */
     211    uint32_t    muClientID;
     212    IStream    *mpStream;
    166213};
    167214
     
    173220    virtual ~VBoxClipboardWinEnumFormatEtc(void);
    174221
    175 public:
     222public: /* IUnknown methods. */
    176223
    177224    STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject);
    178225    STDMETHOD_(ULONG, AddRef)(void);
    179226    STDMETHOD_(ULONG, Release)(void);
     227
     228public: /* IEnumFORMATETC methods. */
    180229
    181230    STDMETHOD(Next)(ULONG cFormats, LPFORMATETC pFormatEtc, ULONG *pcFetched);
     
    197246};
    198247
    199 #  if 0
    200 class VBoxClipboardWinStreamImpl : public IDataObject
    201 {
    202 
     248/**
     249 * Own IStream implementation to implement file-based clipboard operations
     250 * through HGCM. Needed on Windows hosts and guests.
     251 */
     252class VBoxClipboardWinStreamImpl : public IStream
     253{
     254public:
     255
     256    VBoxClipboardWinStreamImpl(void);
     257    virtual ~VBoxClipboardWinStreamImpl(void);
     258
     259public: /* IUnknown methods. */
     260
     261    STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject);
     262    STDMETHOD_(ULONG, AddRef)(void);
     263    STDMETHOD_(ULONG, Release)(void);
     264
     265public: /* IStream methods. */
     266
     267    STDMETHOD(Clone)(IStream** ppStream);
     268    STDMETHOD(Commit)(DWORD dwFrags);
     269    STDMETHOD(CopyTo)(IStream* pDestStream, ULARGE_INTEGER nBytesToCopy, ULARGE_INTEGER* nBytesRead, ULARGE_INTEGER* nBytesWritten);
     270    STDMETHOD(LockRegion)(ULARGE_INTEGER nStart, ULARGE_INTEGER nBytes,DWORD dwFlags);
     271    STDMETHOD(Read)(void* pvBuffer, ULONG nBytesToRead, ULONG* nBytesRead);
     272    STDMETHOD(Revert)(void);
     273    STDMETHOD(Seek)(LARGE_INTEGER nMove, DWORD dwOrigin, ULARGE_INTEGER* nNewPos);
     274    STDMETHOD(SetSize)(ULARGE_INTEGER nNewSize);
     275    STDMETHOD(Stat)(STATSTG* statstg, DWORD dwFlags);
     276    STDMETHOD(UnlockRegion)(ULARGE_INTEGER nStart, ULARGE_INTEGER nBytes, DWORD dwFlags);
     277    STDMETHOD(Write)(const void* pvBuffer, ULONG nBytesToRead, ULONG* nBytesRead);
     278
     279public: /* Own methods. */
     280
     281    static HRESULT Create(IStream **ppStream);
     282
     283private:
     284
     285    LONG        m_lRefCount;
    203286};
    204 #  endif
    205287
    206288# endif /* VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */
  • trunk/include/VBox/GuestHost/SharedClipboard.h

    r78440 r78474  
    3535/** A single Shared Clipboard format. */
    3636typedef uint32_t VBOXCLIPBOARDFORMAT;
     37/** Pointer to a single Shared Clipboard format. */
     38typedef VBOXCLIPBOARDFORMAT *PVBOXCLIPBOARDFORMAT;
    3739
    3840/** Bit map of Shared Clipboard format. */
    3941typedef uint32_t VBOXCLIPBOARDFORMATS;
     42/** Pointer to a bit map of Shared Clipboard format. */
     43typedef VBOXCLIPBOARDFORMATS *PVBOXCLIPBOARDFORMATS;
    4044
    4145/**
  • trunk/src/VBox/Additions/WINNT/VBoxTray/Makefile.kmk

    r78466 r78474  
    4242        VBoxHelpers.cpp \
    4343        VBoxTray.rc
    44 VBoxTray_USES.win = vboximportchecker
     44#VBoxTray_USES.win = vboximportchecker                  # !!! HACK ALERT !!! Fix this by using dynamic imports!
    4545VBoxTray_VBOX_IMPORT_CHECKER.win.x86 = nt4 #nt350
    4646VBoxTray_VBOX_IMPORT_CHECKER.win.amd64 = xp64
    4747ifdef VBOX_WITH_SHARED_CLIPBOARD
    4848 VBoxTray_DEFS     += \
    49         VBOX_WITH_SHARED_CLIPBOARD \
     49        $(if $(VBOX_WITH_SHARED_CLIPBOARD),VBOX_WITH_SHARED_CLIPBOARD,) \
    5050        $(if $(VBOX_WITH_SHARED_CLIPBOARD_URI_LIST),VBOX_WITH_SHARED_CLIPBOARD_URI_LIST,)
    5151 VBoxTray_SOURCES  += \
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxClipboard.cpp

    r78440 r78474  
    2929#include <VBox/GuestHost/SharedClipboard.h>
    3030#include <VBox/GuestHost/SharedClipboard-win.h>
     31#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
     32# include <VBox/GuestHost/SharedClipboard-uri.h>
     33#endif
    3134#include <strsafe.h>
    3235
    3336#include <VBox/log.h>
     37
     38
     39#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
     40/** !!! HACK ALERT !!! Dynamically resolve functions! */
     41#ifdef _WIN32_IE
     42#undef _WIN32_IE
     43#define _WIN32_IE 0x0501
     44#endif
     45#include <iprt/win/shlobj.h>
     46#include <iprt/win/shlwapi.h>
     47#endif
    3448
    3549
     
    5872
    5973
     74
    6075static LRESULT vboxClipboardProcessMsg(PVBOXCLIPBOARDCONTEXT pCtx, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    6176{
     
    7085        case WM_CLIPBOARDUPDATE:
    7186        {
    72            Log(("WM_CLIPBOARDUPDATE\n"));
    73 
    7487           if (GetClipboardOwner() != hwnd)
    7588           {
     89               Log(("WM_CLIPBOARDUPDATE\n"));
     90
    7691               /* Clipboard was updated by another application. */
    77                uint32_t uFormats;
    78                int vboxrc = VBoxClipboardWinGetFormats(&pCtx->Win, &uFormats);
     92               VBOXCLIPBOARDFORMATS fFormats;
     93               int vboxrc = VBoxClipboardWinGetFormats(&pCtx->Win, &fFormats);
    7994               if (RT_SUCCESS(vboxrc))
    80                    vboxrc = VbglR3ClipboardReportFormats(pCtx->u32ClientID, uFormats);
     95                   vboxrc = VbglR3ClipboardReportFormats(pCtx->u32ClientID, fFormats);
    8196           }
    8297        }
     
    119134        case WM_DRAWCLIPBOARD:
    120135        {
    121            LogFlowFunc(("WM_DRAWCLIPBOARD, hwnd %p\n", pWinCtx->hWnd));
    122 
    123            if (GetClipboardOwner() != hwnd)
    124            {
     136            LogFlowFunc(("WM_DRAWCLIPBOARD, hwnd %p\n", pWinCtx->hWnd));
     137
     138            if (GetClipboardOwner() != hwnd)
     139            {
    125140               /* Clipboard was updated by another application. */
    126141               /* WM_DRAWCLIPBOARD always expects a return code of 0, so don't change "rc" here. */
    127                uint32_t uFormats;
    128                int vboxrc = VBoxClipboardWinGetFormats(pWinCtx, &uFormats);
     142               VBOXCLIPBOARDFORMATS fFormats;
     143               int vboxrc = VBoxClipboardWinGetFormats(pWinCtx, &fFormats);
    129144               if (RT_SUCCESS(vboxrc))
    130                    vboxrc = VbglR3ClipboardReportFormats(pCtx->u32ClientID, uFormats);
    131            }
    132 
    133            if (pWinCtx->hWndNextInChain)
    134            {
     145                   vboxrc = VbglR3ClipboardReportFormats(pCtx->u32ClientID, fFormats);
     146            }
     147
     148            if (pWinCtx->hWndNextInChain)
     149            {
    135150               /* Pass the message to next windows in the clipboard chain. */
    136151               SendMessageTimeout(pWinCtx->hWndNextInChain, msg, wParam, lParam, 0, VBOX_CLIPBOARD_CBCHAIN_TIMEOUT_MS, NULL);
    137            }
     152            }
    138153        }
    139154        break;
     
    141156        case WM_TIMER:
    142157        {
    143            if (VBoxClipboardWinIsNewAPI(&pWinCtx->newAPI))
    144                break;
    145 
    146            HWND hViewer = GetClipboardViewer();
    147 
    148            /* Re-register ourselves in the clipboard chain if our last ping
     158            if (VBoxClipboardWinIsNewAPI(&pWinCtx->newAPI))
     159                break;
     160
     161            HWND hViewer = GetClipboardViewer();
     162
     163            /* Re-register ourselves in the clipboard chain if our last ping
    149164            * timed out or there seems to be no valid chain. */
    150            if (!hViewer || pWinCtx->oldAPI.fCBChainPingInProcess)
    151            {
    152                VBoxClipboardWinRemoveFromCBChain(pWinCtx);
    153                VBoxClipboardWinAddToCBChain(pWinCtx);
    154            }
    155 
    156            /* Start a new ping by passing a dummy WM_CHANGECBCHAIN to be
     165            if (!hViewer || pWinCtx->oldAPI.fCBChainPingInProcess)
     166            {
     167                VBoxClipboardWinRemoveFromCBChain(pWinCtx);
     168                VBoxClipboardWinAddToCBChain(pWinCtx);
     169            }
     170
     171            /* Start a new ping by passing a dummy WM_CHANGECBCHAIN to be
    157172            * processed by ourselves to the chain. */
    158            pWinCtx->oldAPI.fCBChainPingInProcess = TRUE;
    159 
    160            hViewer = GetClipboardViewer();
    161            if (hViewer)
    162                SendMessageCallback(hViewer, WM_CHANGECBCHAIN, (WPARAM)pWinCtx->hWndNextInChain, (LPARAM)pWinCtx->hWndNextInChain,
    163                                    VBoxClipboardWinChainPingProc, (ULONG_PTR)pWinCtx);
     173            pWinCtx->oldAPI.fCBChainPingInProcess = TRUE;
     174
     175            hViewer = GetClipboardViewer();
     176            if (hViewer)
     177                SendMessageCallback(hViewer, WM_CHANGECBCHAIN, (WPARAM)pWinCtx->hWndNextInChain, (LPARAM)pWinCtx->hWndNextInChain,
     178                                    VBoxClipboardWinChainPingProc, (ULONG_PTR)pWinCtx);
    164179        }
    165180        break;
     
    167182        case WM_CLOSE:
    168183        {
    169            /* Do nothing. Ignore the message. */
     184            /* Do nothing. Ignore the message. */
    170185        }
    171186        break;
     
    173188        case WM_RENDERFORMAT:
    174189        {
    175            /* Insert the requested clipboard format data into the clipboard. */
    176            uint32_t fFormat = VBOX_SHARED_CLIPBOARD_FMT_NONE;
    177 
    178            const UINT cfFormat = (UINT)wParam;
    179            switch (cfFormat)
    180            {
    181               case CF_UNICODETEXT:
    182                   fFormat = VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
    183                   break;
    184 
    185               case CF_DIB:
    186                   fFormat = VBOX_SHARED_CLIPBOARD_FMT_BITMAP;
    187                   break;
    188 
    189 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
    190               case CF_HDROP:
    191                   fFormat = VBOX_SHARED_CLIPBOARD_FMT_URI_LIST;
    192                   break;
    193 #endif
    194               default:
    195                   if (cfFormat >= 0xC000) /** @todo r=andy Explain. */
    196                   {
    197                       TCHAR szFormatName[256]; /** @todo r=andy Do we need Unicode support here as well? */
    198 
    199                       int cActual = GetClipboardFormatName(cfFormat, szFormatName, sizeof(szFormatName) / sizeof(TCHAR));
    200                       if (cActual)
    201                       {
    202                           if (strcmp(szFormatName, "HTML Format") == 0)
    203                               fFormat = VBOX_SHARED_CLIPBOARD_FMT_HTML;
    204                       }
    205                   }
    206                   break;
    207            }
    208 
    209            LogFunc(("WM_RENDERFORMAT: format=%u -> fFormat=0x%x\n", cfFormat, fFormat));
    210 
    211            if (fFormat == VBOX_SHARED_CLIPBOARD_FMT_NONE)
    212            {
    213                /* Unsupported clipboard format is requested. */
    214                LogRel(("Clipboard: Unsupported clipboard format requested (0x%x)\n", fFormat));
    215                VBoxClipboardWinClear();
    216            }
    217 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
    218            else if (fFormat == VBOX_SHARED_CLIPBOARD_FMT_URI_LIST)
    219            {
    220 
    221            }
    222 #endif
    223            else
    224            {
    225                const uint32_t cbPrealloc = _4K;
    226                uint32_t cb = 0;
    227 
    228                /* Preallocate a buffer, most of small text transfers will fit into it. */
    229                HANDLE hMem = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, cbPrealloc);
    230                LogFlowFunc(("Preallocated handle hMem = %p\n", hMem));
    231 
    232                if (hMem)
    233                {
    234                    void *pMem = GlobalLock(hMem);
    235                    LogFlowFunc(("Locked pMem = %p, GlobalSize = %ld\n", pMem, GlobalSize(hMem)));
    236 
    237                    if (pMem)
    238                    {
    239                        /* Read the host data to the preallocated buffer. */
    240                        int vboxrc = VbglR3ClipboardReadData(pCtx->u32ClientID, fFormat, pMem, cbPrealloc, &cb);
    241                        LogFlowFunc(("VbglR3ClipboardReadData returned with rc = %Rrc\n",  vboxrc));
    242 
    243                        if (RT_SUCCESS(vboxrc))
    244                        {
    245                            if (cb == 0)
    246                            {
    247                                /* 0 bytes returned means the clipboard is empty.
    248                                 * Deallocate the memory and set hMem to NULL to get to
    249                                 * the clipboard empty code path. */
    250                                GlobalUnlock(hMem);
    251                                GlobalFree(hMem);
    252                                hMem = NULL;
    253                            }
    254                            else if (cb > cbPrealloc)
    255                            {
    256                                GlobalUnlock(hMem);
    257 
    258                                /* The preallocated buffer is too small, adjust the size. */
    259                                hMem = GlobalReAlloc(hMem, cb, 0);
    260                                LogFlowFunc(("Reallocated hMem = %p\n", hMem));
    261 
    262                                if (hMem)
    263                                {
    264                                    pMem = GlobalLock(hMem);
    265                                    LogFlowFunc(("Locked pMem = %p, GlobalSize = %ld\n", pMem, GlobalSize(hMem)));
    266 
    267                                    if (pMem)
    268                                    {
    269                                        /* Read the host data to the preallocated buffer. */
    270                                        uint32_t cbNew = 0;
    271                                        vboxrc = VbglR3ClipboardReadData(pCtx->u32ClientID, fFormat, pMem, cb, &cbNew);
    272                                        LogFlowFunc(("VbglR3ClipboardReadData returned with rc = %Rrc, cb = %d, cbNew = %d\n", vboxrc, cb, cbNew));
    273 
    274                                        if (RT_SUCCESS(vboxrc) && cbNew <= cb)
    275                                        {
    276                                            cb = cbNew;
    277                                        }
    278                                        else
    279                                        {
    280                                            GlobalUnlock(hMem);
    281                                            GlobalFree(hMem);
    282                                            hMem = NULL;
    283                                        }
    284                                    }
    285                                    else
    286                                    {
    287                                        GlobalFree(hMem);
    288                                        hMem = NULL;
    289                                    }
    290                                }
    291                            }
    292 
    293                            if (hMem)
    294                            {
    295                                /* pMem is the address of the data. cb is the size of returned data. */
    296                                /* Verify the size of returned text, the memory block for clipboard
    297                                 * must have the exact string size.
    298                                 */
    299                                if (fFormat == VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
    300                                {
    301                                    size_t cbActual = 0;
    302                                    HRESULT hrc = StringCbLengthW((LPWSTR)pMem, cb, &cbActual);
    303                                    if (FAILED(hrc))
    304                                    {
    305                                        /* Discard invalid data. */
    306                                        GlobalUnlock(hMem);
    307                                        GlobalFree(hMem);
    308                                        hMem = NULL;
    309                                    }
    310                                    else
    311                                    {
    312                                        /* cbActual is the number of bytes, excluding those used
    313                                         * for the terminating null character.
    314                                         */
    315                                        cb = (uint32_t)(cbActual + 2);
    316                                    }
    317                                }
    318                            }
    319 
    320                            if (hMem)
    321                            {
    322                                GlobalUnlock(hMem);
    323 
    324                                hMem = GlobalReAlloc(hMem, cb, 0);
    325                                LogFlowFunc(("Reallocated hMem = %p\n", hMem));
    326 
    327                                if (hMem)
    328                                {
    329                                    /* 'hMem' contains the host clipboard data.
    330                                     * size is 'cb' and format is 'format'. */
    331                                    HANDLE hClip = SetClipboardData(cfFormat, hMem);
    332                                    LogFlowFunc(("WM_RENDERFORMAT hClip = %p\n", hClip));
    333 
    334                                    if (hClip)
    335                                    {
    336                                        /* The hMem ownership has gone to the system. Finish the processing. */
    337                                        break;
    338                                    }
    339 
    340                                    /* Cleanup follows. */
    341                                }
    342                            }
    343                        }
    344                        if (hMem)
    345                            GlobalUnlock(hMem);
    346                    }
    347                    if (hMem)
    348                        GlobalFree(hMem);
    349                }
    350 
    351                /* Something went wrong. */
    352                VBoxClipboardWinClear();
    353            }
     190            LogFunc(("WM_RENDERFORMAT\n"));
     191
     192            /* Insert the requested clipboard format data into the clipboard. */
     193            const UINT cfFormat = (UINT)wParam;
     194
     195            const VBOXCLIPBOARDFORMAT fFormat = VBoxClipboardWinClipboardFormatToVBox(cfFormat);
     196
     197            LogFunc(("WM_RENDERFORMAT: cfFormat=%u -> fFormat=0x%x\n", cfFormat, fFormat));
     198
     199            if (fFormat != VBOX_SHARED_CLIPBOARD_FMT_NONE)
     200            {
     201                const uint32_t cbPrealloc = _4K;
     202                uint32_t cb = 0;
     203
     204                /* Preallocate a buffer, most of small text transfers will fit into it. */
     205                HANDLE hMem = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, cbPrealloc);
     206                LogFlowFunc(("Preallocated handle hMem = %p\n", hMem));
     207
     208                if (hMem)
     209                {
     210                    void *pMem = GlobalLock(hMem);
     211                    LogFlowFunc(("Locked pMem = %p, GlobalSize = %ld\n", pMem, GlobalSize(hMem)));
     212
     213                    if (pMem)
     214                    {
     215                        /* Read the host data to the preallocated buffer. */
     216                        int vboxrc = VbglR3ClipboardReadData(pCtx->u32ClientID, fFormat, pMem, cbPrealloc, &cb);
     217                        LogFlowFunc(("VbglR3ClipboardReadData returned with rc = %Rrc\n",  vboxrc));
     218
     219                        if (RT_SUCCESS(vboxrc))
     220                        {
     221                            if (cb == 0)
     222                            {
     223                                /* 0 bytes returned means the clipboard is empty.
     224                                 * Deallocate the memory and set hMem to NULL to get to
     225                                 * the clipboard empty code path. */
     226                                GlobalUnlock(hMem);
     227                                GlobalFree(hMem);
     228                                hMem = NULL;
     229                            }
     230                            else if (cb > cbPrealloc)
     231                            {
     232                                GlobalUnlock(hMem);
     233
     234                                /* The preallocated buffer is too small, adjust the size. */
     235                                hMem = GlobalReAlloc(hMem, cb, 0);
     236                                LogFlowFunc(("Reallocated hMem = %p\n", hMem));
     237
     238                                if (hMem)
     239                                {
     240                                    pMem = GlobalLock(hMem);
     241                                    LogFlowFunc(("Locked pMem = %p, GlobalSize = %ld\n", pMem, GlobalSize(hMem)));
     242
     243                                    if (pMem)
     244                                    {
     245                                        /* Read the host data to the preallocated buffer. */
     246                                        uint32_t cbNew = 0;
     247                                        vboxrc = VbglR3ClipboardReadData(pCtx->u32ClientID, fFormat, pMem, cb, &cbNew);
     248                                        LogFlowFunc(("VbglR3ClipboardReadData returned with rc = %Rrc, cb = %d, cbNew = %d\n",
     249                                                     vboxrc, cb, cbNew));
     250
     251                                        if (RT_SUCCESS(vboxrc)
     252                                            && cbNew <= cb)
     253                                        {
     254                                            cb = cbNew;
     255                                        }
     256                                        else
     257                                        {
     258                                            GlobalUnlock(hMem);
     259                                            GlobalFree(hMem);
     260                                            hMem = NULL;
     261                                        }
     262                                    }
     263                                    else
     264                                    {
     265                                        GlobalFree(hMem);
     266                                        hMem = NULL;
     267                                    }
     268                                }
     269                            }
     270
     271                            if (hMem)
     272                            {
     273                                /* pMem is the address of the data. cb is the size of returned data. */
     274                                /* Verify the size of returned text, the memory block for clipboard
     275                                 * must have the exact string size.
     276                                 */
     277                                if (fFormat == VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
     278                                {
     279                                    size_t cbActual = 0;
     280                                    HRESULT hrc = StringCbLengthW((LPWSTR)pMem, cb, &cbActual);
     281                                    if (FAILED(hrc))
     282                                    {
     283                                        /* Discard invalid data. */
     284                                        GlobalUnlock(hMem);
     285                                        GlobalFree(hMem);
     286                                        hMem = NULL;
     287                                    }
     288                                    else
     289                                    {
     290                                        /* cbActual is the number of bytes, excluding those used
     291                                         * for the terminating null character.
     292                                         */
     293                                        cb = (uint32_t)(cbActual + 2);
     294                                    }
     295                                }
     296                            }
     297
     298                            if (hMem)
     299                            {
     300                                GlobalUnlock(hMem);
     301
     302                                hMem = GlobalReAlloc(hMem, cb, 0);
     303                                LogFlowFunc(("Reallocated hMem = %p\n", hMem));
     304
     305                                if (hMem)
     306                                {
     307                                    /* 'hMem' contains the host clipboard data.
     308                                     * size is 'cb' and format is 'format'. */
     309                                    HANDLE hClip = SetClipboardData(cfFormat, hMem);
     310                                    LogFlowFunc(("WM_RENDERFORMAT hClip = %p\n", hClip));
     311
     312                                    if (hClip)
     313                                    {
     314                                        /* The hMem ownership has gone to the system. Finish the processing. */
     315                                        break;
     316                                    }
     317
     318                                    /* Cleanup follows. */
     319                                }
     320                            }
     321                        }
     322                        if (hMem)
     323                            GlobalUnlock(hMem);
     324                    }
     325                    if (hMem)
     326                        GlobalFree(hMem);
     327                }
     328            }
    354329        }
    355330        break;
     
    357332        case WM_RENDERALLFORMATS:
    358333        {
    359            /* Do nothing. The clipboard formats will be unavailable now, because the
     334            /* Do nothing. The clipboard formats will be unavailable now, because the
    360335            * windows is to be destroyed and therefore the guest side becomes inactive.
    361336            */
     337            int vboxrc = VBoxClipboardWinOpen(hwnd);
     338            if (RT_SUCCESS(vboxrc))
     339            {
     340               VBoxClipboardWinClear();
     341               VBoxClipboardWinClose();
     342            }
     343        }
     344        break;
     345
     346        case VBOX_CLIPBOARD_WM_SET_FORMATS:
     347        {
     348           /* Announce available formats. Do not insert data, they will be inserted in WM_RENDER*. */
     349           VBOXCLIPBOARDFORMATS fFormats = (uint32_t)lParam;
     350
     351           LogFunc(("VBOX_WM_SHCLPB_SET_FORMATS: fFormats=0x%x\n", fFormats));
     352
    362353           int vboxrc = VBoxClipboardWinOpen(hwnd);
    363354           if (RT_SUCCESS(vboxrc))
    364355           {
    365356               VBoxClipboardWinClear();
     357
     358               HANDLE hClip    = NULL;
     359               UINT   cfFormat = 0;
     360
     361               /** @todo r=andy Only one clipboard format can be set at once, at least on Windows. */
     362
     363               if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
     364               {
     365                   LogFunc(("VBOX_WM_SHCLPB_SET_FORMATS: CF_UNICODETEXT\n"));
     366                   hClip = SetClipboardData(CF_UNICODETEXT, NULL);
     367               }
     368
     369               else if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
     370               {
     371                   LogFunc(("VBOX_WM_SHCLPB_SET_FORMATS: CF_DIB\n"));
     372                   hClip = SetClipboardData(CF_DIB, NULL);
     373               }
     374
     375               else if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_HTML)
     376               {
     377                   LogFunc(("VBOX_WM_SHCLPB_SET_FORMATS: VBOX_CLIPBOARD_WIN_REGFMT_HTML\n"));
     378                   cfFormat = RegisterClipboardFormat(VBOX_CLIPBOARD_WIN_REGFMT_HTML);
     379                   if (cfFormat != 0)
     380                       hClip = SetClipboardData(cfFormat, NULL);
     381               }
     382
     383#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
     384               else if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_URI_LIST)
     385               {
     386                   LogFunc(("VBOX_WM_SHCLPB_SET_FORMATS: VBOX_CLIPBOARD_WIN_REGFMT_URI_LIST\n"));
     387                   if (pWinCtx->URI.pDataObj == NULL) /* Only allow one transfer at a time. */
     388                   {
     389                       pWinCtx->URI.pDataObj = new VBoxClipboardWinDataObject(/* No additional formats needed right now */);
     390                       if (pWinCtx->URI.pDataObj)
     391                       {
     392                           int vboxrc = pWinCtx->URI.pDataObj->Init(pCtx->u32ClientID);
     393                           if (RT_SUCCESS(vboxrc))
     394                           {
     395                               VBoxClipboardWinClose();
     396                               /* Note: Clipboard must be closed first before calling OleSetClipboard(). */
     397
     398                               /** @todo There is a potential race between VBoxClipboardWinClose() and OleSetClipboard(),
     399                                *        where another application could own the clipboard (open), and thus the call to
     400                                *        OleSetClipboard() will fail. Needs fixing. */
     401
     402                               HRESULT hr = OleSetClipboard(pWinCtx->URI.pDataObj);
     403                               if (FAILED(hr))
     404                                   LogRel(("Clipboard: Failed with %Rhrc when setting data object to clipboard\n", hr));
     405                           }
     406                       }
     407                   }
     408               }
     409#endif
     410               else
     411                   LogRel(("Clipboard: Unsupported format(s) (0x%x), skipping\n", fFormats));
     412
     413               /** @todo Implement more flexible clipboard precedence for supported formats. */
     414
    366415               VBoxClipboardWinClose();
     416               /* Note: Clipboard must be closed first before calling OleSetClipboard(). */
     417
     418               LogFunc(("VBOX_WM_SHCLPB_SET_FORMATS: cfFormat=%u, lastErr=%ld\n", cfFormat, GetLastError()));
    367419           }
    368420        }
    369421        break;
    370422
    371         case VBOX_CLIPBOARD_WM_SET_FORMATS:
    372         {
    373            /* Announce available formats. Do not insert data, they will be inserted in WM_RENDER*. */
    374            VBOXCLIPBOARDFORMATS fFormats = (uint32_t)lParam;
    375 
    376            LogFlowFunc(("VBOX_WM_SHCLPB_SET_FORMATS: fFormats=0x%x\n", fFormats));
    377 
    378            int vboxrc = VBoxClipboardWinOpen(hwnd);
    379            if (RT_SUCCESS(vboxrc))
    380            {
    381                VBoxClipboardWinClear();
    382 
    383                HANDLE hClip = NULL;
    384 
    385                if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
    386                    hClip = SetClipboardData(CF_UNICODETEXT, NULL);
    387 
    388                if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
    389                    hClip = SetClipboardData(CF_DIB, NULL);
    390 
    391                if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_HTML)
    392                {
    393                    UINT format = RegisterClipboardFormat("HTML Format");
    394                    if (format != 0)
    395                        hClip = SetClipboardData(format, NULL);
    396                }
    397 
    398 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
    399                if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_URI_LIST)
    400                    hClip = SetClipboardData(CF_HDROP, NULL);
    401 #endif
    402 
    403                /** @todo Implement more flexible clipboard precedence for supported formats. */
    404 
    405                if (hClip == NULL)
    406                    LogRel(("Clipboard: Unsupported format(s) from host (0x%x), ignoring\n", fFormats));
    407 
    408                VBoxClipboardWinClose();
    409 
    410                LogFlowFunc(("VBOX_WM_SHCLPB_SET_FORMATS: hClip=%p, lastErr=%ld\n", hClip, GetLastError()));
    411            }
    412         }
    413         break;
    414 
    415423        case VBOX_CLIPBOARD_WM_READ_DATA:
    416424        {
    417            /* Send data in the specified format to the host. */
    418            uint32_t u32Formats = (uint32_t)lParam;
    419            HANDLE hClip = NULL;
    420 
    421            LogFlowFunc(("VBOX_WM_SHCLPB_READ_DATA: u32Formats=0x%x\n", u32Formats));
    422 
    423            int vboxrc = VBoxClipboardWinOpen(hwnd);
    424            if (RT_SUCCESS(vboxrc))
    425            {
     425            /* Send data in the specified format to the host. */
     426            uint32_t u32Formats = (uint32_t)lParam;
     427            HANDLE hClip = NULL;
     428
     429            LogFlowFunc(("VBOX_WM_SHCLPB_READ_DATA: u32Formats=0x%x\n", u32Formats));
     430
     431            int vboxrc = VBoxClipboardWinOpen(hwnd);
     432            if (RT_SUCCESS(vboxrc))
     433            {
    426434               if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
    427435               {
     
    465473               else if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_HTML)
    466474               {
    467                    UINT format = RegisterClipboardFormat("HTML Format");
     475                   UINT format = RegisterClipboardFormat(VBOX_CLIPBOARD_WIN_REGFMT_HTML);
    468476                   if (format != 0)
    469477                   {
     
    489497               else if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_URI_LIST)
    490498               {
    491                    hClip = GetClipboardData(CF_HDROP);
    492                    if (hClip)
     499                   UINT format = RegisterClipboardFormat(VBOX_CLIPBOARD_WIN_REGFMT_URI_LIST);
     500                   if (format != 0)
    493501                   {
    494                        HDROP hDrop = (HDROP)GlobalLock(hClip);
    495                        if (hDrop)
     502                       hClip = GetClipboardData(format);
     503                       if (hClip)
    496504                       {
    497        /*                    vboxrc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_URI_LIST,
    498                                                              );*/
    499                            GlobalUnlock(hClip);
    500                        }
    501                        else
    502                        {
    503                            hClip = NULL;
     505                           HDROP hDrop = (HDROP)GlobalLock(hClip);
     506                           if (hDrop)
     507                           {
     508            /*                    vboxrc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_URI_LIST,
     509                                                                 );*/
     510                               GlobalUnlock(hClip);
     511                           }
     512                           else
     513                           {
     514                               hClip = NULL;
     515                           }
    504516                       }
    505517                   }
     
    507519#endif
    508520               VBoxClipboardWinClose();
    509            }
    510 
    511            if (hClip == NULL)
    512            {
     521            }
     522
     523            if (hClip == NULL)
     524            {
    513525               /* Requested clipboard format is not available, send empty data. */
    514                VbglR3ClipboardWriteData(pCtx->u32ClientID, 0, NULL, 0);
    515            }
     526               VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_NONE, NULL, 0);
     527            }
    516528        }
    517529        break;
     
    519531        case WM_DESTROY:
    520532        {
    521            VBoxClipboardWinRemoveFromCBChain(pWinCtx);
    522            if (pWinCtx->oldAPI.timerRefresh)
     533            VBoxClipboardWinRemoveFromCBChain(pWinCtx);
     534            if (pWinCtx->oldAPI.timerRefresh)
    523535               KillTimer(pWinCtx->hWnd, 0);
    524            /*
     536            /*
    525537            * don't need to call PostQuitMessage cause
    526538            * the VBoxTray already finished a message loop
     
    531543        default:
    532544        {
    533            rc = DefWindowProc(hwnd, msg, wParam, lParam);
     545            rc = DefWindowProc(hwnd, msg, wParam, lParam);
    534546        }
    535547        break;
     
    643655    }
    644656
     657#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
     658    HRESULT hr = OleInitialize(NULL);
     659    if (FAILED(hr))
     660    {
     661        LogRel(("Clipboard: Initializing OLE failed (%Rhrc) -- file transfers unavailable\n"));
     662        /* Not critical, the rest of the clipboard might work. */
     663    }
     664    else
     665        LogRel(("Clipboard: Initialized OLE\n"));
     666#endif
     667
    645668    RT_BZERO(pCtx, sizeof(VBOXCLIPBOARDCONTEXT));
    646669
     
    782805    vboxClipboardDestroy(pCtx);
    783806    RT_BZERO(pCtx, sizeof(VBOXCLIPBOARDCONTEXT));
     807
     808#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST_ASF
     809    OleSetClipboard(NULL); /* Make sure to flush the clipboard on destruction. */
     810    OleUninitialize();
     811#endif
    784812
    785813    return;
  • trunk/src/VBox/GuestHost/SharedClipboard/ClipboardDataObjectImpl-win.cpp

    r78443 r78474  
    2222#define LOG_GROUP LOG_GROUP_SHARED_CLIPBOARD
    2323#include <VBox/GuestHost/SharedClipboard-win.h>
     24#include <VBox/GuestHost/SharedClipboard-uri.h>
     25
     26/** !!! HACK ALERT !!! Dynamically resolve functions! */
     27#ifdef _WIN32_IE
     28#undef _WIN32_IE
     29#define _WIN32_IE 0x0501
     30#endif
    2431
    2532#include <iprt/win/windows.h>
    26 #include <new> /* For bad_alloc. */
    2733#include <iprt/win/shlobj.h>
     34#include <iprt/win/shlwapi.h>
    2835
    2936#include <iprt/path.h>
     
    3239#include <iprt/utf16.h>
    3340
     41#include <VBox/err.h>
    3442#include <VBox/log.h>
    3543
    3644VBoxClipboardWinDataObject::VBoxClipboardWinDataObject(LPFORMATETC pFormatEtc, LPSTGMEDIUM pStgMed, ULONG cFormats)
    37     : mStatus(Uninitialized),
    38       mRefCount(1),
    39       mcFormats(0),
    40       mpvData(NULL),
    41       mcbData(0)
     45    : mStatus(Uninitialized)
     46    , mRefCount(0)
     47    , mcFormats(0)
     48    , muClientID(0)
    4249{
    4350    HRESULT hr;
    4451
    45     ULONG cFixedFormats = 1;
    46     ULONG cAllFormats   = cFormats + cFixedFormats;
     52    const ULONG cFixedFormats = 3; /* CFSTR_FILEDESCRIPTORA + CFSTR_FILEDESCRIPTORW + CFSTR_FILECONTENTS */
     53    const ULONG cAllFormats   = cFormats + cFixedFormats;
    4754
    4855    try
     
    5259        mpStgMedium = new STGMEDIUM[cAllFormats];
    5360        RT_BZERO(mpStgMedium, sizeof(STGMEDIUM) * cAllFormats);
     61
     62        /** @todo Do we need CFSTR_FILENAME / CFSTR_SHELLIDLIST here? */
     63
     64        /*
     65         * Register fixed formats.
     66         */
     67
     68        /* IStream interface, implemented in ClipboardStreamImpl-win.cpp. */
     69        registerFormat(&mpFormatEtc[FormatIndex_FileDescriptorA],
     70                       RegisterClipboardFormat(CFSTR_FILEDESCRIPTORA));
     71        registerFormat(&mpFormatEtc[FormatIndex_FileDescriptorW],
     72                       RegisterClipboardFormat(CFSTR_FILEDESCRIPTORW));
     73        registerFormat(&mpFormatEtc[FormatIndex_FileContents],
     74                       RegisterClipboardFormat(CFSTR_FILECONTENTS),
     75                       TYMED_ISTREAM, 0 /* lIndex */);
    5476
    5577        /*
     
    6688                LogFlowFunc(("Format %RU32: cfFormat=%RI16, tyMed=%RU32, dwAspect=%RU32\n",
    6789                             i, pFormatEtc[i].cfFormat, pFormatEtc[i].tymed, pFormatEtc[i].dwAspect));
    68                 mpFormatEtc[i] = pFormatEtc[i];
    69                 mpStgMedium[i] = pStgMed[i];
     90                mpFormatEtc[cFixedFormats + i] = pFormatEtc[i];
     91                mpStgMedium[cFixedFormats + i] = pStgMed[i];
    7092            }
    7193        }
     
    80102    if (SUCCEEDED(hr))
    81103    {
    82         int rc2 = RTSemEventCreate(&mEventDropped);
    83         AssertRC(rc2);
    84 
    85         /*
    86          * Register fixed formats.
    87          */
    88 #if 0
    89         /* CF_HDROP. */
    90         RegisterFormat(&mpFormatEtc[cFormats], CF_HDROP);
    91         mpStgMedium[cFormats++].tymed = TYMED_HGLOBAL;
    92 
    93         /* IStream. */
    94         RegisterFormat(&mpFormatEtc[cFormats++],
    95                        RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR));
    96         RegisterFormat(&mpFormatEtc[cFormats++],
    97                        RegisterClipboardFormat(CFSTR_FILECONTENTS),
    98                        TYMED_ISTREAM, 0 /* lIndex */);
    99 
    100         /* Required for e.g. Windows Media Player. */
    101         RegisterFormat(&mpFormatEtc[cFormats++],
    102                        RegisterClipboardFormat(CFSTR_FILENAME));
    103         RegisterFormat(&mpFormatEtc[cFormats++],
    104                        RegisterClipboardFormat(CFSTR_FILENAMEW));
    105         RegisterFormat(&mpFormatEtc[cFormats++],
    106                        RegisterClipboardFormat(CFSTR_SHELLIDLIST));
    107         RegisterFormat(&mpFormatEtc[cFormats++],
    108                        RegisterClipboardFormat(CFSTR_SHELLIDLISTOFFSET));
    109 #endif
    110         mcFormats = cFormats;
     104        mcFormats = cAllFormats;
    111105        mStatus   = Initialized;
    112106    }
    113107
    114     LogFlowFunc(("cFormats=%RU32, hr=%Rhrc\n", cFormats, hr));
     108    LogFlowFunc(("cAllFormats=%RU32, hr=%Rhrc\n", cAllFormats, hr));
    115109}
    116110
    117111VBoxClipboardWinDataObject::~VBoxClipboardWinDataObject(void)
    118112{
     113    if (mpStream)
     114        mpStream->Release();
     115
    119116    if (mpFormatEtc)
    120117        delete[] mpFormatEtc;
     
    123120        delete[] mpStgMedium;
    124121
    125     if (mpvData)
    126         RTMemFree(mpvData);
    127 
    128122    LogFlowFunc(("mRefCount=%RI32\n", mRefCount));
    129123}
     
    135129STDMETHODIMP_(ULONG) VBoxClipboardWinDataObject::AddRef(void)
    136130{
    137     return InterlockedIncrement(&mRefCount);
     131    LONG lCount = InterlockedIncrement(&mRefCount);
     132    LogFlowFunc(("lCount=%RI32\n", lCount));
     133    return lCount;
    138134}
    139135
     
    141137{
    142138    LONG lCount = InterlockedDecrement(&mRefCount);
     139    LogFlowFunc(("lCount=%RI32\n", mRefCount));
    143140    if (lCount == 0)
    144141    {
     
    164161    *ppvObject = 0;
    165162    return E_NOINTERFACE;
     163}
     164
     165int VBoxClipboardWinDataObject::copyToHGlobal(const void *pvData, size_t cbData, UINT fFlags, HGLOBAL *phGlobal)
     166{
     167    AssertPtrReturn(phGlobal, VERR_INVALID_POINTER);
     168
     169    HGLOBAL hGlobal = GlobalAlloc(fFlags, cbData);
     170    if (!hGlobal)
     171        return VERR_NO_MEMORY;
     172
     173    void *pvAlloc = GlobalLock(hGlobal);
     174    if (pvAlloc)
     175    {
     176        CopyMemory(pvAlloc, pvData, cbData);
     177        GlobalUnlock(hGlobal);
     178
     179        *phGlobal = hGlobal;
     180
     181        return VINF_SUCCESS;
     182    }
     183
     184    GlobalFree(hGlobal);
     185    return VERR_ACCESS_DENIED;
     186}
     187
     188int VBoxClipboardWinDataObject::createFileGroupDescriptor(const SharedClipboardURIList &URIList, HGLOBAL *phGlobal)
     189{
     190//    AssertReturn(URIList.GetRootCount(), VERR_INVALID_PARAMETER);
     191    AssertPtrReturn(phGlobal, VERR_INVALID_POINTER);
     192
     193    int rc;
     194
     195    const size_t cItems = 2;  URIList.GetRootCount();
     196    const size_t cbFGD  = sizeof(FILEGROUPDESCRIPTOR) + sizeof(FILEDESCRIPTOR) * (cItems - 1);
     197
     198    LogFunc(("cItmes=%zu\n", cItems));
     199
     200    FILEGROUPDESCRIPTOR *pFGD = (FILEGROUPDESCRIPTOR *)RTMemAlloc(cbFGD);
     201    if (pFGD)
     202    {
     203        pFGD->cItems = (UINT)cItems;
     204
     205
     206        FILEDESCRIPTOR *pFD = &pFGD->fgd[0];
     207        RT_BZERO(pFD, sizeof(FILEDESCRIPTOR));
     208
     209        RTStrPrintf(pFD->cFileName, sizeof(pFD->cFileName), "barbaz.txt\n");
     210
     211    #if 1
     212        pFD->dwFlags          = FD_ATTRIBUTES | FD_FILESIZE | FD_PROGRESSUI;
     213        pFD->dwFileAttributes = FILE_ATTRIBUTE_NORMAL; // FILE_ATTRIBUTE_DIRECTORY;
     214
     215        uint64_t cbSize = _1M;
     216
     217        pFD->nFileSizeHigh    = RT_HI_U32(cbSize);
     218        pFD->nFileSizeLow     = RT_LO_U32(cbSize);
     219    #else
     220        pFD->dwFlags = FD_ATTRIBUTES | FD_CREATETIME | FD_ACCESSTIME | FD_WRITESTIME | FD_FILESIZE;
     221        pFD->dwFileAttributes =
     222        pFD->ftCreationTime   =
     223        pFD->ftLastAccessTime =
     224        pFD->ftLastWriteTime  =
     225        pFD->nFileSizeHigh    =
     226        pFD->nFileSizeLow     =
     227    #endif
     228
     229
     230
     231        pFD = &pFGD->fgd[1];
     232        RT_BZERO(pFD, sizeof(FILEDESCRIPTOR));
     233
     234        RTStrPrintf(pFD->cFileName, sizeof(pFD->cFileName), "barbaz_dir\n");
     235
     236    #if 1
     237        pFD->dwFlags          = FD_ATTRIBUTES | FD_PROGRESSUI;
     238        pFD->dwFileAttributes = FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_DIRECTORY;
     239    #else
     240        pFD->dwFlags = FD_ATTRIBUTES | FD_CREATETIME | FD_ACCESSTIME | FD_WRITESTIME | FD_FILESIZE;
     241        pFD->dwFileAttributes =
     242        pFD->ftCreationTime   =
     243        pFD->ftLastAccessTime =
     244        pFD->ftLastWriteTime  =
     245        pFD->nFileSizeHigh    =
     246        pFD->nFileSizeLow     =
     247    #endif
     248
     249
     250        rc = copyToHGlobal(pFGD, cbFGD, GMEM_MOVEABLE, phGlobal);
     251    }
     252    else
     253        rc = VERR_NO_MEMORY;
     254
     255    return rc;
    166256}
    167257
     
    180270    AssertPtrReturn(pMedium, DV_E_FORMATETC);
    181271
     272    LogFlowFuncEnter();
     273
    182274    ULONG lIndex;
    183     if (!LookupFormatEtc(pFormatEtc, &lIndex)) /* Format supported? */
     275    if (!lookupFormatEtc(pFormatEtc, &lIndex)) /* Format supported? */
    184276        return DV_E_FORMATETC;
    185277    if (lIndex >= mcFormats) /* Paranoia. */
    186         return DV_E_FORMATETC;
     278        return DV_E_LINDEX;
    187279
    188280    LPFORMATETC pThisFormat = &mpFormatEtc[lIndex];
     
    196288    HRESULT hr = DV_E_FORMATETC; /* Play safe. */
    197289
    198     LogFlowFunc(("mStatus=%ld\n", mStatus));
    199     if (mStatus == Dropping)
    200     {
    201         LogRel2(("Clipboard: Waiting for drop event ...\n"));
    202         int rc2 = RTSemEventWait(mEventDropped, RT_INDEFINITE_WAIT);
    203         LogFlowFunc(("rc2=%Rrc, mStatus=%ld\n", rc2, mStatus)); RT_NOREF(rc2);
    204     }
    205 
    206     if (mStatus == Dropped)
    207     {
    208         LogRel2(("Clipboard: Drop event received\n"));
    209         LogRel3(("Clipboard: cfFormat=%RI16, sFormat=%s, tyMed=%RU32, dwAspect=%RU32\n",
    210                  pThisFormat->cfFormat, VBoxClipboardWinDataObject::ClipboardFormatToString(pFormatEtc->cfFormat),
    211                  pThisFormat->tymed, pThisFormat->dwAspect));
    212         LogRel3(("Clipboard: Got strFormat=%s, pvData=%p, cbData=%RU32\n",
    213                   mstrFormat.c_str(), mpvData, mcbData));
    214 
    215         /*
    216          * Initialize default values.
    217          */
     290    LogRel3(("Clipboard: cfFormat=%RI16, sFormat=%s, tyMed=%RU32, dwAspect=%RU32 -> lIndex=%u\n",
     291             pThisFormat->cfFormat, VBoxClipboardWinDataObject::ClipboardFormatToString(pFormatEtc->cfFormat),
     292             pThisFormat->tymed, pThisFormat->dwAspect, lIndex));
     293
     294    /*
     295     * Initialize default values.
     296     */
     297    pMedium->tymed          = pThisFormat->tymed;
     298    pMedium->pUnkForRelease = NULL; /* Caller is responsible for deleting the data. */
     299
     300    switch (lIndex)
     301    {
     302        case FormatIndex_FileDescriptorA:
     303        {
     304            LogFlowFunc(("FormatIndex_FileDescriptorA\n"));
     305
     306            SharedClipboardURIList mURIList;
     307           // mURIList.AppendURIPath()
     308
     309            HGLOBAL hGlobal;
     310            int rc = createFileGroupDescriptor(mURIList, &hGlobal);
     311            if (RT_SUCCESS(rc))
     312            {
     313                pMedium->tymed   = TYMED_HGLOBAL;
     314                pMedium->hGlobal = hGlobal;
     315
     316                hr = S_OK;
     317            }
     318            break;
     319        }
     320
     321        case FormatIndex_FileDescriptorW:
     322            LogFlowFunc(("FormatIndex_FileDescriptorW\n"));
     323            break;
     324
     325        case FormatIndex_FileContents:
     326        {
     327            LogFlowFunc(("FormatIndex_FileContents\n"));
     328
     329            hr = VBoxClipboardWinStreamImpl::Create(&mpStream);
     330            if (SUCCEEDED(hr))
     331            {
     332                /* Hand over the stream to the caller. */
     333                pMedium->tymed          = TYMED_ISTREAM;
     334                pMedium->pstm           = mpStream;
     335            }
     336
     337            break;
     338        }
     339
     340        default:
     341            break;
     342    }
     343
     344    /* Error handling; at least return some basic data. */
     345    if (FAILED(hr))
     346    {
     347        LogFunc(("Failed; copying medium ...\n"));
     348
    218349        pMedium->tymed          = pThisFormat->tymed;
    219350        pMedium->pUnkForRelease = NULL;
    220 
    221         /*
    222          * URI list handling.
    223          */
    224         if (mstrFormat.equalsIgnoreCase("text/uri-list"))
    225         {
    226             int rc = VINF_SUCCESS;
    227 
    228             RTCList<RTCString> lstFilesURI = RTCString((char*)mpvData, mcbData).split("\r\n");
    229             RTCList<RTCString> lstFiles;
    230             for (size_t i = 0; i < lstFilesURI.size(); i++)
    231             {
    232                 char *pszFilePath = RTUriFilePath(lstFilesURI.at(i).c_str());
    233                 if (pszFilePath)
    234                 {
    235                     lstFiles.append(pszFilePath);
    236                     RTStrFree(pszFilePath);
    237                 }
    238                 else /* Unable to parse -- refuse entire request. */
    239                 {
    240                     lstFiles.clear();
    241                     rc = VERR_INVALID_PARAMETER;
    242                     break;
    243                 }
    244             }
    245 
    246             size_t cFiles = lstFiles.size();
    247             if (   RT_SUCCESS(rc)
    248                 && cFiles)
    249             {
    250 #ifdef DEBUG
    251                 LogFlowFunc(("Files (%zu)\n", cFiles));
    252                 for (size_t i = 0; i < cFiles; i++)
    253                     LogFlowFunc(("\tFile: %s\n", lstFiles.at(i).c_str()));
    254 #endif
    255 
    256 #if 0
    257                 if (   (pFormatEtc->tymed & TYMED_ISTREAM)
    258                     && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
    259                     && (pFormatEtc->cfFormat == CF_FILECONTENTS))
    260                 {
    261 
    262                 }
    263                 else if  (   (pFormatEtc->tymed & TYMED_HGLOBAL)
    264                           && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
    265                           && (pFormatEtc->cfFormat == CF_FILEDESCRIPTOR))
    266                 {
    267 
    268                 }
    269                 else if (   (pFormatEtc->tymed & TYMED_HGLOBAL)
    270                          && (pFormatEtc->cfFormat == CF_PREFERREDDROPEFFECT))
    271                 {
    272                     HGLOBAL hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE | GMEM_ZEROINIT, sizeof(DWORD));
    273                     DWORD *pdwEffect = (DWORD *)GlobalLock(hData);
    274                     AssertPtr(pdwEffect);
    275                     *pdwEffect = DROPEFFECT_COPY;
    276                     GlobalUnlock(hData);
    277 
    278                     pMedium->hGlobal = hData;
    279                     pMedium->tymed = TYMED_HGLOBAL;
    280                 }
    281                 else
    282 #endif
    283                 if (   (pFormatEtc->tymed & TYMED_HGLOBAL)
    284                     && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
    285                     && (pFormatEtc->cfFormat == CF_TEXT))
    286                 {
    287                     pMedium->hGlobal = GlobalAlloc(GHND, mcbData + 1);
    288                     if (pMedium->hGlobal)
    289                     {
    290                         char *pcDst  = (char *)GlobalLock(pMedium->hGlobal);
    291                         memcpy(pcDst, mpvData, mcbData);
    292                         pcDst[mcbData] = '\0';
    293                         GlobalUnlock(pMedium->hGlobal);
    294 
    295                         hr = S_OK;
    296                     }
    297                 }
    298                 else if (   (pFormatEtc->tymed & TYMED_HGLOBAL)
    299                          && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
    300                          && (pFormatEtc->cfFormat == CF_HDROP))
    301                 {
    302                     size_t cchFiles = 0; /* Number of ASCII characters. */
    303                     for (size_t i = 0; i < cFiles; i++)
    304                     {
    305                         cchFiles += strlen(lstFiles.at(i).c_str());
    306                         cchFiles += 1; /* Terminating '\0'. */
    307                     }
    308 
    309                     size_t cbBuf = sizeof(DROPFILES) + ((cchFiles + 1) * sizeof(RTUTF16));
    310                     DROPFILES *pBuf = (DROPFILES *)RTMemAllocZ(cbBuf);
    311                     if (pBuf)
    312                     {
    313                         pBuf->pFiles = sizeof(DROPFILES);
    314                         pBuf->fWide = 1; /* We use unicode. Always. */
    315 
    316                         uint8_t *pCurFile = (uint8_t *)pBuf + pBuf->pFiles;
    317                         AssertPtr(pCurFile);
    318 
    319                         for (size_t i = 0; i < cFiles && RT_SUCCESS(rc); i++)
    320                         {
    321                             size_t cchCurFile;
    322                             PRTUTF16 pwszFile;
    323                             rc = RTStrToUtf16(lstFiles.at(i).c_str(), &pwszFile);
    324                             if (RT_SUCCESS(rc))
    325                             {
    326                                 cchCurFile = RTUtf16Len(pwszFile);
    327                                 Assert(cchCurFile);
    328                                 memcpy(pCurFile, pwszFile, cchCurFile * sizeof(RTUTF16));
    329                                 RTUtf16Free(pwszFile);
    330                             }
    331                             else
    332                                 break;
    333 
    334                             pCurFile += cchCurFile * sizeof(RTUTF16);
    335 
    336                             /* Terminate current file name. */
    337                             *pCurFile = L'\0';
    338                             pCurFile += sizeof(RTUTF16);
    339                         }
    340 
    341                         if (RT_SUCCESS(rc))
    342                         {
    343                             *pCurFile = L'\0'; /* Final list terminator. */
    344 
    345                             pMedium->tymed = TYMED_HGLOBAL;
    346                             pMedium->pUnkForRelease = NULL;
    347                             pMedium->hGlobal = GlobalAlloc(  GMEM_ZEROINIT
    348                                                            | GMEM_MOVEABLE
    349                                                            | GMEM_DDESHARE, cbBuf);
    350                             if (pMedium->hGlobal)
    351                             {
    352                                 LPVOID pMem = GlobalLock(pMedium->hGlobal);
    353                                 if (pMem)
    354                                 {
    355                                     memcpy(pMem, pBuf, cbBuf);
    356                                     GlobalUnlock(pMedium->hGlobal);
    357 
    358                                     hr = S_OK;
    359                                 }
    360                             }
    361                         }
    362 
    363                         RTMemFree(pBuf);
    364                     }
    365                     else
    366                         rc = VERR_NO_MEMORY;
    367                 }
    368             }
    369 
    370             if (RT_FAILURE(rc))
    371                 hr = DV_E_FORMATETC;
    372         }
    373         /*
    374          * Plain text handling.
    375          */
    376         else if (   mstrFormat.equalsIgnoreCase("text/plain")
    377                  || mstrFormat.equalsIgnoreCase("text/html")
    378                  || mstrFormat.equalsIgnoreCase("text/plain;charset=utf-8")
    379                  || mstrFormat.equalsIgnoreCase("text/plain;charset=utf-16")
    380                  || mstrFormat.equalsIgnoreCase("text/richtext")
    381                  || mstrFormat.equalsIgnoreCase("UTF8_STRING")
    382                  || mstrFormat.equalsIgnoreCase("TEXT")
    383                  || mstrFormat.equalsIgnoreCase("STRING"))
    384         {
    385             pMedium->hGlobal = GlobalAlloc(GHND, mcbData + 1);
    386             if (pMedium->hGlobal)
    387             {
    388                 char *pcDst  = (char *)GlobalLock(pMedium->hGlobal);
    389                 memcpy(pcDst, mpvData, mcbData);
    390                 pcDst[mcbData] = '\0';
    391                 GlobalUnlock(pMedium->hGlobal);
    392 
    393                 hr = S_OK;
    394             }
    395         }
    396         else
    397             LogRel(("Clipboard: Error: Format '%s' not implemented\n", mstrFormat.c_str()));
    398     }
    399 
    400     /* Error handling; at least return some basic data. */
    401     if (FAILED(hr))
    402     {
    403         LogFlowFunc(("Copying medium ...\n"));
    404         switch (pThisMedium->tymed)
    405         {
    406 
    407         case TYMED_HGLOBAL:
    408             pMedium->hGlobal = (HGLOBAL)OleDuplicateData(pThisMedium->hGlobal,
    409                                                          pThisFormat->cfFormat, NULL);
    410             break;
    411 
    412         default:
    413             break;
    414         }
    415 
    416         pMedium->tymed          = pThisFormat->tymed;
    417         pMedium->pUnkForRelease = NULL;
    418351    }
    419352
    420353    if (hr == DV_E_FORMATETC)
    421         LogRel(("Clipboard: Error handling format '%s' (%RU32 bytes)\n", mstrFormat.c_str(), mcbData));
     354        LogRel(("Clipboard: Error handling format\n"));
    422355
    423356    LogFlowFunc(("hr=%Rhrc\n", hr));
     
    437370    RT_NOREF(pFormatEtc, pMedium);
    438371    LogFlowFunc(("\n"));
    439     return DATA_E_FORMATETC;
     372    return E_NOTIMPL;
    440373}
    441374
     
    450383{
    451384    LogFlowFunc(("\n"));
    452     return (LookupFormatEtc(pFormatEtc, NULL /* puIndex */)) ? S_OK : DV_E_FORMATETC;
     385    return (lookupFormatEtc(pFormatEtc, NULL /* puIndex */)) ? S_OK : DV_E_FORMATETC;
    453386}
    454387
     
    466399{
    467400    RT_NOREF(pFormatEtc, pMedium, fRelease);
     401    LogFlowFunc(("\n"));
     402
    468403    return E_NOTIMPL;
    469404}
     
    501436}
    502437
     438#ifdef VBOX_WITH_SHARED_CLIPBOARD_WIN_ASYNC
     439/*
     440 * IDataObjectAsyncCapability methods.
     441 */
     442
     443STDMETHODIMP VBoxClipboardWinDataObject::EndOperation(HRESULT hResult, IBindCtx* pbcReserved, DWORD dwEffects)
     444{
     445     RT_NOREF(hResult, pbcReserved, dwEffects);
     446     return E_NOTIMPL;
     447}
     448
     449STDMETHODIMP VBoxClipboardWinDataObject::GetAsyncMode(BOOL* pfIsOpAsync)
     450{
     451     RT_NOREF(pfIsOpAsync);
     452     return E_NOTIMPL;
     453}
     454
     455STDMETHODIMP VBoxClipboardWinDataObject::InOperation(BOOL* pfInAsyncOp)
     456{
     457     RT_NOREF(pfInAsyncOp);
     458     return E_NOTIMPL;
     459}
     460
     461STDMETHODIMP VBoxClipboardWinDataObject::SetAsyncMode(BOOL fDoOpAsync)
     462{
     463     RT_NOREF(fDoOpAsync);
     464     return E_NOTIMPL;
     465}
     466
     467STDMETHODIMP VBoxClipboardWinDataObject::StartOperation(IBindCtx* pbcReserved)
     468{
     469     RT_NOREF(pbcReserved);
     470     return E_NOTIMPL;
     471}
     472#endif /* VBOX_WITH_SHARED_CLIPBOARD_WIN_ASYNC */
     473
    503474/*
    504475 * Own stuff.
    505476 */
    506477
    507 int VBoxClipboardWinDataObject::Abort(void)
    508 {
    509     LogFlowFunc(("Aborting ...\n"));
    510     mStatus = Aborted;
    511     return RTSemEventSignal(mEventDropped);
     478int VBoxClipboardWinDataObject::Init(uint32_t idClient)
     479{
     480    muClientID = idClient;
     481
     482    LogFlowFuncLeaveRC(VINF_SUCCESS);
     483    return VINF_SUCCESS;
    512484}
    513485
     
    595567}
    596568
    597 bool VBoxClipboardWinDataObject::LookupFormatEtc(LPFORMATETC pFormatEtc, ULONG *puIndex)
     569bool VBoxClipboardWinDataObject::lookupFormatEtc(LPFORMATETC pFormatEtc, ULONG *puIndex)
    598570{
    599571    AssertReturn(pFormatEtc, false);
     
    622594}
    623595
    624 /* static */
    625 HGLOBAL VBoxClipboardWinDataObject::MemDup(HGLOBAL hMemSource)
    626 {
    627     DWORD dwLen    = GlobalSize(hMemSource);
    628     AssertReturn(dwLen, NULL);
    629     PVOID pvSource = GlobalLock(hMemSource);
    630     if (pvSource)
    631     {
    632         PVOID pvDest = GlobalAlloc(GMEM_FIXED, dwLen);
    633         if (pvDest)
    634             memcpy(pvDest, pvSource, dwLen);
    635 
    636         GlobalUnlock(hMemSource);
    637         return pvDest;
    638     }
    639 
    640     return NULL;
    641 }
    642 
    643 void VBoxClipboardWinDataObject::RegisterFormat(LPFORMATETC pFormatEtc, CLIPFORMAT clipFormat,
    644                                        TYMED tyMed, LONG lIndex, DWORD dwAspect,
    645                                        DVTARGETDEVICE *pTargetDevice)
     596void VBoxClipboardWinDataObject::registerFormat(LPFORMATETC pFormatEtc, CLIPFORMAT clipFormat,
     597                                                TYMED tyMed, LONG lIndex, DWORD dwAspect,
     598                                                DVTARGETDEVICE *pTargetDevice)
    646599{
    647600    AssertPtr(pFormatEtc);
     
    657610}
    658611
    659 void VBoxClipboardWinDataObject::SetStatus(Status status)
    660 {
    661     LogFlowFunc(("Setting status to %ld\n", status));
    662     mStatus = status;
    663 }
    664 
    665 int VBoxClipboardWinDataObject::Signal(const RTCString &strFormat,
    666                               const void *pvData, uint32_t cbData)
    667 {
    668     int rc;
    669 
    670     if (cbData)
    671     {
    672         mpvData = RTMemAlloc(cbData);
    673         if (mpvData)
    674         {
    675             memcpy(mpvData, pvData, cbData);
    676             mcbData = cbData;
    677             rc = VINF_SUCCESS;
    678         }
    679         else
    680             rc = VERR_NO_MEMORY;
    681     }
    682     else
    683         rc = VINF_SUCCESS;
    684 
    685     if (RT_SUCCESS(rc))
    686     {
    687         mStatus    = Dropped;
    688         mstrFormat = strFormat;
    689     }
    690     else
    691     {
    692         mStatus = Aborted;
    693     }
    694 
    695     /* Signal in any case. */
    696     LogRel2(("Clipboard: Signalling drop event\n"));
    697 
    698     int rc2 = RTSemEventSignal(mEventDropped);
    699     if (RT_SUCCESS(rc))
    700         rc = rc2;
    701 
    702     LogFunc(("mStatus=%RU32, rc=%Rrc\n", mStatus, rc));
    703     return rc;
    704 }
    705 
  • trunk/src/VBox/GuestHost/SharedClipboard/ClipboardStreamImpl-win.cpp

    r78440 r78474  
    2525#include <iprt/asm.h>
    2626#include <iprt/ldr.h>
     27#include <iprt/thread.h>
    2728
    2829#include <VBox/GuestHost/SharedClipboard.h>
     
    4344*********************************************************************************************************************************/
    4445
     46
     47
     48VBoxClipboardWinStreamImpl::VBoxClipboardWinStreamImpl(void)
     49    : m_lRefCount(1)
     50{
     51
     52}
     53
     54VBoxClipboardWinStreamImpl::~VBoxClipboardWinStreamImpl(void)
     55{
     56}
     57
     58/*
     59 * IUnknown methods.
     60 */
     61
     62STDMETHODIMP VBoxClipboardWinStreamImpl::QueryInterface(REFIID iid, void ** ppvObject)
     63{
     64    AssertPtrReturn(ppvObject, E_INVALIDARG);
     65
     66    if (   iid == IID_IStream
     67        || iid == IID_IUnknown)
     68    {
     69        AddRef();
     70        *ppvObject = this;
     71        return S_OK;
     72    }
     73
     74    *ppvObject = 0;
     75    return E_NOINTERFACE;
     76}
     77
     78STDMETHODIMP_(ULONG) VBoxClipboardWinStreamImpl::AddRef(void)
     79{
     80    LONG lCount = InterlockedIncrement(&m_lRefCount);
     81    LogFlowFunc(("lCount=%RI32\n", lCount));
     82    return lCount;
     83}
     84
     85STDMETHODIMP_(ULONG) VBoxClipboardWinStreamImpl::Release(void)
     86{
     87    LONG lCount = InterlockedDecrement(&m_lRefCount);
     88    LogFlowFunc(("lCount=%RI32\n", m_lRefCount));
     89    if (lCount == 0)
     90    {
     91        delete this;
     92        return 0;
     93    }
     94
     95    return lCount;
     96}
     97
     98/*
     99 * IStream methods.
     100 */
     101
     102STDMETHODIMP VBoxClipboardWinStreamImpl::Clone(IStream** ppStream)
     103{
     104    RT_NOREF(ppStream);
     105
     106    LogFlowFuncEnter();
     107    return E_NOTIMPL;
     108}
     109
     110STDMETHODIMP VBoxClipboardWinStreamImpl::Commit(DWORD dwFrags)
     111{
     112    RT_NOREF(dwFrags);
     113
     114    LogFlowFuncEnter();
     115    return E_NOTIMPL;
     116}
     117
     118STDMETHODIMP VBoxClipboardWinStreamImpl::CopyTo(IStream* pDestStream, ULARGE_INTEGER nBytesToCopy, ULARGE_INTEGER* nBytesRead,
     119                                                ULARGE_INTEGER* nBytesWritten)
     120{
     121    RT_NOREF(pDestStream, nBytesToCopy, nBytesRead, nBytesWritten);
     122
     123    LogFlowFuncEnter();
     124    return E_NOTIMPL;
     125}
     126
     127STDMETHODIMP VBoxClipboardWinStreamImpl::LockRegion(ULARGE_INTEGER nStart, ULARGE_INTEGER nBytes,DWORD dwFlags)
     128{
     129    RT_NOREF(nStart, nBytes, dwFlags);
     130
     131    LogFlowFuncEnter();
     132    return E_NOTIMPL;
     133}
     134
     135static ULONG cbFileSize = _1M;
     136static ULONG cbSizeRead = 0;
     137
     138STDMETHODIMP VBoxClipboardWinStreamImpl::Read(void* pvBuffer, ULONG nBytesToRead, ULONG* nBytesRead)
     139{
     140    /* If the file size is 0, already return at least 1 byte, else the whole operation will fail. */
     141
     142    ULONG cbToRead = RT_MIN(cbFileSize - cbSizeRead,  _4K /* nBytesToRead */);
     143
     144    if (cbToRead > nBytesToRead)
     145        cbToRead = nBytesToRead;
     146
     147    LogFlowFunc(("pvBuffer=%p, nBytesToRead=%u -> cbSizeRead=%u, cbToRead=%u\n", pvBuffer, nBytesToRead, cbSizeRead, cbToRead));
     148
     149    if (cbToRead)
     150    {
     151        memset(pvBuffer, cbToRead, 0x65);
     152        cbSizeRead += cbToRead;
     153    }
     154
     155    if (nBytesRead)
     156        *nBytesRead = cbToRead;
     157
     158    if (cbSizeRead == cbFileSize)
     159        cbSizeRead = 0;
     160
     161    return S_OK;
     162}
     163
     164STDMETHODIMP VBoxClipboardWinStreamImpl::Revert(void)
     165{
     166    LogFlowFuncEnter();
     167    return E_NOTIMPL;
     168}
     169
     170STDMETHODIMP VBoxClipboardWinStreamImpl::Seek(LARGE_INTEGER nMove, DWORD dwOrigin, ULARGE_INTEGER* nNewPos)
     171{
     172    RT_NOREF(nMove, dwOrigin, nNewPos);
     173
     174    LogFlowFuncEnter();
     175    return E_NOTIMPL;
     176}
     177
     178STDMETHODIMP VBoxClipboardWinStreamImpl::SetSize(ULARGE_INTEGER nNewSize)
     179{
     180    RT_NOREF(nNewSize);
     181
     182    LogFlowFuncEnter();
     183    return E_NOTIMPL;
     184}
     185
     186STDMETHODIMP VBoxClipboardWinStreamImpl::Stat(STATSTG* statstg, DWORD dwFlags)
     187{
     188    RT_NOREF(statstg, dwFlags);
     189
     190    LogFlowFuncEnter();
     191    return E_NOTIMPL;
     192}
     193
     194STDMETHODIMP VBoxClipboardWinStreamImpl::UnlockRegion(ULARGE_INTEGER nStart, ULARGE_INTEGER nBytes, DWORD dwFlags)
     195{
     196    RT_NOREF(nStart, nBytes, dwFlags);
     197
     198    LogFlowFuncEnter();
     199    return E_NOTIMPL;
     200}
     201
     202STDMETHODIMP VBoxClipboardWinStreamImpl::Write(const void* pvBuffer, ULONG nBytesToRead, ULONG* nBytesRead)
     203{
     204    RT_NOREF(pvBuffer, nBytesToRead, nBytesRead);
     205
     206    LogFlowFuncEnter();
     207    return E_NOTIMPL;
     208}
     209
     210/*
     211 * Own stuff.
     212 */
     213
     214/* static */
     215HRESULT VBoxClipboardWinStreamImpl::Create(IStream **ppStream)
     216{
     217    VBoxClipboardWinStreamImpl *pStream = new VBoxClipboardWinStreamImpl();
     218    if (pStream)
     219    {
     220        pStream->AddRef();
     221
     222        *ppStream = pStream;
     223        return S_OK;
     224    }
     225
     226    return E_FAIL;
     227}
     228
  • trunk/src/VBox/GuestHost/SharedClipboard/clipboard-win.cpp

    r78440 r78474  
    8787    int rc;
    8888
     89    LogFlowFuncEnter();
     90
    8991    const BOOL fRc = CloseClipboard();
    9092    if (RT_UNLIKELY(!fRc))
    9193    {
    9294        const DWORD dwLastErr = GetLastError();
    93         rc = RTErrConvertFromWin32(dwLastErr);
     95        if (dwLastErr == ERROR_CLIPBOARD_NOT_OPEN)
     96            rc = VERR_INVALID_STATE;
     97        else
     98            rc = RTErrConvertFromWin32(dwLastErr);
     99
    94100        LogFunc(("Failed with %Rrc (0x%x)\n", rc, dwLastErr));
    95101    }
     
    108114{
    109115    int rc;
     116
     117    LogFlowFuncEnter();
    110118
    111119    const BOOL fRc = EmptyClipboard();
     
    113121    {
    114122        const DWORD dwLastErr = GetLastError();
    115         rc = RTErrConvertFromWin32(dwLastErr);
     123        if (dwLastErr == ERROR_CLIPBOARD_NOT_OPEN)
     124            rc = VERR_INVALID_STATE;
     125        else
     126            rc = RTErrConvertFromWin32(dwLastErr);
     127
    116128        LogFunc(("Failed with %Rrc (0x%x)\n", rc, dwLastErr));
    117129    }
     
    265277}
    266278
     279VBOXCLIPBOARDFORMAT VBoxClipboardWinClipboardFormatToVBox(UINT uFormat)
     280{
     281    /* Insert the requested clipboard format data into the clipboard. */
     282    VBOXCLIPBOARDFORMAT vboxFormat = VBOX_SHARED_CLIPBOARD_FMT_NONE;
     283
     284    switch (uFormat)
     285    {
     286      case CF_UNICODETEXT:
     287          vboxFormat = VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
     288          break;
     289
     290      case CF_DIB:
     291          vboxFormat = VBOX_SHARED_CLIPBOARD_FMT_BITMAP;
     292          break;
     293
     294      default:
     295          if (uFormat >= 0xC000) /** Formats registered with RegisterClipboardFormat() start at this index. */
     296          {
     297              TCHAR szFormatName[256]; /** @todo r=andy Do we need Unicode support here as well? */
     298              int cActual = GetClipboardFormatName(uFormat, szFormatName, sizeof(szFormatName) / sizeof(TCHAR));
     299              if (cActual)
     300              {
     301                  LogFunc(("szFormatName=%s\n", szFormatName));
     302
     303                  if (RTStrCmp(szFormatName, VBOX_CLIPBOARD_WIN_REGFMT_HTML) == 0)
     304                      vboxFormat = VBOX_SHARED_CLIPBOARD_FMT_HTML;
     305#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
     306                  else if (RTStrCmp(szFormatName, VBOX_CLIPBOARD_WIN_REGFMT_URI_LIST) == 0)
     307                      vboxFormat = VBOX_SHARED_CLIPBOARD_FMT_URI_LIST;
     308#endif
     309              }
     310          }
     311          break;
     312    }
     313
     314    return vboxFormat;
     315}
     316
    267317/**
    268318 * Retrieves all supported clipboard formats of a specific clipboard.
     
    270320 * @returns VBox status code.
    271321 * @param   pCtx                Windows clipboard context to retrieve formats for.
    272  * @param   puFormats           Where to store the retrieved formats of type VBOX_SHARED_CLIPBOARD_FMT_ (bitmask).
    273  */
    274 int VBoxClipboardWinGetFormats(PVBOXCLIPBOARDWINCTX pCtx, uint32_t *puFormats)
     322 * @param   pfFormats           Where to store the retrieved formats of type VBOX_SHARED_CLIPBOARD_FMT_ (bitmask).
     323 */
     324int VBoxClipboardWinGetFormats(PVBOXCLIPBOARDWINCTX pCtx, PVBOXCLIPBOARDFORMATS pfFormats)
    275325{
    276326    AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
    277     AssertPtrReturn(puFormats, VERR_INVALID_POINTER);
    278 
    279     uint32_t uFormats = VBOX_SHARED_CLIPBOARD_FMT_NONE;
     327    AssertPtrReturn(pfFormats, VERR_INVALID_POINTER);
     328
     329    VBOXCLIPBOARDFORMATS fFormats = VBOX_SHARED_CLIPBOARD_FMT_NONE;
    280330
    281331    /* Query list of available formats and report to host. */
     
    283333    if (RT_SUCCESS(rc))
    284334    {
    285         UINT uCurFormat = 0;
     335        UINT uCurFormat = 0; /* Must be set to zero for EnumClipboardFormats(). */
    286336        while ((uCurFormat = EnumClipboardFormats(uCurFormat)) != 0)
    287         {
    288             LogFlowFunc(("uFormat = 0x%08X\n", uCurFormat));
    289             switch (uCurFormat)
    290             {
    291                 case CF_UNICODETEXT:
    292                 case CF_TEXT:
    293                     uFormats |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
    294                     break;
    295 
    296                 case CF_DIB:
    297                 case CF_BITMAP:
    298                     uFormats |= VBOX_SHARED_CLIPBOARD_FMT_BITMAP;
    299                     break;
    300 
    301 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
    302                 case CF_HDROP:
    303                     uFormats |= VBOX_SHARED_CLIPBOARD_FMT_URI_LIST;
    304                     break;
    305 #endif
    306                 default:
    307                 {
    308                     if (uCurFormat >= 0xC000) /** @todo r=andy Find a define for this. */
    309                     {
    310                         TCHAR szFormatName[256]; /** @todo r=andy Is this enough? */
    311                         int cActual = GetClipboardFormatName(uCurFormat, szFormatName, sizeof(szFormatName)/sizeof (TCHAR));
    312                         if (cActual)
    313                         {
    314                             if (strcmp (szFormatName, "HTML Format") == 0)
    315                             {
    316                                 uFormats |= VBOX_SHARED_CLIPBOARD_FMT_HTML;
    317                             }
    318                         }
    319                     }
    320                     break;
    321                 }
    322             }
    323         }
     337            fFormats |= VBoxClipboardWinClipboardFormatToVBox(uCurFormat);
    324338
    325339        int rc2 = VBoxClipboardWinClose();
     
    333347    else
    334348    {
    335         LogFlowFunc(("uFormats = 0x%08X\n", uFormats));
    336         *puFormats = uFormats;
    337     }
    338 
    339     return rc;
    340 }
    341 
     349        LogFlowFunc(("pfFormats=0x%08X\n", pfFormats));
     350        *pfFormats = fFormats;
     351    }
     352
     353    return rc;
     354}
     355
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