VirtualBox

source: vbox/trunk/src/VBox/GuestHost/SharedClipboard/ClipboardDataObjectImpl-win.cpp@ 79299

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

Shared Clipboard/URI: Update.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.5 KB
Line 
1/* $Id: ClipboardDataObjectImpl-win.cpp 79299 2019-06-24 10:18:19Z vboxsync $ */
2/** @file
3 * ClipboardDataObjectImpl-win.cpp - Shared Clipboard IDataObject implementation.
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#include <VBox/GuestHost/SharedClipboard-uri.h>
25
26/** !!! HACK ALERT !!! Dynamically resolve functions! */
27#ifdef _WIN32_IE
28#undef _WIN32_IE
29#define _WIN32_IE 0x0501
30#endif
31
32#include <iprt/win/windows.h>
33#include <iprt/win/shlobj.h>
34#include <iprt/win/shlwapi.h>
35
36#include <iprt/path.h>
37#include <iprt/semaphore.h>
38#include <iprt/uri.h>
39#include <iprt/utf16.h>
40
41#include <iprt/errcore.h>
42#include <VBox/log.h>
43
44/** Also handle Unicode entries. */
45#define VBOX_CLIPBOARD_WITH_UNICODE_SUPPORT 1
46
47VBoxClipboardWinDataObject::VBoxClipboardWinDataObject(PSHAREDCLIPBOARDURITRANSFER pTransfer,
48 LPFORMATETC pFormatEtc, LPSTGMEDIUM pStgMed, ULONG cFormats)
49 : m_enmStatus(Uninitialized)
50 , m_lRefCount(1)
51 , m_cFormats(0)
52 , m_pTransfer(pTransfer)
53 , m_pStream(NULL)
54 , m_uObjIdx(0)
55{
56 AssertPtr(m_pTransfer);
57
58 HRESULT hr;
59
60 ULONG cFixedFormats = 2; /* CFSTR_FILEDESCRIPTORA + CFSTR_FILECONTENTS */
61#ifdef VBOX_CLIPBOARD_WITH_UNICODE_SUPPORT
62 cFixedFormats++; /* CFSTR_FILEDESCRIPTORW */
63#endif
64 const ULONG cAllFormats = cFormats + cFixedFormats;
65
66 try
67 {
68 m_pFormatEtc = new FORMATETC[cAllFormats];
69 RT_BZERO(m_pFormatEtc, sizeof(FORMATETC) * cAllFormats);
70 m_pStgMedium = new STGMEDIUM[cAllFormats];
71 RT_BZERO(m_pStgMedium, sizeof(STGMEDIUM) * cAllFormats);
72
73 /** @todo Do we need CFSTR_FILENAME / CFSTR_SHELLIDLIST here? */
74
75 /*
76 * Register fixed formats.
77 */
78
79 LogFlowFunc(("Registering CFSTR_FILEDESCRIPTORA ...\n"));
80 registerFormat(&m_pFormatEtc[FormatIndex_FileDescriptorA],
81 RegisterClipboardFormat(CFSTR_FILEDESCRIPTORA));
82#ifdef VBOX_CLIPBOARD_WITH_UNICODE_SUPPORT
83 LogFlowFunc(("Registering CFSTR_FILEDESCRIPTORW ...\n"));
84 registerFormat(&m_pFormatEtc[FormatIndex_FileDescriptorW],
85 RegisterClipboardFormat(CFSTR_FILEDESCRIPTORW));
86#endif
87 /* IStream interface, implemented in ClipboardStreamImpl-win.cpp. */
88 LogFlowFunc(("Registering CFSTR_FILECONTENTS ...\n"));
89 registerFormat(&m_pFormatEtc[FormatIndex_FileContents],
90 RegisterClipboardFormat(CFSTR_FILECONTENTS),
91 TYMED_ISTREAM, 0 /* lIndex */);
92
93 /*
94 * Registration of dynamic formats needed?
95 */
96 LogFlowFunc(("%RU32 dynamic formats\n", cFormats));
97 if (cFormats)
98 {
99 AssertPtr(pFormatEtc);
100 AssertPtr(pStgMed);
101
102 for (ULONG i = 0; i < cFormats; i++)
103 {
104 LogFlowFunc(("Format %RU32: cfFormat=%RI16, tyMed=%RU32, dwAspect=%RU32\n",
105 i, pFormatEtc[i].cfFormat, pFormatEtc[i].tymed, pFormatEtc[i].dwAspect));
106 m_pFormatEtc[cFixedFormats + i] = pFormatEtc[i];
107 m_pStgMedium[cFixedFormats + i] = pStgMed[i];
108 }
109 }
110
111 hr = S_OK;
112 }
113 catch (std::bad_alloc &)
114 {
115 hr = E_OUTOFMEMORY;
116 }
117
118 if (SUCCEEDED(hr))
119 {
120 m_cFormats = cAllFormats;
121 m_enmStatus = Initialized;
122
123 int rc2 = RTSemEventCreate(&m_EventMetaDataComplete);
124 AssertRC(rc2);
125
126 AssertPtr(m_pTransfer->pProvider);
127 m_pTransfer->pProvider->AddRef();
128 }
129
130 LogFlowFunc(("cAllFormats=%RU32, hr=%Rhrc\n", cAllFormats, hr));
131}
132
133VBoxClipboardWinDataObject::~VBoxClipboardWinDataObject(void)
134{
135 RTSemEventDestroy(m_EventMetaDataComplete);
136
137 if (m_pTransfer->pProvider)
138 m_pTransfer->pProvider->Release();
139
140 if (m_pStream)
141 m_pStream->Release();
142
143 if (m_pFormatEtc)
144 delete[] m_pFormatEtc;
145
146 if (m_pStgMedium)
147 delete[] m_pStgMedium;
148
149 LogFlowFunc(("mRefCount=%RI32\n", m_lRefCount));
150}
151
152/*
153 * IUnknown methods.
154 */
155
156STDMETHODIMP_(ULONG) VBoxClipboardWinDataObject::AddRef(void)
157{
158 LONG lCount = InterlockedIncrement(&m_lRefCount);
159 LogFlowFunc(("lCount=%RI32\n", lCount));
160 return lCount;
161}
162
163STDMETHODIMP_(ULONG) VBoxClipboardWinDataObject::Release(void)
164{
165 LONG lCount = InterlockedDecrement(&m_lRefCount);
166 LogFlowFunc(("lCount=%RI32\n", m_lRefCount));
167 if (lCount == 0)
168 {
169 delete this;
170 return 0;
171 }
172
173 return lCount;
174}
175
176STDMETHODIMP VBoxClipboardWinDataObject::QueryInterface(REFIID iid, void **ppvObject)
177{
178 AssertPtrReturn(ppvObject, E_INVALIDARG);
179
180 if ( iid == IID_IDataObject
181 || iid == IID_IUnknown)
182 {
183 AddRef();
184 *ppvObject = this;
185 return S_OK;
186 }
187
188 *ppvObject = 0;
189 return E_NOINTERFACE;
190}
191
192/**
193 * Copies a chunk of data into a HGLOBAL object.
194 *
195 * @returns VBox status code.
196 * @param pvData Data to copy.
197 * @param cbData Size (in bytes) to copy.
198 * @param fFlags GlobalAlloc flags, used for allocating the HGLOBAL block.
199 * @param phGlobal Where to store the allocated HGLOBAL object.
200 */
201int VBoxClipboardWinDataObject::copyToHGlobal(const void *pvData, size_t cbData, UINT fFlags, HGLOBAL *phGlobal)
202{
203 AssertPtrReturn(phGlobal, VERR_INVALID_POINTER);
204
205 HGLOBAL hGlobal = GlobalAlloc(fFlags, cbData);
206 if (!hGlobal)
207 return VERR_NO_MEMORY;
208
209 void *pvAlloc = GlobalLock(hGlobal);
210 if (pvAlloc)
211 {
212 CopyMemory(pvAlloc, pvData, cbData);
213 GlobalUnlock(hGlobal);
214
215 *phGlobal = hGlobal;
216
217 return VINF_SUCCESS;
218 }
219
220 GlobalFree(hGlobal);
221 return VERR_ACCESS_DENIED;
222}
223
224/**
225 * Creates a FILEGROUPDESCRIPTOR object from a given URI transfer and stores the result into an HGLOBAL object.
226 *
227 * @returns VBox status code.
228 * @param pTransfer URI transfer to create file grou desciprtor for.
229 * @param fUnicode Whether the FILEGROUPDESCRIPTOR object shall contain Unicode data or not.
230 * @param phGlobal Where to store the allocated HGLOBAL object on success.
231 */
232int VBoxClipboardWinDataObject::createFileGroupDescriptorFromTransfer(PSHAREDCLIPBOARDURITRANSFER pTransfer,
233 bool fUnicode, HGLOBAL *phGlobal)
234{
235 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
236 AssertPtrReturn(phGlobal, VERR_INVALID_POINTER);
237
238 LogFlowFuncEnter();
239
240 SharedClipboardURIList *pURIList = SharedClipboardURITransferGetList(pTransfer);
241 if (!pURIList)
242 return VERR_WRONG_ORDER;
243
244 const size_t cbFileGroupDescriptor = fUnicode ? sizeof(FILEGROUPDESCRIPTORW) : sizeof(FILEGROUPDESCRIPTORA);
245 const size_t cbFileDescriptor = fUnicode ? sizeof(FILEDESCRIPTORW) : sizeof(FILEDESCRIPTORA);
246
247 const UINT cItems = (UINT)pURIList->GetRootCount(); /** @todo UINT vs. uint64_t */
248 const size_t cbFGD = cbFileGroupDescriptor + (cbFileDescriptor * (cItems - 1));
249
250 LogFunc(("fUnicode=%RTbool, cItems=%u, cbFileDescriptor=%zu\n", fUnicode, cItems, cbFileDescriptor));
251
252 /* FILEGROUPDESCRIPTORA / FILEGROUPDESCRIPTOR matches except the cFileName member (TCHAR vs. WCHAR). */
253 FILEGROUPDESCRIPTOR *pFGD = (FILEGROUPDESCRIPTOR *)RTMemAlloc(cbFGD);
254 if (!pFGD)
255 return VERR_NO_MEMORY;
256
257 int rc = VINF_SUCCESS;
258
259 pFGD->cItems = cItems;
260
261 char *pszFileSpec = NULL;
262
263 for (UINT i = 0; i < cItems; i++)
264 {
265 FILEDESCRIPTOR *pFD = &pFGD->fgd[i];
266 RT_BZERO(pFD, cbFileDescriptor);
267
268 const SharedClipboardURIObject *pObj = pURIList->At(i);
269 AssertPtr(pObj);
270 const char *pszFile = pObj->GetSourcePathAbs().c_str();
271 AssertPtr(pszFile);
272
273 pszFileSpec = RTStrDup(pszFile);
274 AssertBreakStmt(pszFileSpec != NULL, rc = VERR_NO_MEMORY);
275
276 if (fUnicode)
277 {
278 PRTUTF16 pwszFileSpec;
279 rc = RTStrToUtf16(pszFileSpec, &pwszFileSpec);
280 if (RT_SUCCESS(rc))
281 {
282 rc = RTUtf16CopyEx((PRTUTF16 )pFD->cFileName, sizeof(pFD->cFileName) / sizeof(WCHAR),
283 pwszFileSpec, RTUtf16Len(pwszFileSpec));
284 RTUtf16Free(pwszFileSpec);
285 }
286 }
287 else
288 rc = RTStrCopy(pFD->cFileName, sizeof(pFD->cFileName), pszFileSpec);
289
290 RTStrFree(pszFileSpec);
291 pszFileSpec = NULL;
292
293 if (RT_FAILURE(rc))
294 break;
295
296 pFD->dwFlags = FD_PROGRESSUI | FD_ATTRIBUTES;
297 if (fUnicode) /** @todo Only >= Vista. */
298 pFD->dwFlags |= FD_UNICODE;
299 pFD->dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
300
301 switch (pObj->GetType())
302 {
303 case SharedClipboardURIObject::Type_Directory:
304 pFD->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
305
306 LogFunc(("pszDir=%s\n", pszFile));
307 break;
308
309 case SharedClipboardURIObject::Type_File:
310 {
311 pFD->dwFlags |= FD_FILESIZE;
312
313 const uint64_t cbObjSize = pObj->GetSize();
314
315 pFD->nFileSizeHigh = RT_HI_U32(cbObjSize);
316 pFD->nFileSizeLow = RT_LO_U32(cbObjSize);
317
318 LogFunc(("pszFile=%s, cbObjSize=%RU64\n", pszFile, cbObjSize));
319 break;
320 }
321
322 default:
323 AssertFailed();
324 break;
325 }
326#if 0
327 pFD->dwFlags = FD_ATTRIBUTES | FD_CREATETIME | FD_ACCESSTIME | FD_WRITESTIME | FD_FILESIZE; /** @todo Implement this. */
328 pFD->dwFileAttributes =
329 pFD->ftCreationTime =
330 pFD->ftLastAccessTime =
331 pFD->ftLastWriteTime =
332#endif
333 }
334
335 if (pszFileSpec)
336 RTStrFree(pszFileSpec);
337
338 if (RT_SUCCESS(rc))
339 {
340 rc = copyToHGlobal(pFGD, cbFGD, GMEM_MOVEABLE, phGlobal);
341 }
342 else
343 {
344 RTMemFree(pFGD);
345 }
346
347 LogFlowFuncLeaveRC(rc);
348 return rc;
349}
350
351/**
352 * Retrieves the data stored in this object and store the result in
353 * pMedium.
354 *
355 * @return IPRT status code.
356 * @return HRESULT
357 * @param pFormatEtc
358 * @param pMedium
359 */
360STDMETHODIMP VBoxClipboardWinDataObject::GetData(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium)
361{
362 AssertPtrReturn(pFormatEtc, DV_E_FORMATETC);
363 AssertPtrReturn(pMedium, DV_E_FORMATETC);
364
365 LogFlowFuncEnter();
366
367 ULONG lIndex;
368 if (!lookupFormatEtc(pFormatEtc, &lIndex)) /* Format supported? */
369 return DV_E_FORMATETC;
370 if (lIndex >= m_cFormats) /* Paranoia. */
371 return DV_E_LINDEX;
372
373 LPFORMATETC pThisFormat = &m_pFormatEtc[lIndex];
374 AssertPtr(pThisFormat);
375
376 LPSTGMEDIUM pThisMedium = &m_pStgMedium[lIndex];
377 AssertPtr(pThisMedium);
378
379 LogFlowFunc(("Using pThisFormat=%p, pThisMedium=%p\n", pThisFormat, pThisMedium));
380
381 HRESULT hr = DV_E_FORMATETC; /* Play safe. */
382
383 LogRel2(("Shared Clipboard: cfFormat=%RI16, sFormat=%s, tyMed=%RU32, dwAspect=%RU32 -> lIndex=%u\n",
384 pThisFormat->cfFormat, VBoxClipboardWinDataObject::ClipboardFormatToString(pFormatEtc->cfFormat),
385 pThisFormat->tymed, pThisFormat->dwAspect, lIndex));
386
387 /*
388 * Initialize default values.
389 */
390 pMedium->tymed = pThisFormat->tymed;
391 pMedium->pUnkForRelease = NULL; /* Caller is responsible for deleting the data. */
392
393 switch (lIndex)
394 {
395 case FormatIndex_FileDescriptorA: /* ANSI */
396#ifdef VBOX_CLIPBOARD_WITH_UNICODE_SUPPORT
397 RT_FALL_THROUGH();
398 case FormatIndex_FileDescriptorW: /* Unicode */
399#endif
400 {
401 int rc = SharedClipboardURITransferPrepare(m_pTransfer);
402 if (RT_SUCCESS(rc))
403 {
404 const bool fUnicode = lIndex == FormatIndex_FileDescriptorW;
405
406 LogFlowFunc(("FormatIndex_FileDescriptor%s\n", fUnicode ? "W" : "A"));
407
408 /* Register needed callbacks so that we can wait for the meta data to arrive here. */
409 SHAREDCLIPBOARDURITRANSFERCALLBACKS Callbacks;
410 RT_ZERO(Callbacks);
411 Callbacks.pfnMetaDataComplete = VBoxClipboardWinDataObject::onMetaDataCompleteCallback;
412
413 SharedClipboardURITransferSetCallbacks(m_pTransfer, &Callbacks);
414
415 /* Start the transfer asynchronously in a separate thread. */
416 rc = SharedClipboardURITransferRun(m_pTransfer, true /* fAsync */);
417 if (RT_SUCCESS(rc))
418 {
419 /* Wait for the meta data to arrive. */
420 LogFlowFunc(("Waiting for meta data to arrive ...\n"));
421 rc = RTSemEventWait(m_EventMetaDataComplete, 30 * 1000 /* 30s timeout */);
422 if (RT_SUCCESS(rc))
423 {
424 const SharedClipboardURIList *pURIList = SharedClipboardURITransferGetList(m_pTransfer);
425 if ( pURIList
426 && !pURIList->IsEmpty())
427 {
428 HGLOBAL hGlobal;
429 rc = createFileGroupDescriptorFromTransfer(m_pTransfer, fUnicode, &hGlobal);
430 if (RT_SUCCESS(rc))
431 {
432 pMedium->tymed = TYMED_HGLOBAL;
433 pMedium->hGlobal = hGlobal;
434 /* Note: hGlobal now is being owned by pMedium / the caller. */
435
436 hr = S_OK;
437 }
438 }
439 }
440 }
441 }
442 break;
443 }
444
445 case FormatIndex_FileContents:
446 {
447 LogFlowFunc(("FormatIndex_FileContents: m_uObjIdx=%u\n", m_uObjIdx));
448
449 /* Hand-in the provider so that our IStream implementation can continue working with it. */
450 hr = VBoxClipboardWinStreamImpl::Create(this /* pParent */, m_pTransfer, m_uObjIdx, &m_pStream);
451 if (SUCCEEDED(hr))
452 {
453 /* Hand over the stream to the caller. */
454 pMedium->tymed = TYMED_ISTREAM;
455 pMedium->pstm = m_pStream;
456
457 /* Handle next object. */
458 m_uObjIdx++;
459 }
460 break;
461 }
462
463 default:
464 break;
465 }
466
467 /* Error handling; at least return some basic data. */
468 if (FAILED(hr))
469 {
470 LogFunc(("Failed; copying medium ...\n"));
471
472 pMedium->tymed = pThisFormat->tymed;
473 pMedium->pUnkForRelease = NULL;
474 }
475
476 if (hr == DV_E_FORMATETC)
477 LogRel(("Shared Clipboard: Error handling format\n"));
478
479 LogFlowFunc(("hr=%Rhrc\n", hr));
480 return hr;
481}
482
483/**
484 * Only required for IStream / IStorage interfaces.
485 *
486 * @return IPRT status code.
487 * @return HRESULT
488 * @param pFormatEtc
489 * @param pMedium
490 */
491STDMETHODIMP VBoxClipboardWinDataObject::GetDataHere(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium)
492{
493 RT_NOREF(pFormatEtc, pMedium);
494 LogFlowFunc(("\n"));
495 return E_NOTIMPL;
496}
497
498/**
499 * Query if this objects supports a specific format.
500 *
501 * @return IPRT status code.
502 * @return HRESULT
503 * @param pFormatEtc
504 */
505STDMETHODIMP VBoxClipboardWinDataObject::QueryGetData(LPFORMATETC pFormatEtc)
506{
507 LogFlowFunc(("\n"));
508 return (lookupFormatEtc(pFormatEtc, NULL /* puIndex */)) ? S_OK : DV_E_FORMATETC;
509}
510
511STDMETHODIMP VBoxClipboardWinDataObject::GetCanonicalFormatEtc(LPFORMATETC pFormatEtc, LPFORMATETC pFormatEtcOut)
512{
513 RT_NOREF(pFormatEtc);
514 LogFlowFunc(("\n"));
515
516 /* Set this to NULL in any case. */
517 pFormatEtcOut->ptd = NULL;
518 return E_NOTIMPL;
519}
520
521STDMETHODIMP VBoxClipboardWinDataObject::SetData(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium, BOOL fRelease)
522{
523 RT_NOREF(pFormatEtc, pMedium, fRelease);
524 LogFlowFunc(("\n"));
525
526 return E_NOTIMPL;
527}
528
529STDMETHODIMP VBoxClipboardWinDataObject::EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppEnumFormatEtc)
530{
531 LogFlowFunc(("dwDirection=%RI32, mcFormats=%RI32, mpFormatEtc=%p\n", dwDirection, m_cFormats, m_pFormatEtc));
532
533 HRESULT hr;
534 if (dwDirection == DATADIR_GET)
535 hr = VBoxClipboardWinEnumFormatEtc::CreateEnumFormatEtc(m_cFormats, m_pFormatEtc, ppEnumFormatEtc);
536 else
537 hr = E_NOTIMPL;
538
539 LogFlowFunc(("hr=%Rhrc\n", hr));
540 return hr;
541}
542
543STDMETHODIMP VBoxClipboardWinDataObject::DAdvise(LPFORMATETC pFormatEtc, DWORD fAdvise, IAdviseSink *pAdvSink, DWORD *pdwConnection)
544{
545 RT_NOREF(pFormatEtc, fAdvise, pAdvSink, pdwConnection);
546 return OLE_E_ADVISENOTSUPPORTED;
547}
548
549STDMETHODIMP VBoxClipboardWinDataObject::DUnadvise(DWORD dwConnection)
550{
551 RT_NOREF(dwConnection);
552 return OLE_E_ADVISENOTSUPPORTED;
553}
554
555STDMETHODIMP VBoxClipboardWinDataObject::EnumDAdvise(IEnumSTATDATA **ppEnumAdvise)
556{
557 RT_NOREF(ppEnumAdvise);
558 return OLE_E_ADVISENOTSUPPORTED;
559}
560
561#ifdef VBOX_WITH_SHARED_CLIPBOARD_WIN_ASYNC
562/*
563 * IDataObjectAsyncCapability methods.
564 */
565
566STDMETHODIMP VBoxClipboardWinDataObject::EndOperation(HRESULT hResult, IBindCtx *pbcReserved, DWORD dwEffects)
567{
568 RT_NOREF(hResult, pbcReserved, dwEffects);
569 return E_NOTIMPL;
570}
571
572STDMETHODIMP VBoxClipboardWinDataObject::GetAsyncMode(BOOL *pfIsOpAsync)
573{
574 RT_NOREF(pfIsOpAsync);
575 return E_NOTIMPL;
576}
577
578STDMETHODIMP VBoxClipboardWinDataObject::InOperation(BOOL *pfInAsyncOp)
579{
580 RT_NOREF(pfInAsyncOp);
581 return E_NOTIMPL;
582}
583
584STDMETHODIMP VBoxClipboardWinDataObject::SetAsyncMode(BOOL fDoOpAsync)
585{
586 RT_NOREF(fDoOpAsync);
587 return E_NOTIMPL;
588}
589
590STDMETHODIMP VBoxClipboardWinDataObject::StartOperation(IBindCtx *pbcReserved)
591{
592 RT_NOREF(pbcReserved);
593 return E_NOTIMPL;
594}
595#endif /* VBOX_WITH_SHARED_CLIPBOARD_WIN_ASYNC */
596
597/*
598 * Own stuff.
599 */
600
601int VBoxClipboardWinDataObject::Init(void)
602{
603 LogFlowFuncLeaveRC(VINF_SUCCESS);
604 return VINF_SUCCESS;
605}
606
607void VBoxClipboardWinDataObject::OnTransferComplete(int rc /* = VINF_SUCESS */)
608{
609 RT_NOREF(rc);
610
611 LogFlowFuncLeaveRC(rc);
612}
613
614void VBoxClipboardWinDataObject::OnTransferCanceled(void)
615{
616 LogFlowFuncLeave();
617}
618
619/* static */
620const char* VBoxClipboardWinDataObject::ClipboardFormatToString(CLIPFORMAT fmt)
621{
622#if 0
623 char szFormat[128];
624 if (GetClipboardFormatName(fmt, szFormat, sizeof(szFormat)))
625 LogFlowFunc(("wFormat=%RI16, szName=%s\n", fmt, szFormat));
626#endif
627
628 switch (fmt)
629 {
630
631 case 1:
632 return "CF_TEXT";
633 case 2:
634 return "CF_BITMAP";
635 case 3:
636 return "CF_METAFILEPICT";
637 case 4:
638 return "CF_SYLK";
639 case 5:
640 return "CF_DIF";
641 case 6:
642 return "CF_TIFF";
643 case 7:
644 return "CF_OEMTEXT";
645 case 8:
646 return "CF_DIB";
647 case 9:
648 return "CF_PALETTE";
649 case 10:
650 return "CF_PENDATA";
651 case 11:
652 return "CF_RIFF";
653 case 12:
654 return "CF_WAVE";
655 case 13:
656 return "CF_UNICODETEXT";
657 case 14:
658 return "CF_ENHMETAFILE";
659 case 15:
660 return "CF_HDROP";
661 case 16:
662 return "CF_LOCALE";
663 case 17:
664 return "CF_DIBV5";
665 case 18:
666 return "CF_MAX";
667 case 49158:
668 return "FileName";
669 case 49159:
670 return "FileNameW";
671 case 49161:
672 return "DATAOBJECT";
673 case 49171:
674 return "Ole Private Data";
675 case 49314:
676 return "Shell Object Offsets";
677 case 49316:
678 return "File Contents";
679 case 49317:
680 return "File Group Descriptor";
681 case 49323:
682 return "Preferred Drop Effect";
683 case 49380:
684 return "Shell Object Offsets";
685 case 49382:
686 return "FileContents";
687 case 49383:
688 return "FileGroupDescriptor";
689 case 49389:
690 return "Preferred DropEffect";
691 case 49268:
692 return "Shell IDList Array";
693 case 49619:
694 return "RenPrivateFileAttachments";
695 default:
696 break;
697 }
698
699 return "unknown";
700}
701
702bool VBoxClipboardWinDataObject::lookupFormatEtc(LPFORMATETC pFormatEtc, ULONG *puIndex)
703{
704 AssertReturn(pFormatEtc, false);
705 /* puIndex is optional. */
706
707 for (ULONG i = 0; i < m_cFormats; i++)
708 {
709 if( (pFormatEtc->tymed & m_pFormatEtc[i].tymed)
710 && pFormatEtc->cfFormat == m_pFormatEtc[i].cfFormat)
711 /* Note: Do *not* compare dwAspect here, as this can be dynamic, depending on how the object should be represented. */
712 //&& pFormatEtc->dwAspect == m_pFormatEtc[i].dwAspect)
713 {
714 LogRel3(("Shared Clipboard: Format found: tyMed=%RI32, cfFormat=%RI16, sFormats=%s, dwAspect=%RI32, ulIndex=%RU32\n",
715 pFormatEtc->tymed, pFormatEtc->cfFormat, VBoxClipboardWinDataObject::ClipboardFormatToString(m_pFormatEtc[i].cfFormat),
716 pFormatEtc->dwAspect, i));
717 if (puIndex)
718 *puIndex = i;
719 return true;
720 }
721 }
722
723 LogRel3(("Shared Clipboard: Format NOT found: tyMed=%RI32, cfFormat=%RI16, sFormats=%s, dwAspect=%RI32\n",
724 pFormatEtc->tymed, pFormatEtc->cfFormat, VBoxClipboardWinDataObject::ClipboardFormatToString(pFormatEtc->cfFormat),
725 pFormatEtc->dwAspect));
726
727 return false;
728}
729
730void VBoxClipboardWinDataObject::registerFormat(LPFORMATETC pFormatEtc, CLIPFORMAT clipFormat,
731 TYMED tyMed, LONG lIndex, DWORD dwAspect,
732 DVTARGETDEVICE *pTargetDevice)
733{
734 AssertPtr(pFormatEtc);
735
736 pFormatEtc->cfFormat = clipFormat;
737 pFormatEtc->tymed = tyMed;
738 pFormatEtc->lindex = lIndex;
739 pFormatEtc->dwAspect = dwAspect;
740 pFormatEtc->ptd = pTargetDevice;
741
742 LogFlowFunc(("Registered format=%ld, sFormat=%s\n",
743 pFormatEtc->cfFormat, VBoxClipboardWinDataObject::ClipboardFormatToString(pFormatEtc->cfFormat)));
744}
745
746/* static */
747DECLCALLBACK(void) VBoxClipboardWinDataObject::onMetaDataCompleteCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData)
748{
749 VBoxClipboardWinDataObject *pThis = (VBoxClipboardWinDataObject *)pData->pvUser;
750
751 LogFlowFunc(("pThis=%p\n", pThis));
752
753 int rc2 = RTSemEventSignal(pThis->m_EventMetaDataComplete);
754 AssertRC(rc2);
755}
756
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