VirtualBox

source: vbox/trunk/include/VBox/GuestHost/SharedClipboard-win.h@ 81259

Last change on this file since 81259 was 81259, checked in by vboxsync, 5 years ago

Shared Clipboard/Transfers: Bugfixes.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.3 KB
Line 
1/** @file
2 * Shared Clipboard - Common Guest and Host Code, for Windows OSes.
3 */
4
5/*
6 * Copyright (C) 2006-2019 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 *
16 * The contents of this file may alternatively be used under the terms
17 * of the Common Development and Distribution License Version 1.0
18 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
19 * VirtualBox OSE distribution, in which case the provisions of the
20 * CDDL are applicable instead of those of the GPL.
21 *
22 * You may elect to license modified versions of this file under the
23 * terms and conditions of either the GPL or the CDDL or both.
24 */
25
26#ifndef VBOX_INCLUDED_GuestHost_SharedClipboard_win_h
27#define VBOX_INCLUDED_GuestHost_SharedClipboard_win_h
28#ifndef RT_WITHOUT_PRAGMA_ONCE
29# pragma once
30#endif
31
32#include <iprt/critsect.h>
33#include <iprt/types.h>
34#include <iprt/win/windows.h>
35
36#include <VBox/GuestHost/SharedClipboard.h>
37
38# ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
39# include <vector>
40
41# include <iprt/cpp/ministring.h> /* For RTCString. */
42# include <iprt/win/shlobj.h> /* For DROPFILES and friends. */
43# include <VBox/com/string.h> /* For Utf8Str. */
44# include <oleidl.h>
45
46# include <VBox/GuestHost/SharedClipboard-transfers.h>
47
48using namespace com;
49# endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
50
51#ifndef WM_CLIPBOARDUPDATE
52# define WM_CLIPBOARDUPDATE 0x031D
53#endif
54
55#define SHCL_WIN_WNDCLASS_NAME "VBoxSharedClipboardClass"
56
57/** See: https://docs.microsoft.com/en-us/windows/desktop/dataxchg/html-clipboard-format
58 * Do *not* change the name, as this will break compatbility with other (legacy) applications! */
59#define SHCL_WIN_REGFMT_HTML "HTML Format"
60
61/** Default timeout (in ms) for passing down messages down the clipboard chain. */
62#define SHCL_WIN_CBCHAIN_TIMEOUT_MS 5000
63
64/** Reports clipboard formats. */
65#define SHCL_WIN_WM_REPORT_FORMATS WM_USER
66/** Reads data from the clipboard and sends it to the destination. */
67#define SHCL_WIN_WM_READ_DATA WM_USER + 1
68#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
69/** Starts a transfer on the guest.
70 * This creates the necessary IDataObject in the matching window thread. */
71# define SHCL_WIN_WM_TRANSFER_START WM_USER + 2
72#endif
73
74/* Dynamically load clipboard functions from User32.dll. */
75typedef BOOL WINAPI FNADDCLIPBOARDFORMATLISTENER(HWND);
76typedef FNADDCLIPBOARDFORMATLISTENER *PFNADDCLIPBOARDFORMATLISTENER;
77
78typedef BOOL WINAPI FNREMOVECLIPBOARDFORMATLISTENER(HWND);
79typedef FNREMOVECLIPBOARDFORMATLISTENER *PFNREMOVECLIPBOARDFORMATLISTENER;
80
81/**
82 * Structure for keeping function pointers for the new clipboard API.
83 * If the new API is not available, those function pointer are NULL.
84 */
85typedef struct _SHCLWINAPINEW
86{
87 PFNADDCLIPBOARDFORMATLISTENER pfnAddClipboardFormatListener;
88 PFNREMOVECLIPBOARDFORMATLISTENER pfnRemoveClipboardFormatListener;
89} SHCLWINAPINEW, *PSHCLWINAPINEW;
90
91/**
92 * Structure for keeping variables which are needed to drive the old clipboard API.
93 */
94typedef struct _SHCLWINAPIOLD
95{
96 /** Timer ID for the refresh timer. */
97 UINT timerRefresh;
98 /** Whether "pinging" the clipboard chain currently is in progress or not. */
99 bool fCBChainPingInProcess;
100} SHCLWINAPIOLD, *PSHCLWINAPIOLD;
101
102/**
103 * Structure for maintaining a Shared Clipboard context on Windows platforms.
104 */
105typedef struct _SHCLWINCTX
106{
107 /** Critical section to serialize access. */
108 RTCRITSECT CritSect;
109 /** Window handle of our (invisible) clipbaord window. */
110 HWND hWnd;
111 /** Window handle which is next to us in the clipboard chain. */
112 HWND hWndNextInChain;
113 /** Window handle of the clipboard owner *if* we are the owner. */
114 HWND hWndClipboardOwnerUs;
115 /** Structure for maintaining the new clipboard API. */
116 SHCLWINAPINEW newAPI;
117 /** Structure for maintaining the old clipboard API. */
118 SHCLWINAPIOLD oldAPI;
119} SHCLWINCTX, *PSHCLWINCTX;
120
121int SharedClipboardWinOpen(HWND hWnd);
122int SharedClipboardWinClose(void);
123int SharedClipboardWinClear(void);
124
125int SharedClipboardWinCtxInit(PSHCLWINCTX pWinCtx);
126void SharedClipboardWinCtxDestroy(PSHCLWINCTX pWinCtx);
127
128int SharedClipboardWinCheckAndInitNewAPI(PSHCLWINAPINEW pAPI);
129bool SharedClipboardWinIsNewAPI(PSHCLWINAPINEW pAPI);
130
131int SharedClipboardWinChainAdd(PSHCLWINCTX pCtx);
132int SharedClipboardWinChainRemove(PSHCLWINCTX pCtx);
133VOID CALLBACK SharedClipboardWinChainPingProc(HWND hWnd, UINT uMsg, ULONG_PTR dwData, LRESULT lResult);
134LRESULT SharedClipboardWinChainPassToNext(PSHCLWINCTX pWinCtx, UINT msg, WPARAM wParam, LPARAM lParam);
135
136SHCLFORMAT SharedClipboardWinClipboardFormatToVBox(UINT uFormat);
137int SharedClipboardWinGetFormats(PSHCLWINCTX pCtx, PSHCLFORMATDATA pFormats);
138
139#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
140int SharedClipboardWinGetRoots(PSHCLWINCTX pWinCtx, PSHCLTRANSFER pTransfer);
141int SharedClipboardWinDropFilesToStringList(DROPFILES *pDropFiles, char **papszList, uint32_t *pcbList);
142#endif
143
144int SharedClipboardWinGetCFHTMLHeaderValue(const char *pszSrc, const char *pszOption, uint32_t *puValue);
145bool SharedClipboardWinIsCFHTML(const char *pszSource);
146int SharedClipboardWinConvertCFHTMLToMIME(const char *pszSource, const uint32_t cch, char **ppszOutput, uint32_t *pcbOutput);
147int SharedClipboardWinConvertMIMEToCFHTML(const char *pszSource, size_t cb, char **ppszOutput, uint32_t *pcbOutput);
148
149LRESULT SharedClipboardWinHandleWMChangeCBChain(PSHCLWINCTX pWinCtx, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
150int SharedClipboardWinHandleWMDestroy(PSHCLWINCTX pWinCtx);
151int SharedClipboardWinHandleWMRenderAllFormats(PSHCLWINCTX pWinCtx, HWND hWnd);
152int SharedClipboardWinHandleWMTimer(PSHCLWINCTX pWinCtx);
153
154int SharedClipboardWinAnnounceFormats(PSHCLWINCTX pWinCtx, SHCLFORMATS fFormats);
155#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
156int SharedClipboardWinTransferCreate(PSHCLWINCTX pWinCtx, PSHCLTRANSFER pTransfer);
157void SharedClipboardWinTransferDestroy(PSHCLWINCTX pWinCtx, PSHCLTRANSFER pTransfer);
158#endif
159
160# ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
161class SharedClipboardTransferList;
162# ifndef FILEGROUPDESCRIPTOR
163class FILEGROUPDESCRIPTOR;
164# endif
165
166class SharedClipboardWinDataObject : public IDataObject //, public IDataObjectAsyncCapability
167{
168public:
169
170 enum Status
171 {
172 Uninitialized = 0,
173 Initialized
174 };
175
176public:
177
178 SharedClipboardWinDataObject(PSHCLTRANSFER pTransfer,
179 LPFORMATETC pFormatEtc = NULL, LPSTGMEDIUM pStgMed = NULL, ULONG cFormats = 0);
180 virtual ~SharedClipboardWinDataObject(void);
181
182public: /* IUnknown methods. */
183
184 STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject);
185 STDMETHOD_(ULONG, AddRef)(void);
186 STDMETHOD_(ULONG, Release)(void);
187
188public: /* IDataObject methods. */
189
190 STDMETHOD(GetData)(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium);
191 STDMETHOD(GetDataHere)(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium);
192 STDMETHOD(QueryGetData)(LPFORMATETC pFormatEtc);
193 STDMETHOD(GetCanonicalFormatEtc)(LPFORMATETC pFormatEct, LPFORMATETC pFormatEtcOut);
194 STDMETHOD(SetData)(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium, BOOL fRelease);
195 STDMETHOD(EnumFormatEtc)(DWORD dwDirection, IEnumFORMATETC **ppEnumFormatEtc);
196 STDMETHOD(DAdvise)(LPFORMATETC pFormatEtc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection);
197 STDMETHOD(DUnadvise)(DWORD dwConnection);
198 STDMETHOD(EnumDAdvise)(IEnumSTATDATA **ppEnumAdvise);
199
200#ifdef VBOX_WITH_SHARED_CLIPBOARD_WIN_ASYNC
201public: /* IDataObjectAsyncCapability methods. */
202
203 STDMETHOD(EndOperation)(HRESULT hResult, IBindCtx* pbcReserved, DWORD dwEffects);
204 STDMETHOD(GetAsyncMode)(BOOL* pfIsOpAsync);
205 STDMETHOD(InOperation)(BOOL* pfInAsyncOp);
206 STDMETHOD(SetAsyncMode)(BOOL fDoOpAsync);
207 STDMETHOD(StartOperation)(IBindCtx* pbcReserved);
208#endif /* VBOX_WITH_SHARED_CLIPBOARD_WIN_ASYNC */
209
210public:
211
212 int Init(void);
213 void OnTransferComplete(int rc = VINF_SUCCESS);
214 void OnTransferCanceled();
215
216public:
217
218 static DECLCALLBACK(int) readThread(RTTHREAD ThreadSelf, void *pvUser);
219
220 static const char* ClipboardFormatToString(CLIPFORMAT fmt);
221
222protected:
223
224 static int Thread(RTTHREAD hThread, void *pvUser);
225
226 int readDir(PSHCLTRANSFER pTransfer, const Utf8Str &strPath);
227
228 int copyToHGlobal(const void *pvData, size_t cbData, UINT fFlags, HGLOBAL *phGlobal);
229 int createFileGroupDescriptorFromTransfer(PSHCLTRANSFER pTransfer,
230 bool fUnicode, HGLOBAL *phGlobal);
231
232 bool lookupFormatEtc(LPFORMATETC pFormatEtc, ULONG *puIndex);
233 void registerFormat(LPFORMATETC pFormatEtc, CLIPFORMAT clipFormat, TYMED tyMed = TYMED_HGLOBAL,
234 LONG lindex = -1, DWORD dwAspect = DVASPECT_CONTENT, DVTARGETDEVICE *pTargetDevice = NULL);
235protected:
236
237 /**
238 * Structure for keeping a single file system object entry.
239 */
240 struct FSOBJENTRY
241 {
242 /** Relative path of the object. */
243 Utf8Str strPath;
244 /** Related (cached) object information. */
245 SHCLFSOBJINFO objInfo;
246 };
247
248 /** Vector containing file system objects with its (cached) objection information. */
249 typedef std::vector<FSOBJENTRY> FsObjEntryList;
250
251 Status m_enmStatus;
252 LONG m_lRefCount;
253 ULONG m_cFormats;
254 LPFORMATETC m_pFormatEtc;
255 LPSTGMEDIUM m_pStgMedium;
256 PSHCLTRANSFER m_pTransfer;
257 IStream *m_pStream;
258 ULONG m_uObjIdx;
259 /** List of (cached) file system objects. */
260 FsObjEntryList m_lstEntries;
261 /** Whether the transfer thread is running. */
262 bool m_fRunning;
263 /** Event being triggered when reading the transfer list been completed. */
264 RTSEMEVENT m_EventListComplete;
265 /** Event being triggered when the transfer has been completed. */
266 RTSEMEVENT m_EventTransferComplete;
267 UINT m_cfFileDescriptorA;
268 UINT m_cfFileDescriptorW;
269 UINT m_cfFileContents;
270};
271
272class SharedClipboardWinEnumFormatEtc : public IEnumFORMATETC
273{
274public:
275
276 SharedClipboardWinEnumFormatEtc(LPFORMATETC pFormatEtc, ULONG cFormats);
277 virtual ~SharedClipboardWinEnumFormatEtc(void);
278
279public: /* IUnknown methods. */
280
281 STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject);
282 STDMETHOD_(ULONG, AddRef)(void);
283 STDMETHOD_(ULONG, Release)(void);
284
285public: /* IEnumFORMATETC methods. */
286
287 STDMETHOD(Next)(ULONG cFormats, LPFORMATETC pFormatEtc, ULONG *pcFetched);
288 STDMETHOD(Skip)(ULONG cFormats);
289 STDMETHOD(Reset)(void);
290 STDMETHOD(Clone)(IEnumFORMATETC **ppEnumFormatEtc);
291
292public:
293
294 static void CopyFormat(LPFORMATETC pFormatDest, LPFORMATETC pFormatSource);
295 static HRESULT CreateEnumFormatEtc(UINT cFormats, LPFORMATETC pFormatEtc, IEnumFORMATETC **ppEnumFormatEtc);
296
297private:
298
299 LONG m_lRefCount;
300 ULONG m_nIndex;
301 ULONG m_nNumFormats;
302 LPFORMATETC m_pFormatEtc;
303};
304
305/**
306 * Own IStream implementation to implement file-based clipboard operations
307 * through HGCM. Needed on Windows hosts and guests.
308 */
309class SharedClipboardWinStreamImpl : public IStream
310{
311public:
312
313 SharedClipboardWinStreamImpl(SharedClipboardWinDataObject *pParent, PSHCLTRANSFER pTransfer,
314 const Utf8Str &strPath, PSHCLFSOBJINFO pObjInfo);
315 virtual ~SharedClipboardWinStreamImpl(void);
316
317public: /* IUnknown methods. */
318
319 STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject);
320 STDMETHOD_(ULONG, AddRef)(void);
321 STDMETHOD_(ULONG, Release)(void);
322
323public: /* IStream methods. */
324
325 STDMETHOD(Clone)(IStream** ppStream);
326 STDMETHOD(Commit)(DWORD dwFrags);
327 STDMETHOD(CopyTo)(IStream* pDestStream, ULARGE_INTEGER nBytesToCopy, ULARGE_INTEGER* nBytesRead, ULARGE_INTEGER* nBytesWritten);
328 STDMETHOD(LockRegion)(ULARGE_INTEGER nStart, ULARGE_INTEGER nBytes,DWORD dwFlags);
329 STDMETHOD(Read)(void* pvBuffer, ULONG nBytesToRead, ULONG* nBytesRead);
330 STDMETHOD(Revert)(void);
331 STDMETHOD(Seek)(LARGE_INTEGER nMove, DWORD dwOrigin, ULARGE_INTEGER* nNewPos);
332 STDMETHOD(SetSize)(ULARGE_INTEGER nNewSize);
333 STDMETHOD(Stat)(STATSTG* statstg, DWORD dwFlags);
334 STDMETHOD(UnlockRegion)(ULARGE_INTEGER nStart, ULARGE_INTEGER nBytes, DWORD dwFlags);
335 STDMETHOD(Write)(const void* pvBuffer, ULONG nBytesToRead, ULONG* nBytesRead);
336
337public: /* Own methods. */
338
339 static HRESULT Create(SharedClipboardWinDataObject *pParent, PSHCLTRANSFER pTransfer, const Utf8Str &strPath,
340 PSHCLFSOBJINFO pObjInfo, IStream **ppStream);
341private:
342
343 /** Pointer to the parent data object. */
344 SharedClipboardWinDataObject *m_pParent;
345 /** The stream object's current reference count. */
346 LONG m_lRefCount;
347 /** Pointer to the associated Shared Clipboard transfer. */
348 PSHCLTRANSFER m_pTransfer;
349 /** The object handle to use. */
350 SHCLOBJHANDLE m_hObj;
351 /** Object path. */
352 Utf8Str m_strPath;
353 /** (Cached) object information. */
354 SHCLFSOBJINFO m_objInfo;
355 /** Number of bytes already processed. */
356 uint64_t m_cbProcessed;
357 /** Whether this object already is in completed state or not. */
358 bool m_fIsComplete;
359};
360
361/**
362 * Class for Windows-specifics for maintaining a single Shared Clipboard transfer.
363 * Set as pvUser / cbUser in SHCLTRANSFERCTX.
364 */
365class SharedClipboardWinTransferCtx
366{
367public:
368 SharedClipboardWinTransferCtx()
369 : pDataObj(NULL) { }
370
371 virtual ~SharedClipboardWinTransferCtx()
372 {
373 if (pDataObj)
374 delete pDataObj;
375 }
376
377 /** Pointer to data object to use for this transfer.
378 * Can be NULL if not being used. */
379 SharedClipboardWinDataObject *pDataObj;
380};
381# endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
382#endif /* !VBOX_INCLUDED_GuestHost_SharedClipboard_win_h */
383
Note: See TracBrowser for help on using the repository browser.

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