VirtualBox

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

Last change on this file since 100509 was 100509, checked in by vboxsync, 18 months ago

Shared Clipboard: Resolved a @todo: Use CoTaskMemAlloc() in SharedClipboardWinStreamImpl::Stat(). bugref:9437

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.2 KB
Line 
1/* $Id: ClipboardStreamImpl-win.cpp 100509 2023-07-11 11:23:47Z 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 if (RT_FAILURE(rc))
237 {
238 if (m_pParent)
239 m_pParent->SetStatus(SharedClipboardWinDataObject::Error, rc /* Propagate rc */);
240 }
241
242 LogFlowThisFunc(("LEAVE: rc=%Rrc, cbSize=%RU64, cbProcessed=%RU64 -> nBytesToRead=%RU32, cbToRead=%RU32, cbRead=%RU32\n",
243 rc, cbSize, m_cbProcessed, nBytesToRead, cbToRead, cbRead));
244
245 if (nBytesRead)
246 *nBytesRead = (ULONG)cbRead;
247
248 if (nBytesToRead != cbRead)
249 return S_FALSE;
250
251 return S_OK;
252}
253
254STDMETHODIMP SharedClipboardWinStreamImpl::Revert(void)
255{
256 LogFlowThisFuncEnter();
257 return E_NOTIMPL;
258}
259
260STDMETHODIMP SharedClipboardWinStreamImpl::Seek(LARGE_INTEGER nMove, DWORD dwOrigin, ULARGE_INTEGER* nNewPos)
261{
262 RT_NOREF(nMove, dwOrigin, nNewPos);
263
264 LogFlowThisFunc(("nMove=%RI64, dwOrigin=%RI32\n", nMove, dwOrigin));
265
266 return E_NOTIMPL;
267}
268
269STDMETHODIMP SharedClipboardWinStreamImpl::SetSize(ULARGE_INTEGER nNewSize)
270{
271 RT_NOREF(nNewSize);
272
273 LogFlowThisFuncEnter();
274 return E_NOTIMPL;
275}
276
277STDMETHODIMP SharedClipboardWinStreamImpl::Stat(STATSTG *pStatStg, DWORD dwFlags)
278{
279 HRESULT hr = S_OK;
280
281 if (pStatStg)
282 {
283 RT_ZERO(*pStatStg);
284
285 switch (dwFlags)
286 {
287 case STATFLAG_NONAME:
288 pStatStg->pwcsName = NULL;
289 break;
290
291 case STATFLAG_DEFAULT:
292 {
293 size_t const cchLen = m_strPath.length() + 1 /* Include terminator */;
294 pStatStg->pwcsName = (LPOLESTR)CoTaskMemAlloc(cchLen * sizeof(RTUTF16));
295 if (pStatStg->pwcsName)
296 {
297 PRTUTF16 pwszStr;
298 int rc2 = RTStrToUtf16(m_strPath.c_str(), &pwszStr);
299 if (RT_SUCCESS(rc2))
300 {
301 memcpy(pStatStg->pwcsName, pwszStr, cchLen * sizeof(RTUTF16));
302 RTUtf16Free(pwszStr);
303 pwszStr = NULL;
304 }
305
306 if (RT_FAILURE(rc2))
307 {
308 CoTaskMemFree(pStatStg->pwcsName);
309 pStatStg->pwcsName = NULL;
310 hr = E_UNEXPECTED;
311 }
312 }
313 else
314 hr = E_OUTOFMEMORY;
315 break;
316 }
317
318 default:
319 hr = STG_E_INVALIDFLAG;
320 break;
321 }
322
323 if (SUCCEEDED(hr))
324 {
325 pStatStg->type = STGTY_STREAM;
326 pStatStg->grfMode = STGM_READ;
327 pStatStg->grfLocksSupported = 0;
328 pStatStg->cbSize.QuadPart = (uint64_t)m_objInfo.cbObject;
329 }
330 }
331 else
332 hr = STG_E_INVALIDPOINTER;
333
334 LogFlowThisFunc(("hr=%Rhrc\n", hr));
335 return hr;
336}
337
338STDMETHODIMP SharedClipboardWinStreamImpl::UnlockRegion(ULARGE_INTEGER nStart, ULARGE_INTEGER nBytes, DWORD dwFlags)
339{
340 RT_NOREF(nStart, nBytes, dwFlags);
341
342 LogFlowThisFuncEnter();
343 return E_NOTIMPL;
344}
345
346STDMETHODIMP SharedClipboardWinStreamImpl::Write(const void *pvBuffer, ULONG nBytesToRead, ULONG *nBytesRead)
347{
348 RT_NOREF(pvBuffer, nBytesToRead, nBytesRead);
349
350 LogFlowThisFuncEnter();
351 return E_NOTIMPL;
352}
353
354/*
355 * Own stuff.
356 */
357
358/**
359 * Factory to create our own IStream implementation.
360 *
361 * @returns HRESULT
362 * @param pParent Pointer to the parent data object.
363 * @param pTransfer Pointer to Shared Clipboard transfer object to use.
364 * @param strPath Path of object to handle for the stream.
365 * @param pObjInfo Pointer to object information.
366 * @param ppStream Where to return the created stream object on success.
367 */
368/* static */
369HRESULT SharedClipboardWinStreamImpl::Create(SharedClipboardWinDataObject *pParent, PSHCLTRANSFER pTransfer,
370 const Utf8Str &strPath, PSHCLFSOBJINFO pObjInfo,
371 IStream **ppStream)
372{
373 AssertPtrReturn(pTransfer, E_POINTER);
374
375 SharedClipboardWinStreamImpl *pStream = new SharedClipboardWinStreamImpl(pParent, pTransfer, strPath, pObjInfo);
376 if (pStream)
377 {
378 pStream->AddRef();
379
380 *ppStream = pStream;
381 return S_OK;
382 }
383
384 return E_FAIL;
385}
386
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