VirtualBox

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

Last change on this file since 91933 was 86948, checked in by vboxsync, 4 years ago

Shared Clipboard/Transfers: Resurrected Windows code. bugref:9437

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.9 KB
RevLine 
[78440]1/* $Id: ClipboardStreamImpl-win.cpp 86948 2020-11-20 18:35:24Z vboxsync $ */
2/** @file
[79027]3 * ClipboardStreamImpl-win.cpp - Shared Clipboard IStream object implementation (guest and host side).
[78440]4 */
5
6/*
[82968]7 * Copyright (C) 2019-2020 Oracle Corporation
[78440]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>
[78474]27#include <iprt/thread.h>
[78440]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
[78474]46
47
[80858]48SharedClipboardWinStreamImpl::SharedClipboardWinStreamImpl(SharedClipboardWinDataObject *pParent, PSHCLTRANSFER pTransfer,
[80664]49 const Utf8Str &strPath, PSHCLFSOBJINFO pObjInfo)
[78974]50 : m_pParent(pParent)
[79702]51 , m_lRefCount(1) /* Our IDataObjct *always* holds the last reference to this object; needed for the callbacks. */
[80858]52 , m_pTransfer(pTransfer)
[86948]53 , m_hObj(SHCLOBJHANDLE_INVALID)
[79702]54 , m_strPath(strPath)
55 , m_objInfo(*pObjInfo)
56 , m_cbProcessed(0)
[81259]57 , m_fIsComplete(false)
[78474]58{
[80858]59 AssertPtr(m_pTransfer);
[78809]60
[79702]61 LogFunc(("m_strPath=%s\n", m_strPath.c_str()));
[78474]62}
63
[80664]64SharedClipboardWinStreamImpl::~SharedClipboardWinStreamImpl(void)
[78474]65{
[78809]66 LogFlowThisFuncEnter();
[78474]67}
68
69/*
70 * IUnknown methods.
71 */
72
[80664]73STDMETHODIMP SharedClipboardWinStreamImpl::QueryInterface(REFIID iid, void **ppvObject)
[78474]74{
75 AssertPtrReturn(ppvObject, E_INVALIDARG);
76
[79027]77 if (iid == IID_IUnknown)
[78474]78 {
[79027]79 LogFlowFunc(("IID_IUnknown\n"));
80 *ppvObject = (IUnknown *)(ISequentialStream *)this;
[78474]81 }
[79027]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 }
[78474]97
[79027]98 AddRef();
99 return S_OK;
[78474]100}
101
[80664]102STDMETHODIMP_(ULONG) SharedClipboardWinStreamImpl::AddRef(void)
[78474]103{
104 LONG lCount = InterlockedIncrement(&m_lRefCount);
105 LogFlowFunc(("lCount=%RI32\n", lCount));
106 return lCount;
107}
108
[80664]109STDMETHODIMP_(ULONG) SharedClipboardWinStreamImpl::Release(void)
[78474]110{
111 LONG lCount = InterlockedDecrement(&m_lRefCount);
112 LogFlowFunc(("lCount=%RI32\n", m_lRefCount));
113 if (lCount == 0)
114 {
115 delete this;
116 return 0;
117 }
118
119 return lCount;
120}
121
122/*
123 * IStream methods.
124 */
125
[80664]126STDMETHODIMP SharedClipboardWinStreamImpl::Clone(IStream** ppStream)
[78474]127{
128 RT_NOREF(ppStream);
129
130 LogFlowFuncEnter();
131 return E_NOTIMPL;
132}
133
[80664]134STDMETHODIMP SharedClipboardWinStreamImpl::Commit(DWORD dwFrags)
[78474]135{
136 RT_NOREF(dwFrags);
137
[78809]138 LogFlowThisFuncEnter();
[78474]139 return E_NOTIMPL;
140}
141
[80664]142STDMETHODIMP SharedClipboardWinStreamImpl::CopyTo(IStream *pDestStream, ULARGE_INTEGER nBytesToCopy, ULARGE_INTEGER *nBytesRead,
143 ULARGE_INTEGER *nBytesWritten)
[78474]144{
145 RT_NOREF(pDestStream, nBytesToCopy, nBytesRead, nBytesWritten);
146
[78809]147 LogFlowThisFuncEnter();
[78474]148 return E_NOTIMPL;
149}
150
[80664]151STDMETHODIMP SharedClipboardWinStreamImpl::LockRegion(ULARGE_INTEGER nStart, ULARGE_INTEGER nBytes,DWORD dwFlags)
[78474]152{
153 RT_NOREF(nStart, nBytes, dwFlags);
154
[78809]155 LogFlowThisFuncEnter();
[79027]156 return STG_E_INVALIDFUNCTION;
[78474]157}
158
[79702]159/* Note: Windows seems to assume EOF if nBytesRead < nBytesToRead. */
[80664]160STDMETHODIMP SharedClipboardWinStreamImpl::Read(void *pvBuffer, ULONG nBytesToRead, ULONG *nBytesRead)
[78474]161{
[79702]162 LogFlowThisFunc(("Enter: m_cbProcessed=%RU64\n", m_cbProcessed));
[78474]163
[79702]164 /** @todo Is there any locking required so that parallel reads aren't possible? */
[79027]165
[79702]166 if (!pvBuffer)
167 return STG_E_INVALIDPOINTER;
168
[81259]169 if ( nBytesToRead == 0
170 || m_fIsComplete)
[78474]171 {
[78897]172 if (nBytesRead)
[79702]173 *nBytesRead = 0;
174 return S_OK;
[78474]175 }
176
[79702]177 int rc;
[78897]178
[79702]179 try
180 {
[80662]181 if ( m_hObj == SHCLOBJHANDLE_INVALID
[80858]182 && m_pTransfer->ProviderIface.pfnObjOpen)
[79702]183 {
[80662]184 SHCLOBJOPENCREATEPARMS openParms;
[81223]185 rc = ShClTransferObjOpenParmsInit(&openParms);
[80359]186 if (RT_SUCCESS(rc))
[80283]187 {
[82466]188 openParms.fCreate = SHCL_OBJ_CF_ACCESS_READ
[80662]189 | SHCL_OBJ_CF_ACCESS_DENYWRITE;
[80283]190
[80359]191 rc = RTStrCopy(openParms.pszPath, openParms.cbPath, m_strPath.c_str());
192 if (RT_SUCCESS(rc))
193 {
[80858]194 rc = m_pTransfer->ProviderIface.pfnObjOpen(&m_pTransfer->ProviderCtx, &openParms, &m_hObj);
[80359]195 }
196
[81223]197 ShClTransferObjOpenParmsDestroy(&openParms);
[80283]198 }
[79702]199 }
200 else
201 rc = VINF_SUCCESS;
202
203 uint32_t cbRead = 0;
204
205 const uint64_t cbSize = (uint64_t)m_objInfo.cbObject;
206 const uint32_t cbToRead = RT_MIN(cbSize - m_cbProcessed, nBytesToRead);
207
[78974]208 if (RT_SUCCESS(rc))
209 {
[79702]210 if (cbToRead)
211 {
[80858]212 rc = m_pTransfer->ProviderIface.pfnObjRead(&m_pTransfer->ProviderCtx, m_hObj,
213 pvBuffer, cbToRead, 0 /* fFlags */, &cbRead);
[79702]214 if (RT_SUCCESS(rc))
215 {
216 m_cbProcessed += cbRead;
217 Assert(m_cbProcessed <= cbSize);
218 }
219 }
[79120]220
[79702]221 /* Transfer complete? Make sure to close the object again. */
[81259]222 m_fIsComplete = m_cbProcessed == cbSize;
[79497]223
[81259]224 if (m_fIsComplete)
[79702]225 {
[80858]226 if (m_pTransfer->ProviderIface.pfnObjClose)
[79702]227 {
[80858]228 int rc2 = m_pTransfer->ProviderIface.pfnObjClose(&m_pTransfer->ProviderCtx, m_hObj);
[79702]229 AssertRC(rc2);
230 }
231
232 if (m_pParent)
233 m_pParent->OnTransferComplete();
234 }
[78974]235 }
[79702]236
237 LogFlowThisFunc(("Leave: rc=%Rrc, cbSize=%RU64, cbProcessed=%RU64 -> nBytesToRead=%RU32, cbToRead=%RU32, cbRead=%RU32\n",
238 rc, cbSize, m_cbProcessed, nBytesToRead, cbToRead, cbRead));
239
240 if (nBytesRead)
241 *nBytesRead = (ULONG)cbRead;
242
243 if (nBytesToRead != cbRead)
244 return S_FALSE;
245
246 return S_OK;
[78974]247 }
[79702]248 catch (...)
249 {
250 LogFunc(("Caught exception\n"));
251 }
[78974]252
[79702]253 return E_FAIL;
[78474]254}
255
[80664]256STDMETHODIMP SharedClipboardWinStreamImpl::Revert(void)
[78474]257{
[78809]258 LogFlowThisFuncEnter();
[79702]259 return E_NOTIMPL;
[78474]260}
261
[80664]262STDMETHODIMP SharedClipboardWinStreamImpl::Seek(LARGE_INTEGER nMove, DWORD dwOrigin, ULARGE_INTEGER* nNewPos)
[78474]263{
264 RT_NOREF(nMove, dwOrigin, nNewPos);
265
[79702]266 LogFlowThisFunc(("nMove=%RI64, dwOrigin=%RI32\n", nMove, dwOrigin));
267
268 return E_NOTIMPL;
[78474]269}
270
[80664]271STDMETHODIMP SharedClipboardWinStreamImpl::SetSize(ULARGE_INTEGER nNewSize)
[78474]272{
273 RT_NOREF(nNewSize);
274
[78809]275 LogFlowThisFuncEnter();
[79702]276 return E_NOTIMPL;
[78474]277}
278
[80664]279STDMETHODIMP SharedClipboardWinStreamImpl::Stat(STATSTG *pStatStg, DWORD dwFlags)
[78474]280{
[79027]281 HRESULT hr = S_OK;
[78474]282
[79027]283 if (pStatStg)
284 {
[82495]285 RT_ZERO(*pStatStg);
[79027]286
287 switch (dwFlags)
288 {
289 case STATFLAG_NONAME:
290 pStatStg->pwcsName = NULL;
291 break;
292
293 case STATFLAG_DEFAULT:
294 {
[82495]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. */
[79702]298 int rc2 = RTStrToUtf16(m_strPath.c_str(), &pStatStg->pwcsName);
[79027]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;
[79702]314 pStatStg->cbSize.QuadPart = (uint64_t)m_objInfo.cbObject;
[79027]315 }
316 }
317 else
318 hr = STG_E_INVALIDPOINTER;
319
320 LogFlowThisFunc(("hr=%Rhrc\n", hr));
321 return hr;
[78474]322}
323
[80664]324STDMETHODIMP SharedClipboardWinStreamImpl::UnlockRegion(ULARGE_INTEGER nStart, ULARGE_INTEGER nBytes, DWORD dwFlags)
[78474]325{
326 RT_NOREF(nStart, nBytes, dwFlags);
327
[78809]328 LogFlowThisFuncEnter();
[79702]329 return E_NOTIMPL;
[78474]330}
331
[80664]332STDMETHODIMP SharedClipboardWinStreamImpl::Write(const void *pvBuffer, ULONG nBytesToRead, ULONG *nBytesRead)
[78474]333{
334 RT_NOREF(pvBuffer, nBytesToRead, nBytesRead);
335
[78809]336 LogFlowThisFuncEnter();
[78474]337 return E_NOTIMPL;
338}
339
340/*
341 * Own stuff.
342 */
343
[78725]344/**
345 * Factory to create our own IStream implementation.
346 *
347 * @returns HRESULT
[78974]348 * @param pParent Pointer to the parent data object.
[80858]349 * @param pTransfer Pointer to Shared Clipboard transfer object to use.
[79702]350 * @param strPath Path of object to handle for the stream.
351 * @param pObjInfo Pointer to object information.
[78725]352 * @param ppStream Where to return the created stream object on success.
353 */
[78474]354/* static */
[80858]355HRESULT SharedClipboardWinStreamImpl::Create(SharedClipboardWinDataObject *pParent, PSHCLTRANSFER pTransfer,
[80664]356 const Utf8Str &strPath, PSHCLFSOBJINFO pObjInfo,
357 IStream **ppStream)
[78474]358{
[78974]359 AssertPtrReturn(pTransfer, E_POINTER);
[78809]360
[80664]361 SharedClipboardWinStreamImpl *pStream = new SharedClipboardWinStreamImpl(pParent, pTransfer, strPath, pObjInfo);
[78474]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.

© 2023 Oracle
ContactPrivacy policyTerms of Use