VirtualBox

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

Last change on this file since 100434 was 100434, checked in by vboxsync, 17 months ago

Shared Clipboard: Use ShClTransfer methods instead of calling the provider interface directly. ​​bugref:9437

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.5 KB
Line 
1/* $Id: ClipboardStreamImpl-win.cpp 100434 2023-07-07 11:55:21Z 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 {
190 SHCLOBJOPENCREATEPARMS openParms;
191 rc = ShClTransferObjOpenParmsInit(&openParms);
192 if (RT_SUCCESS(rc))
193 {
194 openParms.fCreate = SHCL_OBJ_CF_ACCESS_READ
195 | SHCL_OBJ_CF_ACCESS_DENYWRITE;
196
197 rc = RTStrCopy(openParms.pszPath, openParms.cbPath, m_strPath.c_str());
198 if (RT_SUCCESS(rc))
199 rc = ShClTransferObjOpen(m_pTransfer, &openParms, &m_hObj);
200
201 ShClTransferObjOpenParmsDestroy(&openParms);
202 }
203 }
204 else
205 rc = VINF_SUCCESS;
206
207 uint32_t cbRead = 0;
208
209 const uint64_t cbSize = (uint64_t)m_objInfo.cbObject;
210 const uint32_t cbToRead = RT_MIN(cbSize - m_cbProcessed, nBytesToRead);
211
212 if (RT_SUCCESS(rc))
213 {
214 if (cbToRead)
215 {
216 rc = ShClTransferObjRead(m_pTransfer, m_hObj, pvBuffer, cbToRead, 0 /* fFlags */, &cbRead);
217 if (RT_SUCCESS(rc))
218 {
219 m_cbProcessed += cbRead;
220 Assert(m_cbProcessed <= cbSize);
221 }
222 }
223
224 /* Transfer complete? Make sure to close the object again. */
225 m_fIsComplete = m_cbProcessed == cbSize;
226
227 if (m_fIsComplete)
228 {
229 rc = ShClTransferObjClose(m_pTransfer, m_hObj);
230
231 if (m_pParent)
232 m_pParent->SetStatus(SharedClipboardWinDataObject::Completed);
233 }
234 }
235
236 LogFlowThisFunc(("Leave: rc=%Rrc, cbSize=%RU64, cbProcessed=%RU64 -> nBytesToRead=%RU32, cbToRead=%RU32, cbRead=%RU32\n",
237 rc, cbSize, m_cbProcessed, nBytesToRead, cbToRead, cbRead));
238
239 if (nBytesRead)
240 *nBytesRead = (ULONG)cbRead;
241
242 if (nBytesToRead != cbRead)
243 return S_FALSE;
244
245 return S_OK;
246}
247
248STDMETHODIMP SharedClipboardWinStreamImpl::Revert(void)
249{
250 LogFlowThisFuncEnter();
251 return E_NOTIMPL;
252}
253
254STDMETHODIMP SharedClipboardWinStreamImpl::Seek(LARGE_INTEGER nMove, DWORD dwOrigin, ULARGE_INTEGER* nNewPos)
255{
256 RT_NOREF(nMove, dwOrigin, nNewPos);
257
258 LogFlowThisFunc(("nMove=%RI64, dwOrigin=%RI32\n", nMove, dwOrigin));
259
260 return E_NOTIMPL;
261}
262
263STDMETHODIMP SharedClipboardWinStreamImpl::SetSize(ULARGE_INTEGER nNewSize)
264{
265 RT_NOREF(nNewSize);
266
267 LogFlowThisFuncEnter();
268 return E_NOTIMPL;
269}
270
271STDMETHODIMP SharedClipboardWinStreamImpl::Stat(STATSTG *pStatStg, DWORD dwFlags)
272{
273 HRESULT hr = S_OK;
274
275 if (pStatStg)
276 {
277 RT_ZERO(*pStatStg);
278
279 switch (dwFlags)
280 {
281 case STATFLAG_NONAME:
282 pStatStg->pwcsName = NULL;
283 break;
284
285 case STATFLAG_DEFAULT:
286 {
287 /** @todo r=bird: This is using the wrong allocator. According to MSDN the
288 * caller will pass this to CoTaskMemFree, so we should use CoTaskMemAlloc to
289 * allocate it. */
290 int rc2 = RTStrToUtf16(m_strPath.c_str(), &pStatStg->pwcsName);
291 if (RT_FAILURE(rc2))
292 hr = E_FAIL;
293 break;
294 }
295
296 default:
297 hr = STG_E_INVALIDFLAG;
298 break;
299 }
300
301 if (SUCCEEDED(hr))
302 {
303 pStatStg->type = STGTY_STREAM;
304 pStatStg->grfMode = STGM_READ;
305 pStatStg->grfLocksSupported = 0;
306 pStatStg->cbSize.QuadPart = (uint64_t)m_objInfo.cbObject;
307 }
308 }
309 else
310 hr = STG_E_INVALIDPOINTER;
311
312 LogFlowThisFunc(("hr=%Rhrc\n", hr));
313 return hr;
314}
315
316STDMETHODIMP SharedClipboardWinStreamImpl::UnlockRegion(ULARGE_INTEGER nStart, ULARGE_INTEGER nBytes, DWORD dwFlags)
317{
318 RT_NOREF(nStart, nBytes, dwFlags);
319
320 LogFlowThisFuncEnter();
321 return E_NOTIMPL;
322}
323
324STDMETHODIMP SharedClipboardWinStreamImpl::Write(const void *pvBuffer, ULONG nBytesToRead, ULONG *nBytesRead)
325{
326 RT_NOREF(pvBuffer, nBytesToRead, nBytesRead);
327
328 LogFlowThisFuncEnter();
329 return E_NOTIMPL;
330}
331
332/*
333 * Own stuff.
334 */
335
336/**
337 * Factory to create our own IStream implementation.
338 *
339 * @returns HRESULT
340 * @param pParent Pointer to the parent data object.
341 * @param pTransfer Pointer to Shared Clipboard transfer object to use.
342 * @param strPath Path of object to handle for the stream.
343 * @param pObjInfo Pointer to object information.
344 * @param ppStream Where to return the created stream object on success.
345 */
346/* static */
347HRESULT SharedClipboardWinStreamImpl::Create(SharedClipboardWinDataObject *pParent, PSHCLTRANSFER pTransfer,
348 const Utf8Str &strPath, PSHCLFSOBJINFO pObjInfo,
349 IStream **ppStream)
350{
351 AssertPtrReturn(pTransfer, E_POINTER);
352
353 SharedClipboardWinStreamImpl *pStream = new SharedClipboardWinStreamImpl(pParent, pTransfer, strPath, pObjInfo);
354 if (pStream)
355 {
356 pStream->AddRef();
357
358 *ppStream = pStream;
359 return S_OK;
360 }
361
362 return E_FAIL;
363}
364
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