VirtualBox

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

Last change on this file since 80858 was 80858, checked in by vboxsync, 5 years ago

Shared Clipboard/URI: More renaming (URI -> transfer).

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