VirtualBox

source: vbox/trunk/src/VBox/GuestHost/SharedClipboard/ClipboardStreamImpl-win.cpp@ 100386

Last change on this file since 100386 was 100204, checked in by vboxsync, 19 months ago

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.

bugref:9437

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.8 KB
Line 
1/* $Id: ClipboardStreamImpl-win.cpp 100204 2023-06-19 09:11:37Z vboxsync $ */
2/** @file
3 * ClipboardStreamImpl-win.cpp - Shared Clipboard IStream object implementation (guest and host side).
4 */
5
6/*
7 * Copyright (C) 2019-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#define LOG_GROUP LOG_GROUP_SHARED_CLIPBOARD
33#include <VBox/GuestHost/SharedClipboard-win.h>
34
35#include <iprt/asm.h>
36#include <iprt/ldr.h>
37#include <iprt/thread.h>
38
39#include <VBox/GuestHost/SharedClipboard.h>
40#include <VBox/GuestHost/SharedClipboard-win.h>
41
42#include <VBox/log.h>
43
44
45/*********************************************************************************************************************************
46* Structures and Typedefs *
47*********************************************************************************************************************************/
48
49
50
51/*********************************************************************************************************************************
52* Static variables *
53*********************************************************************************************************************************/
54
55
56
57SharedClipboardWinStreamImpl::SharedClipboardWinStreamImpl(SharedClipboardWinDataObject *pParent, PSHCLTRANSFER pTransfer,
58 const Utf8Str &strPath, PSHCLFSOBJINFO pObjInfo)
59 : m_pParent(pParent)
60 , m_lRefCount(1) /* Our IDataObjct *always* holds the last reference to this object; needed for the callbacks. */
61 , m_pTransfer(pTransfer)
62 , m_hObj(NIL_SHCLOBJHANDLE)
63 , m_strPath(strPath)
64 , m_objInfo(*pObjInfo)
65 , m_cbProcessed(0)
66 , m_fIsComplete(false)
67{
68 AssertPtr(m_pTransfer);
69
70 LogFunc(("m_strPath=%s\n", m_strPath.c_str()));
71}
72
73SharedClipboardWinStreamImpl::~SharedClipboardWinStreamImpl(void)
74{
75 LogFlowThisFuncEnter();
76}
77
78/*
79 * IUnknown methods.
80 */
81
82STDMETHODIMP SharedClipboardWinStreamImpl::QueryInterface(REFIID iid, void **ppvObject)
83{
84 AssertPtrReturn(ppvObject, E_INVALIDARG);
85
86 if (iid == IID_IUnknown)
87 {
88 LogFlowFunc(("IID_IUnknown\n"));
89 *ppvObject = (IUnknown *)(ISequentialStream *)this;
90 }
91 else if (iid == IID_ISequentialStream)
92 {
93 LogFlowFunc(("IID_ISequentialStream\n"));
94 *ppvObject = (ISequentialStream *)this;
95 }
96 else if (iid == IID_IStream)
97 {
98 LogFlowFunc(("IID_IStream\n"));
99 *ppvObject = (IStream *)this;
100 }
101 else
102 {
103 *ppvObject = NULL;
104 return E_NOINTERFACE;
105 }
106
107 AddRef();
108 return S_OK;
109}
110
111STDMETHODIMP_(ULONG) SharedClipboardWinStreamImpl::AddRef(void)
112{
113 LONG lCount = InterlockedIncrement(&m_lRefCount);
114 LogFlowFunc(("lCount=%RI32\n", lCount));
115 return lCount;
116}
117
118STDMETHODIMP_(ULONG) SharedClipboardWinStreamImpl::Release(void)
119{
120 LONG lCount = InterlockedDecrement(&m_lRefCount);
121 LogFlowFunc(("lCount=%RI32\n", m_lRefCount));
122 if (lCount == 0)
123 {
124 delete this;
125 return 0;
126 }
127
128 return lCount;
129}
130
131/*
132 * IStream methods.
133 */
134
135STDMETHODIMP SharedClipboardWinStreamImpl::Clone(IStream** ppStream)
136{
137 RT_NOREF(ppStream);
138
139 LogFlowFuncEnter();
140 return E_NOTIMPL;
141}
142
143STDMETHODIMP SharedClipboardWinStreamImpl::Commit(DWORD dwFrags)
144{
145 RT_NOREF(dwFrags);
146
147 LogFlowThisFuncEnter();
148 return E_NOTIMPL;
149}
150
151STDMETHODIMP SharedClipboardWinStreamImpl::CopyTo(IStream *pDestStream, ULARGE_INTEGER nBytesToCopy, ULARGE_INTEGER *nBytesRead,
152 ULARGE_INTEGER *nBytesWritten)
153{
154 RT_NOREF(pDestStream, nBytesToCopy, nBytesRead, nBytesWritten);
155
156 LogFlowThisFuncEnter();
157 return E_NOTIMPL;
158}
159
160STDMETHODIMP SharedClipboardWinStreamImpl::LockRegion(ULARGE_INTEGER nStart, ULARGE_INTEGER nBytes,DWORD dwFlags)
161{
162 RT_NOREF(nStart, nBytes, dwFlags);
163
164 LogFlowThisFuncEnter();
165 return STG_E_INVALIDFUNCTION;
166}
167
168/* Note: Windows seems to assume EOF if nBytesRead < nBytesToRead. */
169STDMETHODIMP SharedClipboardWinStreamImpl::Read(void *pvBuffer, ULONG nBytesToRead, ULONG *nBytesRead)
170{
171 LogFlowThisFunc(("Enter: m_cbProcessed=%RU64\n", m_cbProcessed));
172
173 /** @todo Is there any locking required so that parallel reads aren't possible? */
174
175 if (!pvBuffer)
176 return STG_E_INVALIDPOINTER;
177
178 if ( nBytesToRead == 0
179 || m_fIsComplete)
180 {
181 if (nBytesRead)
182 *nBytesRead = 0;
183 return S_OK;
184 }
185
186 int rc;
187
188 if ( m_hObj == NIL_SHCLOBJHANDLE
189 && m_pTransfer->ProviderIface.pfnObjOpen)
190 {
191 SHCLOBJOPENCREATEPARMS openParms;
192 rc = ShClTransferObjOpenParmsInit(&openParms);
193 if (RT_SUCCESS(rc))
194 {
195 openParms.fCreate = SHCL_OBJ_CF_ACCESS_READ
196 | SHCL_OBJ_CF_ACCESS_DENYWRITE;
197
198 rc = RTStrCopy(openParms.pszPath, openParms.cbPath, m_strPath.c_str());
199 if (RT_SUCCESS(rc))
200 {
201 rc = m_pTransfer->ProviderIface.pfnObjOpen(&m_pTransfer->ProviderCtx, &openParms, &m_hObj);
202 }
203
204 ShClTransferObjOpenParmsDestroy(&openParms);
205 }
206 }
207 else
208 rc = VINF_SUCCESS;
209
210 uint32_t cbRead = 0;
211
212 const uint64_t cbSize = (uint64_t)m_objInfo.cbObject;
213 const uint32_t cbToRead = RT_MIN(cbSize - m_cbProcessed, nBytesToRead);
214
215 if (RT_SUCCESS(rc))
216 {
217 if (cbToRead)
218 {
219 rc = m_pTransfer->ProviderIface.pfnObjRead(&m_pTransfer->ProviderCtx, m_hObj,
220 pvBuffer, cbToRead, 0 /* fFlags */, &cbRead);
221 if (RT_SUCCESS(rc))
222 {
223 m_cbProcessed += cbRead;
224 Assert(m_cbProcessed <= cbSize);
225 }
226 }
227
228 /* Transfer complete? Make sure to close the object again. */
229 m_fIsComplete = m_cbProcessed == cbSize;
230
231 if (m_fIsComplete)
232 {
233 if (m_pTransfer->ProviderIface.pfnObjClose)
234 {
235 int rc2 = m_pTransfer->ProviderIface.pfnObjClose(&m_pTransfer->ProviderCtx, m_hObj);
236 AssertRC(rc2);
237 }
238
239 if (m_pParent)
240 m_pParent->SetStatus(SharedClipboardWinDataObject::Completed);
241 }
242 }
243
244 LogFlowThisFunc(("Leave: rc=%Rrc, cbSize=%RU64, cbProcessed=%RU64 -> nBytesToRead=%RU32, cbToRead=%RU32, cbRead=%RU32\n",
245 rc, cbSize, m_cbProcessed, nBytesToRead, cbToRead, cbRead));
246
247 if (nBytesRead)
248 *nBytesRead = (ULONG)cbRead;
249
250 if (nBytesToRead != cbRead)
251 return S_FALSE;
252
253 return S_OK;
254}
255
256STDMETHODIMP SharedClipboardWinStreamImpl::Revert(void)
257{
258 LogFlowThisFuncEnter();
259 return E_NOTIMPL;
260}
261
262STDMETHODIMP SharedClipboardWinStreamImpl::Seek(LARGE_INTEGER nMove, DWORD dwOrigin, ULARGE_INTEGER* nNewPos)
263{
264 RT_NOREF(nMove, dwOrigin, nNewPos);
265
266 LogFlowThisFunc(("nMove=%RI64, dwOrigin=%RI32\n", nMove, dwOrigin));
267
268 return E_NOTIMPL;
269}
270
271STDMETHODIMP SharedClipboardWinStreamImpl::SetSize(ULARGE_INTEGER nNewSize)
272{
273 RT_NOREF(nNewSize);
274
275 LogFlowThisFuncEnter();
276 return E_NOTIMPL;
277}
278
279STDMETHODIMP SharedClipboardWinStreamImpl::Stat(STATSTG *pStatStg, DWORD dwFlags)
280{
281 HRESULT hr = S_OK;
282
283 if (pStatStg)
284 {
285 RT_ZERO(*pStatStg);
286
287 switch (dwFlags)
288 {
289 case STATFLAG_NONAME:
290 pStatStg->pwcsName = NULL;
291 break;
292
293 case STATFLAG_DEFAULT:
294 {
295 /** @todo r=bird: This is using the wrong allocator. According to MSDN the
296 * caller will pass this to CoTaskMemFree, so we should use CoTaskMemAlloc to
297 * allocate it. */
298 int rc2 = RTStrToUtf16(m_strPath.c_str(), &pStatStg->pwcsName);
299 if (RT_FAILURE(rc2))
300 hr = E_FAIL;
301 break;
302 }
303
304 default:
305 hr = STG_E_INVALIDFLAG;
306 break;
307 }
308
309 if (SUCCEEDED(hr))
310 {
311 pStatStg->type = STGTY_STREAM;
312 pStatStg->grfMode = STGM_READ;
313 pStatStg->grfLocksSupported = 0;
314 pStatStg->cbSize.QuadPart = (uint64_t)m_objInfo.cbObject;
315 }
316 }
317 else
318 hr = STG_E_INVALIDPOINTER;
319
320 LogFlowThisFunc(("hr=%Rhrc\n", hr));
321 return hr;
322}
323
324STDMETHODIMP SharedClipboardWinStreamImpl::UnlockRegion(ULARGE_INTEGER nStart, ULARGE_INTEGER nBytes, DWORD dwFlags)
325{
326 RT_NOREF(nStart, nBytes, dwFlags);
327
328 LogFlowThisFuncEnter();
329 return E_NOTIMPL;
330}
331
332STDMETHODIMP SharedClipboardWinStreamImpl::Write(const void *pvBuffer, ULONG nBytesToRead, ULONG *nBytesRead)
333{
334 RT_NOREF(pvBuffer, nBytesToRead, nBytesRead);
335
336 LogFlowThisFuncEnter();
337 return E_NOTIMPL;
338}
339
340/*
341 * Own stuff.
342 */
343
344/**
345 * Factory to create our own IStream implementation.
346 *
347 * @returns HRESULT
348 * @param pParent Pointer to the parent data object.
349 * @param pTransfer Pointer to Shared Clipboard transfer object to use.
350 * @param strPath Path of object to handle for the stream.
351 * @param pObjInfo Pointer to object information.
352 * @param ppStream Where to return the created stream object on success.
353 */
354/* static */
355HRESULT SharedClipboardWinStreamImpl::Create(SharedClipboardWinDataObject *pParent, PSHCLTRANSFER pTransfer,
356 const Utf8Str &strPath, PSHCLFSOBJINFO pObjInfo,
357 IStream **ppStream)
358{
359 AssertPtrReturn(pTransfer, E_POINTER);
360
361 SharedClipboardWinStreamImpl *pStream = new SharedClipboardWinStreamImpl(pParent, pTransfer, strPath, pObjInfo);
362 if (pStream)
363 {
364 pStream->AddRef();
365
366 *ppStream = pStream;
367 return S_OK;
368 }
369
370 return E_FAIL;
371}
372
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