VirtualBox

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

Last change on this file since 93115 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.6 KB
Line 
1/** @file
2 * Shared Clipboard - Common Guest and Host Code, for Windows OSes.
3 */
4
5/*
6 * Copyright (C) 2006-2022 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 * @todo r=bird: Ignore the misleading statement above. This is only set to
115 * NULL by the initialization code and then it's set to the clipboard owner
116 * after we announce data to the clipboard. So, essentially this will be our
117 * windows handle or NULL. End of story. */
118 HWND hWndClipboardOwnerUs;
119 /** Structure for maintaining the new clipboard API. */
120 SHCLWINAPINEW newAPI;
121 /** Structure for maintaining the old clipboard API. */
122 SHCLWINAPIOLD oldAPI;
123} SHCLWINCTX, *PSHCLWINCTX;
124
125int SharedClipboardWinOpen(HWND hWnd);
126int SharedClipboardWinClose(void);
127int SharedClipboardWinClear(void);
128
129int SharedClipboardWinCtxInit(PSHCLWINCTX pWinCtx);
130void SharedClipboardWinCtxDestroy(PSHCLWINCTX pWinCtx);
131
132int SharedClipboardWinCheckAndInitNewAPI(PSHCLWINAPINEW pAPI);
133bool SharedClipboardWinIsNewAPI(PSHCLWINAPINEW pAPI);
134
135int SharedClipboardWinChainAdd(PSHCLWINCTX pCtx);
136int SharedClipboardWinChainRemove(PSHCLWINCTX pCtx);
137VOID CALLBACK SharedClipboardWinChainPingProc(HWND hWnd, UINT uMsg, ULONG_PTR dwData, LRESULT lResult) RT_NOTHROW_DEF;
138LRESULT SharedClipboardWinChainPassToNext(PSHCLWINCTX pWinCtx, UINT msg, WPARAM wParam, LPARAM lParam);
139
140SHCLFORMAT SharedClipboardWinClipboardFormatToVBox(UINT uFormat);
141int SharedClipboardWinGetFormats(PSHCLWINCTX pCtx, PSHCLFORMATS pfFormats);
142
143#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
144int SharedClipboardWinGetRoots(PSHCLWINCTX pWinCtx, PSHCLTRANSFER pTransfer);
145int SharedClipboardWinDropFilesToStringList(DROPFILES *pDropFiles, char **papszList, uint32_t *pcbList);
146#endif
147
148int SharedClipboardWinGetCFHTMLHeaderValue(const char *pszSrc, const char *pszOption, uint32_t *puValue);
149bool SharedClipboardWinIsCFHTML(const char *pszSource);
150int SharedClipboardWinConvertCFHTMLToMIME(const char *pszSource, const uint32_t cch, char **ppszOutput, uint32_t *pcbOutput);
151int SharedClipboardWinConvertMIMEToCFHTML(const char *pszSource, size_t cb, char **ppszOutput, uint32_t *pcbOutput);
152
153LRESULT SharedClipboardWinHandleWMChangeCBChain(PSHCLWINCTX pWinCtx, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
154int SharedClipboardWinHandleWMDestroy(PSHCLWINCTX pWinCtx);
155int SharedClipboardWinHandleWMRenderAllFormats(PSHCLWINCTX pWinCtx, HWND hWnd);
156int SharedClipboardWinHandleWMTimer(PSHCLWINCTX pWinCtx);
157
158int SharedClipboardWinClearAndAnnounceFormats(PSHCLWINCTX pWinCtx, SHCLFORMATS fFormats, HWND hWnd);
159#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
160int SharedClipboardWinTransferCreate(PSHCLWINCTX pWinCtx, PSHCLTRANSFER pTransfer);
161void SharedClipboardWinTransferDestroy(PSHCLWINCTX pWinCtx, PSHCLTRANSFER pTransfer);
162#endif
163
164# ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
165class SharedClipboardTransferList;
166# ifndef FILEGROUPDESCRIPTOR
167class FILEGROUPDESCRIPTOR;
168# endif
169
170class SharedClipboardWinDataObject : public IDataObject //, public IDataObjectAsyncCapability
171{
172public:
173
174 enum Status
175 {
176 /** The object is uninitialized (not ready). */
177 Uninitialized = 0,
178 /** The object is initialized and ready to use. */
179 Initialized,
180 /** The operation has been successfully completed. */
181 Completed,
182 /** The operation has been canceled. */
183 Canceled,
184 /** An (unrecoverable) error occurred. */
185 Error
186 };
187
188public:
189
190 SharedClipboardWinDataObject(PSHCLTRANSFER pTransfer,
191 LPFORMATETC pFormatEtc = NULL, LPSTGMEDIUM pStgMed = NULL, ULONG cFormats = 0);
192 virtual ~SharedClipboardWinDataObject(void);
193
194public: /* IUnknown methods. */
195
196 STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject);
197 STDMETHOD_(ULONG, AddRef)(void);
198 STDMETHOD_(ULONG, Release)(void);
199
200public: /* IDataObject methods. */
201
202 STDMETHOD(GetData)(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium);
203 STDMETHOD(GetDataHere)(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium);
204 STDMETHOD(QueryGetData)(LPFORMATETC pFormatEtc);
205 STDMETHOD(GetCanonicalFormatEtc)(LPFORMATETC pFormatEct, LPFORMATETC pFormatEtcOut);
206 STDMETHOD(SetData)(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium, BOOL fRelease);
207 STDMETHOD(EnumFormatEtc)(DWORD dwDirection, IEnumFORMATETC **ppEnumFormatEtc);
208 STDMETHOD(DAdvise)(LPFORMATETC pFormatEtc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection);
209 STDMETHOD(DUnadvise)(DWORD dwConnection);
210 STDMETHOD(EnumDAdvise)(IEnumSTATDATA **ppEnumAdvise);
211
212#ifdef VBOX_WITH_SHARED_CLIPBOARD_WIN_ASYNC
213public: /* IDataObjectAsyncCapability methods. */
214
215 STDMETHOD(EndOperation)(HRESULT hResult, IBindCtx* pbcReserved, DWORD dwEffects);
216 STDMETHOD(GetAsyncMode)(BOOL* pfIsOpAsync);
217 STDMETHOD(InOperation)(BOOL* pfInAsyncOp);
218 STDMETHOD(SetAsyncMode)(BOOL fDoOpAsync);
219 STDMETHOD(StartOperation)(IBindCtx* pbcReserved);
220#endif /* VBOX_WITH_SHARED_CLIPBOARD_WIN_ASYNC */
221
222public:
223
224 int Init(void);
225 void OnTransferComplete(int rc = VINF_SUCCESS);
226 void OnTransferCanceled();
227
228public:
229
230 static DECLCALLBACK(int) readThread(RTTHREAD ThreadSelf, void *pvUser);
231
232 static void logFormat(CLIPFORMAT fmt);
233
234protected:
235
236 static int Thread(RTTHREAD hThread, void *pvUser);
237
238 int readDir(PSHCLTRANSFER pTransfer, const Utf8Str &strPath);
239
240 int copyToHGlobal(const void *pvData, size_t cbData, UINT fFlags, HGLOBAL *phGlobal);
241 int createFileGroupDescriptorFromTransfer(PSHCLTRANSFER pTransfer,
242 bool fUnicode, HGLOBAL *phGlobal);
243
244 bool lookupFormatEtc(LPFORMATETC pFormatEtc, ULONG *puIndex);
245 void registerFormat(LPFORMATETC pFormatEtc, CLIPFORMAT clipFormat, TYMED tyMed = TYMED_HGLOBAL,
246 LONG lindex = -1, DWORD dwAspect = DVASPECT_CONTENT, DVTARGETDEVICE *pTargetDevice = NULL);
247protected:
248
249 /**
250 * Structure for keeping a single file system object entry.
251 */
252 struct FSOBJENTRY
253 {
254 /** Relative path of the object. */
255 Utf8Str strPath;
256 /** Related (cached) object information. */
257 SHCLFSOBJINFO objInfo;
258 };
259
260 /** Vector containing file system objects with its (cached) objection information. */
261 typedef std::vector<FSOBJENTRY> FsObjEntryList;
262
263 /** The object's current status. */
264 Status m_enmStatus;
265 /** The object's current reference count. */
266 LONG m_lRefCount;
267 /** How many formats have been registered. */
268 ULONG m_cFormats;
269 LPFORMATETC m_pFormatEtc;
270 LPSTGMEDIUM m_pStgMedium;
271 /** Pointer to the associated transfer object being handled. */
272 PSHCLTRANSFER m_pTransfer;
273 /** Current stream object being used. */
274 IStream *m_pStream;
275 /** Current object index being handled by the data object.
276 * This is needed to create the next IStream object for e.g. the next upcoming file/dir/++ in the transfer. */
277 ULONG m_uObjIdx;
278 /** List of (cached) file system objects. */
279 FsObjEntryList m_lstEntries;
280 /** Whether the transfer thread is running. */
281 bool m_fRunning;
282 /** Event being triggered when reading the transfer list been completed. */
283 RTSEMEVENT m_EventListComplete;
284 /** Event being triggered when the transfer has been completed. */
285 RTSEMEVENT m_EventTransferComplete;
286 /** Registered format for CFSTR_FILEDESCRIPTORA. */
287 UINT m_cfFileDescriptorA;
288 /** Registered format for CFSTR_FILEDESCRIPTORW. */
289 UINT m_cfFileDescriptorW;
290 /** Registered format for CFSTR_FILECONTENTS. */
291 UINT m_cfFileContents;
292 /** Registered format for CFSTR_PERFORMEDDROPEFFECT. */
293 UINT m_cfPerformedDropEffect;
294};
295
296class SharedClipboardWinEnumFormatEtc : public IEnumFORMATETC
297{
298public:
299
300 SharedClipboardWinEnumFormatEtc(LPFORMATETC pFormatEtc, ULONG cFormats);
301 virtual ~SharedClipboardWinEnumFormatEtc(void);
302
303public: /* IUnknown methods. */
304
305 STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject);
306 STDMETHOD_(ULONG, AddRef)(void);
307 STDMETHOD_(ULONG, Release)(void);
308
309public: /* IEnumFORMATETC methods. */
310
311 STDMETHOD(Next)(ULONG cFormats, LPFORMATETC pFormatEtc, ULONG *pcFetched);
312 STDMETHOD(Skip)(ULONG cFormats);
313 STDMETHOD(Reset)(void);
314 STDMETHOD(Clone)(IEnumFORMATETC **ppEnumFormatEtc);
315
316public:
317
318 static void CopyFormat(LPFORMATETC pFormatDest, LPFORMATETC pFormatSource);
319 static HRESULT CreateEnumFormatEtc(UINT cFormats, LPFORMATETC pFormatEtc, IEnumFORMATETC **ppEnumFormatEtc);
320
321private:
322
323 LONG m_lRefCount;
324 ULONG m_nIndex;
325 ULONG m_nNumFormats;
326 LPFORMATETC m_pFormatEtc;
327};
328
329/**
330 * Own IStream implementation to implement file-based clipboard operations
331 * through HGCM. Needed on Windows hosts and guests.
332 */
333class SharedClipboardWinStreamImpl : public IStream
334{
335public:
336
337 SharedClipboardWinStreamImpl(SharedClipboardWinDataObject *pParent, PSHCLTRANSFER pTransfer,
338 const Utf8Str &strPath, PSHCLFSOBJINFO pObjInfo);
339 virtual ~SharedClipboardWinStreamImpl(void);
340
341public: /* IUnknown methods. */
342
343 STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject);
344 STDMETHOD_(ULONG, AddRef)(void);
345 STDMETHOD_(ULONG, Release)(void);
346
347public: /* IStream methods. */
348
349 STDMETHOD(Clone)(IStream** ppStream);
350 STDMETHOD(Commit)(DWORD dwFrags);
351 STDMETHOD(CopyTo)(IStream* pDestStream, ULARGE_INTEGER nBytesToCopy, ULARGE_INTEGER* nBytesRead, ULARGE_INTEGER* nBytesWritten);
352 STDMETHOD(LockRegion)(ULARGE_INTEGER nStart, ULARGE_INTEGER nBytes,DWORD dwFlags);
353 STDMETHOD(Read)(void* pvBuffer, ULONG nBytesToRead, ULONG* nBytesRead);
354 STDMETHOD(Revert)(void);
355 STDMETHOD(Seek)(LARGE_INTEGER nMove, DWORD dwOrigin, ULARGE_INTEGER* nNewPos);
356 STDMETHOD(SetSize)(ULARGE_INTEGER nNewSize);
357 STDMETHOD(Stat)(STATSTG* statstg, DWORD dwFlags);
358 STDMETHOD(UnlockRegion)(ULARGE_INTEGER nStart, ULARGE_INTEGER nBytes, DWORD dwFlags);
359 STDMETHOD(Write)(const void* pvBuffer, ULONG nBytesToRead, ULONG* nBytesRead);
360
361public: /* Own methods. */
362
363 static HRESULT Create(SharedClipboardWinDataObject *pParent, PSHCLTRANSFER pTransfer, const Utf8Str &strPath,
364 PSHCLFSOBJINFO pObjInfo, IStream **ppStream);
365private:
366
367 /** Pointer to the parent data object. */
368 SharedClipboardWinDataObject *m_pParent;
369 /** The stream object's current reference count. */
370 LONG m_lRefCount;
371 /** Pointer to the associated Shared Clipboard transfer. */
372 PSHCLTRANSFER m_pTransfer;
373 /** The object handle to use. */
374 SHCLOBJHANDLE m_hObj;
375 /** Object path. */
376 Utf8Str m_strPath;
377 /** (Cached) object information. */
378 SHCLFSOBJINFO m_objInfo;
379 /** Number of bytes already processed. */
380 uint64_t m_cbProcessed;
381 /** Whether this object already is in completed state or not. */
382 bool m_fIsComplete;
383};
384
385/**
386 * Class for Windows-specifics for maintaining a single Shared Clipboard transfer.
387 * Set as pvUser / cbUser in SHCLTRANSFERCTX.
388 */
389class SharedClipboardWinTransferCtx
390{
391public:
392 SharedClipboardWinTransferCtx()
393 : pDataObj(NULL) { }
394
395 virtual ~SharedClipboardWinTransferCtx()
396 {
397 if (pDataObj)
398 delete pDataObj;
399 }
400
401 /** Pointer to data object to use for this transfer.
402 * Can be NULL if not being used. */
403 SharedClipboardWinDataObject *pDataObj;
404};
405# endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
406#endif /* !VBOX_INCLUDED_GuestHost_SharedClipboard_win_h */
407
Note: See TracBrowser for help on using the repository browser.

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