VirtualBox

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

Last change on this file since 79268 was 79267, checked in by vboxsync, 6 years ago

Shared Clipboard/URI: Update.

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