VirtualBox

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

最後變更 在這個檔案從100357是 100206,由 vboxsync 提交於 22 月 前

Shared Clipboard: Unified root list entry code to also use the generic list entry code, a lot of updates for the cross OS transfer handling code, more updates for HTTP server transfer handling. This also changed the handling of how that transfers are being initiated, as we needed to have this for X11: Before, transfers were initiated as soon as on side announced the URI list format -- now we postpone initiating the transfer until the receiving side requests the data as URI list [build fix]. ​​bugref:9437

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 17.6 KB
 
1/** @file
2 * Shared Clipboard - Common Guest and Host Code, for Windows OSes.
3 */
4
5/*
6 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
7 *
8 * This file is part of VirtualBox base platform packages, as
9 * available from https://www.alldomusa.eu.org.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation, in version 3 of the
14 * License.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, see <https://www.gnu.org/licenses>.
23 *
24 * The contents of this file may alternatively be used under the terms
25 * of the Common Development and Distribution License Version 1.0
26 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
27 * in the VirtualBox distribution, in which case the provisions of the
28 * CDDL are applicable instead of those of the GPL.
29 *
30 * You may elect to license modified versions of this file under the
31 * terms and conditions of either the GPL or the CDDL or both.
32 *
33 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
34 */
35
36#ifndef VBOX_INCLUDED_GuestHost_SharedClipboard_win_h
37#define VBOX_INCLUDED_GuestHost_SharedClipboard_win_h
38#ifndef RT_WITHOUT_PRAGMA_ONCE
39# pragma once
40#endif
41
42#include <iprt/critsect.h>
43#include <iprt/types.h>
44#include <iprt/req.h>
45#include <iprt/win/windows.h>
46
47#include <VBox/GuestHost/SharedClipboard.h>
48
49# ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
50# include <vector>
51
52# include <iprt/cpp/ministring.h> /* For RTCString. */
53# include <iprt/win/shlobj.h> /* For DROPFILES and friends. */
54# include <VBox/com/string.h> /* For Utf8Str. */
55# include <oleidl.h>
56
57# include <VBox/GuestHost/SharedClipboard-transfers.h>
58
59using namespace com;
60# endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
61
62#ifndef WM_CLIPBOARDUPDATE
63# define WM_CLIPBOARDUPDATE 0x031D
64#endif
65
66#define SHCL_WIN_WNDCLASS_NAME "VBoxSharedClipboardClass"
67
68/** See: https://docs.microsoft.com/en-us/windows/desktop/dataxchg/html-clipboard-format
69 * Do *not* change the name, as this will break compatbility with other (legacy) applications! */
70#define SHCL_WIN_REGFMT_HTML "HTML Format"
71
72/** Default timeout (in ms) for passing down messages down the clipboard chain. */
73#define SHCL_WIN_CBCHAIN_TIMEOUT_MS 5000
74
75/** Reports clipboard formats. */
76#define SHCL_WIN_WM_REPORT_FORMATS WM_USER
77/** Reads data from the clipboard and sends it to the destination. */
78#define SHCL_WIN_WM_READ_DATA WM_USER + 1
79#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
80/** Starts a transfer on the guest.
81 * This creates the necessary IDataObject in the matching window thread. */
82# define SHCL_WIN_WM_TRANSFER_START WM_USER + 2
83#endif
84
85/* Dynamically load clipboard functions from User32.dll. */
86typedef BOOL WINAPI FNADDCLIPBOARDFORMATLISTENER(HWND);
87typedef FNADDCLIPBOARDFORMATLISTENER *PFNADDCLIPBOARDFORMATLISTENER;
88
89typedef BOOL WINAPI FNREMOVECLIPBOARDFORMATLISTENER(HWND);
90typedef FNREMOVECLIPBOARDFORMATLISTENER *PFNREMOVECLIPBOARDFORMATLISTENER;
91
92/**
93 * Structure for keeping function pointers for the new clipboard API.
94 * If the new API is not available, those function pointer are NULL.
95 */
96typedef struct _SHCLWINAPINEW
97{
98 PFNADDCLIPBOARDFORMATLISTENER pfnAddClipboardFormatListener;
99 PFNREMOVECLIPBOARDFORMATLISTENER pfnRemoveClipboardFormatListener;
100} SHCLWINAPINEW, *PSHCLWINAPINEW;
101
102/**
103 * Structure for keeping variables which are needed to drive the old clipboard API.
104 */
105typedef struct _SHCLWINAPIOLD
106{
107 /** Timer ID for the refresh timer. */
108 UINT timerRefresh;
109 /** Whether "pinging" the clipboard chain currently is in progress or not. */
110 bool fCBChainPingInProcess;
111} SHCLWINAPIOLD, *PSHCLWINAPIOLD;
112
113#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
114/** Forward declaration for the Windows data object. */
115class SharedClipboardWinDataObject;
116#endif
117
118/**
119 * Structure for maintaining a Shared Clipboard context on Windows platforms.
120 */
121typedef struct _SHCLWINCTX
122{
123 /** Critical section to serialize access. */
124 RTCRITSECT CritSect;
125 /** Window handle of our (invisible) clipbaord window. */
126 HWND hWnd;
127 /** Window handle which is next to us in the clipboard chain. */
128 HWND hWndNextInChain;
129 /** Window handle of the clipboard owner *if* we are the owner.
130 * @todo r=bird: Ignore the misleading statement above. This is only set to
131 * NULL by the initialization code and then it's set to the clipboard owner
132 * after we announce data to the clipboard. So, essentially this will be our
133 * windows handle or NULL. End of story. */
134 HWND hWndClipboardOwnerUs;
135 /** Structure for maintaining the new clipboard API. */
136 SHCLWINAPINEW newAPI;
137 /** Structure for maintaining the old clipboard API. */
138 SHCLWINAPIOLD oldAPI;
139#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
140 /** The "in-flight" data object for file transfers.
141 * This is the current data object which has been created and sent to the Windows clipboard.
142 * That way Windows knows that a potential file transfer is available, but the actual transfer
143 * hasn't been started yet.
144 * Can be NULL if currently not being used / no current "in-flight" transfer present. */
145 SharedClipboardWinDataObject
146 *pDataObjInFlight;
147#endif
148 /** Request queue.
149 * Needed for processing HGCM requests within the HGCM (main) thread from the Windows event thread. */
150 RTREQQUEUE hReqQ;
151} SHCLWINCTX, *PSHCLWINCTX;
152
153int SharedClipboardWinOpen(HWND hWnd);
154int SharedClipboardWinClose(void);
155int SharedClipboardWinClear(void);
156
157int SharedClipboardWinCtxInit(PSHCLWINCTX pWinCtx);
158void SharedClipboardWinCtxDestroy(PSHCLWINCTX pWinCtx);
159
160int SharedClipboardWinCheckAndInitNewAPI(PSHCLWINAPINEW pAPI);
161bool SharedClipboardWinIsNewAPI(PSHCLWINAPINEW pAPI);
162
163int SharedClipboardWinDataWrite(UINT cfFormat, void *pvData, uint32_t cbData);
164
165int SharedClipboardWinChainAdd(PSHCLWINCTX pCtx);
166int SharedClipboardWinChainRemove(PSHCLWINCTX pCtx);
167VOID CALLBACK SharedClipboardWinChainPingProc(HWND hWnd, UINT uMsg, ULONG_PTR dwData, LRESULT lResult) RT_NOTHROW_DEF;
168LRESULT SharedClipboardWinChainPassToNext(PSHCLWINCTX pWinCtx, UINT msg, WPARAM wParam, LPARAM lParam);
169
170SHCLFORMAT SharedClipboardWinClipboardFormatToVBox(UINT uFormat);
171int SharedClipboardWinGetFormats(PSHCLWINCTX pCtx, PSHCLFORMATS pfFormats);
172
173#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
174int SharedClipboardWinTransferGetRoots(PSHCLWINCTX pWinCtx, PSHCLTRANSFER pTransfer);
175int SharedClipboardWinTransferDropFilesToStringList(DROPFILES *pDropFiles, char **papszList, uint32_t *pcbList);
176int SharedClipboardWinTransferGetRootsFromClipboard(PSHCLWINCTX pWinCtx, PSHCLTRANSFER pTransfer);
177int SharedClipboardWinTransferCreateAndSetDataObject(PSHCLWINCTX pWinCtx, PSHCLCONTEXT pCtx, PSHCLCALLBACKS pCallbacks);
178#endif
179
180int SharedClipboardWinGetCFHTMLHeaderValue(const char *pszSrc, const char *pszOption, uint32_t *puValue);
181bool SharedClipboardWinIsCFHTML(const char *pszSource);
182int SharedClipboardWinConvertCFHTMLToMIME(const char *pszSource, const uint32_t cch, char **ppszOutput, uint32_t *pcbOutput);
183int SharedClipboardWinConvertMIMEToCFHTML(const char *pszSource, size_t cb, char **ppszOutput, uint32_t *pcbOutput);
184
185LRESULT SharedClipboardWinHandleWMChangeCBChain(PSHCLWINCTX pWinCtx, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
186int SharedClipboardWinHandleWMDestroy(PSHCLWINCTX pWinCtx);
187int SharedClipboardWinHandleWMRenderAllFormats(PSHCLWINCTX pWinCtx, HWND hWnd);
188int SharedClipboardWinHandleWMTimer(PSHCLWINCTX pWinCtx);
189
190int SharedClipboardWinClearAndAnnounceFormats(PSHCLWINCTX pWinCtx, SHCLFORMATS fFormats, HWND hWnd);
191#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
192int SharedClipboardWinTransferCreate(PSHCLWINCTX pWinCtx, PSHCLTRANSFER pTransfer);
193void SharedClipboardWinTransferDestroy(PSHCLWINCTX pWinCtx, PSHCLTRANSFER pTransfer);
194#endif
195
196# ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
197class SharedClipboardTransferList;
198# ifndef FILEGROUPDESCRIPTOR
199class FILEGROUPDESCRIPTOR;
200# endif
201
202class SharedClipboardWinDataObject : public IDataObject //, public IDataObjectAsyncCapability
203{
204public:
205
206 enum Status
207 {
208 /** The object is uninitialized (not ready). */
209 Uninitialized = 0,
210 /** The object is initialized and ready to use.
211 * A transfer is *not* running yet! */
212 Initialized,
213 /** Transfer is running. */
214 Running,
215 /** The operation has been successfully completed. */
216 Completed,
217 /** The operation has been canceled. */
218 Canceled,
219 /** An (unrecoverable) error occurred. */
220 Error
221 };
222
223public:
224
225 SharedClipboardWinDataObject(void);
226 virtual ~SharedClipboardWinDataObject(void);
227
228public:
229
230 int Init(PSHCLCONTEXT pCtx, LPFORMATETC pFormatEtc = NULL, LPSTGMEDIUM pStgMed = NULL, ULONG cFormats = 0);
231 void Destroy(void);
232
233 void SetCallbacks(PSHCLCALLBACKS pCallbacks);
234
235public: /* IUnknown methods. */
236
237 STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject);
238 STDMETHOD_(ULONG, AddRef)(void);
239 STDMETHOD_(ULONG, Release)(void);
240
241public: /* IDataObject methods. */
242
243 STDMETHOD(GetData)(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium);
244 STDMETHOD(GetDataHere)(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium);
245 STDMETHOD(QueryGetData)(LPFORMATETC pFormatEtc);
246 STDMETHOD(GetCanonicalFormatEtc)(LPFORMATETC pFormatEct, LPFORMATETC pFormatEtcOut);
247 STDMETHOD(SetData)(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium, BOOL fRelease);
248 STDMETHOD(EnumFormatEtc)(DWORD dwDirection, IEnumFORMATETC **ppEnumFormatEtc);
249 STDMETHOD(DAdvise)(LPFORMATETC pFormatEtc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection);
250 STDMETHOD(DUnadvise)(DWORD dwConnection);
251 STDMETHOD(EnumDAdvise)(IEnumSTATDATA **ppEnumAdvise);
252
253#ifdef VBOX_WITH_SHARED_CLIPBOARD_WIN_ASYNC
254public: /* IDataObjectAsyncCapability methods. */
255
256 STDMETHOD(EndOperation)(HRESULT hResult, IBindCtx* pbcReserved, DWORD dwEffects);
257 STDMETHOD(GetAsyncMode)(BOOL* pfIsOpAsync);
258 STDMETHOD(InOperation)(BOOL* pfInAsyncOp);
259 STDMETHOD(SetAsyncMode)(BOOL fDoOpAsync);
260 STDMETHOD(StartOperation)(IBindCtx* pbcReserved);
261#endif /* VBOX_WITH_SHARED_CLIPBOARD_WIN_ASYNC */
262
263public:
264
265 int SetAndStartTransfer(PSHCLTRANSFER pTransfer);
266 int SetStatus(Status enmStatus, int rc = VINF_SUCCESS);
267
268public:
269
270 static DECLCALLBACK(int) readThread(RTTHREAD ThreadSelf, void *pvUser);
271
272 static void logFormat(CLIPFORMAT fmt);
273
274protected:
275
276 static int Thread(RTTHREAD hThread, void *pvUser);
277
278 int readDir(PSHCLTRANSFER pTransfer, const Utf8Str &strPath);
279
280 int copyToHGlobal(const void *pvData, size_t cbData, UINT fFlags, HGLOBAL *phGlobal);
281 int createFileGroupDescriptorFromTransfer(PSHCLTRANSFER pTransfer,
282 bool fUnicode, HGLOBAL *phGlobal);
283
284 bool lookupFormatEtc(LPFORMATETC pFormatEtc, ULONG *puIndex);
285 void registerFormat(LPFORMATETC pFormatEtc, CLIPFORMAT clipFormat, TYMED tyMed = TYMED_HGLOBAL,
286 LONG lindex = -1, DWORD dwAspect = DVASPECT_CONTENT, DVTARGETDEVICE *pTargetDevice = NULL);
287 int setStatusLocked(Status enmStatus, int rc = VINF_SUCCESS);
288
289protected:
290
291 /**
292 * Structure for keeping a single file system object entry.
293 */
294 struct FSOBJENTRY
295 {
296 /** Relative path of the object. */
297 char *pszPath;
298 /** Related (cached) object information. */
299 SHCLFSOBJINFO objInfo;
300 };
301
302 /** Vector containing file system objects with its (cached) objection information. */
303 typedef std::vector<FSOBJENTRY> FsObjEntryList;
304
305 /** Shared Clipboard context to use. */
306 PSHCLCONTEXT m_pCtx;
307 /** Callbacks table to use. */
308 SHCLCALLBACKS m_Callbacks;
309 /** The object's current status. */
310 Status m_enmStatus;
311 /** The object's current reference count. */
312 LONG m_lRefCount;
313 /** How many formats have been registered. */
314 ULONG m_cFormats;
315 LPFORMATETC m_pFormatEtc;
316 LPSTGMEDIUM m_pStgMedium;
317 /** Pointer to the associated transfer object being handled. */
318 PSHCLTRANSFER m_pTransfer;
319 /** Current stream object being used. */
320 IStream *m_pStream;
321 /** Current object index being handled by the data object.
322 * This is needed to create the next IStream object for e.g. the next upcoming file/dir/++ in the transfer. */
323 ULONG m_uObjIdx;
324 /** List of (cached) file system objects. */
325 FsObjEntryList m_lstEntries;
326 /** Critical section to serialize access. */
327 RTCRITSECT m_CritSect;
328 /** Whether the transfer thread is running. */
329 bool m_fThreadRunning;
330 /** Event being triggered when reading the transfer list been completed. */
331 RTSEMEVENT m_EventListComplete;
332 /** Event being triggered when the transfer status has been changed. */
333 RTSEMEVENT m_EventStatusChanged;
334 /** Registered format for CFSTR_FILEDESCRIPTORA. */
335 UINT m_cfFileDescriptorA;
336 /** Registered format for CFSTR_FILEDESCRIPTORW. */
337 UINT m_cfFileDescriptorW;
338 /** Registered format for CFSTR_FILECONTENTS. */
339 UINT m_cfFileContents;
340 /** Registered format for CFSTR_PERFORMEDDROPEFFECT. */
341 UINT m_cfPerformedDropEffect;
342};
343
344class SharedClipboardWinEnumFormatEtc : public IEnumFORMATETC
345{
346public:
347
348 SharedClipboardWinEnumFormatEtc(void);
349 virtual ~SharedClipboardWinEnumFormatEtc(void);
350
351public:
352
353 int Init(LPFORMATETC pFormatEtc, ULONG cFormats);
354 void Destroy(void);
355
356public: /* IUnknown methods. */
357
358 STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject);
359 STDMETHOD_(ULONG, AddRef)(void);
360 STDMETHOD_(ULONG, Release)(void);
361
362public: /* IEnumFORMATETC methods. */
363
364 STDMETHOD(Next)(ULONG cFormats, LPFORMATETC pFormatEtc, ULONG *pcFetched);
365 STDMETHOD(Skip)(ULONG cFormats);
366 STDMETHOD(Reset)(void);
367 STDMETHOD(Clone)(IEnumFORMATETC **ppEnumFormatEtc);
368
369public:
370
371 static void CopyFormat(LPFORMATETC pFormatDest, LPFORMATETC pFormatSource);
372 static HRESULT CreateEnumFormatEtc(UINT cFormats, LPFORMATETC pFormatEtc, IEnumFORMATETC **ppEnumFormatEtc);
373
374private:
375
376 LONG m_lRefCount;
377 ULONG m_nIndex;
378 ULONG m_nNumFormats;
379 LPFORMATETC m_pFormatEtc;
380};
381
382/**
383 * Own IStream implementation to implement file-based clipboard operations
384 * through HGCM. Needed on Windows hosts and guests.
385 */
386class SharedClipboardWinStreamImpl : public IStream
387{
388public:
389
390 SharedClipboardWinStreamImpl(SharedClipboardWinDataObject *pParent, PSHCLTRANSFER pTransfer,
391 const Utf8Str &strPath, PSHCLFSOBJINFO pObjInfo);
392 virtual ~SharedClipboardWinStreamImpl(void);
393
394public: /* IUnknown methods. */
395
396 STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject);
397 STDMETHOD_(ULONG, AddRef)(void);
398 STDMETHOD_(ULONG, Release)(void);
399
400public: /* IStream methods. */
401
402 STDMETHOD(Clone)(IStream** ppStream);
403 STDMETHOD(Commit)(DWORD dwFrags);
404 STDMETHOD(CopyTo)(IStream* pDestStream, ULARGE_INTEGER nBytesToCopy, ULARGE_INTEGER* nBytesRead, ULARGE_INTEGER* nBytesWritten);
405 STDMETHOD(LockRegion)(ULARGE_INTEGER nStart, ULARGE_INTEGER nBytes,DWORD dwFlags);
406 STDMETHOD(Read)(void* pvBuffer, ULONG nBytesToRead, ULONG* nBytesRead);
407 STDMETHOD(Revert)(void);
408 STDMETHOD(Seek)(LARGE_INTEGER nMove, DWORD dwOrigin, ULARGE_INTEGER* nNewPos);
409 STDMETHOD(SetSize)(ULARGE_INTEGER nNewSize);
410 STDMETHOD(Stat)(STATSTG* statstg, DWORD dwFlags);
411 STDMETHOD(UnlockRegion)(ULARGE_INTEGER nStart, ULARGE_INTEGER nBytes, DWORD dwFlags);
412 STDMETHOD(Write)(const void* pvBuffer, ULONG nBytesToRead, ULONG* nBytesRead);
413
414public: /* Own methods. */
415
416 static HRESULT Create(SharedClipboardWinDataObject *pParent, PSHCLTRANSFER pTransfer, const Utf8Str &strPath,
417 PSHCLFSOBJINFO pObjInfo, IStream **ppStream);
418private:
419
420 /** Pointer to the parent data object. */
421 SharedClipboardWinDataObject *m_pParent;
422 /** The stream object's current reference count. */
423 LONG m_lRefCount;
424 /** Pointer to the associated Shared Clipboard transfer. */
425 PSHCLTRANSFER m_pTransfer;
426 /** The object handle to use. */
427 SHCLOBJHANDLE m_hObj;
428 /** Object path. */
429 Utf8Str m_strPath;
430 /** (Cached) object information. */
431 SHCLFSOBJINFO m_objInfo;
432 /** Number of bytes already processed. */
433 uint64_t m_cbProcessed;
434 /** Whether this object already is in completed state or not. */
435 bool m_fIsComplete;
436};
437
438/**
439 * Class for Windows-specifics for maintaining a single Shared Clipboard transfer.
440 * Set as pvUser / cbUser in SHCLTRANSFERCTX.
441 */
442class SharedClipboardWinTransferCtx
443{
444public:
445 SharedClipboardWinTransferCtx()
446 : pDataObj(NULL) { }
447
448 virtual ~SharedClipboardWinTransferCtx()
449 {
450 if (pDataObj)
451 delete pDataObj;
452 }
453
454 /** Pointer to data object to use for this transfer.
455 * Can be NULL if not being used. */
456 SharedClipboardWinDataObject *pDataObj;
457};
458# endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
459#endif /* !VBOX_INCLUDED_GuestHost_SharedClipboard_win_h */
460
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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