VirtualBox

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

Last change on this file since 98988 was 98103, checked in by vboxsync, 23 months ago

Copyright year updates by scm.

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