VirtualBox

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

Last change on this file since 79107 was 79107, 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.8 KB
Line 
1/* $Id: ClipboardDataObjectImpl-win.cpp 79107 2019-06-12 13:57:04Z 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 const bool fUnicode = lIndex == FormatIndex_FileDescriptorW;
394
395 LogFlowFunc(("FormatIndex_FileDescriptor%s\n", fUnicode ? "W" : "A"));
396
397 int rc = SharedClipboardURITransferMetaDataRead(m_pTransfer, NULL /* cbRead */);
398 if (RT_SUCCESS(rc))
399 {
400 const SharedClipboardURIList *pURIList = SharedClipboardURITransferGetList(m_pTransfer);
401 if ( pURIList
402 && !pURIList->IsEmpty())
403 {
404 HGLOBAL hGlobal;
405 rc = createFileGroupDescriptorFromURIList(*pURIList, fUnicode, &hGlobal);
406 if (RT_SUCCESS(rc))
407 {
408 pMedium->tymed = TYMED_HGLOBAL;
409 pMedium->hGlobal = hGlobal;
410 /* Note: hGlobal now is being owned by pMedium / the caller. */
411
412 hr = S_OK;
413 }
414 }
415 }
416 break;
417 }
418
419 case FormatIndex_FileContents:
420 {
421 LogFlowFunc(("FormatIndex_FileContents: m_uObjIdx=%u\n", m_uObjIdx));
422
423 /* Hand-in the provider so that our IStream implementation can continue working with it. */
424 hr = VBoxClipboardWinStreamImpl::Create(this /* pParent */, m_pTransfer, m_uObjIdx, &m_pStream);
425 if (SUCCEEDED(hr))
426 {
427 /* Hand over the stream to the caller. */
428 pMedium->tymed = TYMED_ISTREAM;
429 pMedium->pstm = m_pStream;
430
431 /* Handle next object. */
432 m_uObjIdx++;
433 }
434 break;
435 }
436
437 default:
438 break;
439 }
440
441 /* Error handling; at least return some basic data. */
442 if (FAILED(hr))
443 {
444 LogFunc(("Failed; copying medium ...\n"));
445
446 pMedium->tymed = pThisFormat->tymed;
447 pMedium->pUnkForRelease = NULL;
448 }
449
450 if (hr == DV_E_FORMATETC)
451 LogRel(("Clipboard: Error handling format\n"));
452
453 LogFlowFunc(("hr=%Rhrc\n", hr));
454 return hr;
455}
456
457/**
458 * Only required for IStream / IStorage interfaces.
459 *
460 * @return IPRT status code.
461 * @return HRESULT
462 * @param pFormatEtc
463 * @param pMedium
464 */
465STDMETHODIMP VBoxClipboardWinDataObject::GetDataHere(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium)
466{
467 RT_NOREF(pFormatEtc, pMedium);
468 LogFlowFunc(("\n"));
469 return E_NOTIMPL;
470}
471
472/**
473 * Query if this objects supports a specific format.
474 *
475 * @return IPRT status code.
476 * @return HRESULT
477 * @param pFormatEtc
478 */
479STDMETHODIMP VBoxClipboardWinDataObject::QueryGetData(LPFORMATETC pFormatEtc)
480{
481 LogFlowFunc(("\n"));
482 return (lookupFormatEtc(pFormatEtc, NULL /* puIndex */)) ? S_OK : DV_E_FORMATETC;
483}
484
485STDMETHODIMP VBoxClipboardWinDataObject::GetCanonicalFormatEtc(LPFORMATETC pFormatEtc, LPFORMATETC pFormatEtcOut)
486{
487 RT_NOREF(pFormatEtc);
488 LogFlowFunc(("\n"));
489
490 /* Set this to NULL in any case. */
491 pFormatEtcOut->ptd = NULL;
492 return E_NOTIMPL;
493}
494
495STDMETHODIMP VBoxClipboardWinDataObject::SetData(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium, BOOL fRelease)
496{
497 RT_NOREF(pFormatEtc, pMedium, fRelease);
498 LogFlowFunc(("\n"));
499
500 return E_NOTIMPL;
501}
502
503STDMETHODIMP VBoxClipboardWinDataObject::EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppEnumFormatEtc)
504{
505 LogFlowFunc(("dwDirection=%RI32, mcFormats=%RI32, mpFormatEtc=%p\n", dwDirection, m_cFormats, m_pFormatEtc));
506
507 HRESULT hr;
508 if (dwDirection == DATADIR_GET)
509 hr = VBoxClipboardWinEnumFormatEtc::CreateEnumFormatEtc(m_cFormats, m_pFormatEtc, ppEnumFormatEtc);
510 else
511 hr = E_NOTIMPL;
512
513 LogFlowFunc(("hr=%Rhrc\n", hr));
514 return hr;
515}
516
517STDMETHODIMP VBoxClipboardWinDataObject::DAdvise(LPFORMATETC pFormatEtc, DWORD fAdvise, IAdviseSink *pAdvSink, DWORD *pdwConnection)
518{
519 RT_NOREF(pFormatEtc, fAdvise, pAdvSink, pdwConnection);
520 return OLE_E_ADVISENOTSUPPORTED;
521}
522
523STDMETHODIMP VBoxClipboardWinDataObject::DUnadvise(DWORD dwConnection)
524{
525 RT_NOREF(dwConnection);
526 return OLE_E_ADVISENOTSUPPORTED;
527}
528
529STDMETHODIMP VBoxClipboardWinDataObject::EnumDAdvise(IEnumSTATDATA **ppEnumAdvise)
530{
531 RT_NOREF(ppEnumAdvise);
532 return OLE_E_ADVISENOTSUPPORTED;
533}
534
535#ifdef VBOX_WITH_SHARED_CLIPBOARD_WIN_ASYNC
536/*
537 * IDataObjectAsyncCapability methods.
538 */
539
540STDMETHODIMP VBoxClipboardWinDataObject::EndOperation(HRESULT hResult, IBindCtx *pbcReserved, DWORD dwEffects)
541{
542 RT_NOREF(hResult, pbcReserved, dwEffects);
543 return E_NOTIMPL;
544}
545
546STDMETHODIMP VBoxClipboardWinDataObject::GetAsyncMode(BOOL *pfIsOpAsync)
547{
548 RT_NOREF(pfIsOpAsync);
549 return E_NOTIMPL;
550}
551
552STDMETHODIMP VBoxClipboardWinDataObject::InOperation(BOOL *pfInAsyncOp)
553{
554 RT_NOREF(pfInAsyncOp);
555 return E_NOTIMPL;
556}
557
558STDMETHODIMP VBoxClipboardWinDataObject::SetAsyncMode(BOOL fDoOpAsync)
559{
560 RT_NOREF(fDoOpAsync);
561 return E_NOTIMPL;
562}
563
564STDMETHODIMP VBoxClipboardWinDataObject::StartOperation(IBindCtx *pbcReserved)
565{
566 RT_NOREF(pbcReserved);
567 return E_NOTIMPL;
568}
569#endif /* VBOX_WITH_SHARED_CLIPBOARD_WIN_ASYNC */
570
571/*
572 * Own stuff.
573 */
574
575int VBoxClipboardWinDataObject::Init(void)
576{
577 LogFlowFuncLeaveRC(VINF_SUCCESS);
578 return VINF_SUCCESS;
579}
580
581void VBoxClipboardWinDataObject::OnTransferComplete(int rc /* = VINF_SUCESS */)
582{
583 RT_NOREF(rc);
584
585 LogFlowFuncLeaveRC(rc);
586}
587
588void VBoxClipboardWinDataObject::OnTransferCanceled(void)
589{
590 LogFlowFuncLeave();
591}
592
593/* static */
594const char* VBoxClipboardWinDataObject::ClipboardFormatToString(CLIPFORMAT fmt)
595{
596#if 0
597 char szFormat[128];
598 if (GetClipboardFormatName(fmt, szFormat, sizeof(szFormat)))
599 LogFlowFunc(("wFormat=%RI16, szName=%s\n", fmt, szFormat));
600#endif
601
602 switch (fmt)
603 {
604
605 case 1:
606 return "CF_TEXT";
607 case 2:
608 return "CF_BITMAP";
609 case 3:
610 return "CF_METAFILEPICT";
611 case 4:
612 return "CF_SYLK";
613 case 5:
614 return "CF_DIF";
615 case 6:
616 return "CF_TIFF";
617 case 7:
618 return "CF_OEMTEXT";
619 case 8:
620 return "CF_DIB";
621 case 9:
622 return "CF_PALETTE";
623 case 10:
624 return "CF_PENDATA";
625 case 11:
626 return "CF_RIFF";
627 case 12:
628 return "CF_WAVE";
629 case 13:
630 return "CF_UNICODETEXT";
631 case 14:
632 return "CF_ENHMETAFILE";
633 case 15:
634 return "CF_HDROP";
635 case 16:
636 return "CF_LOCALE";
637 case 17:
638 return "CF_DIBV5";
639 case 18:
640 return "CF_MAX";
641 case 49158:
642 return "FileName";
643 case 49159:
644 return "FileNameW";
645 case 49161:
646 return "DATAOBJECT";
647 case 49171:
648 return "Ole Private Data";
649 case 49314:
650 return "Shell Object Offsets";
651 case 49316:
652 return "File Contents";
653 case 49317:
654 return "File Group Descriptor";
655 case 49323:
656 return "Preferred Drop Effect";
657 case 49380:
658 return "Shell Object Offsets";
659 case 49382:
660 return "FileContents";
661 case 49383:
662 return "FileGroupDescriptor";
663 case 49389:
664 return "Preferred DropEffect";
665 case 49268:
666 return "Shell IDList Array";
667 case 49619:
668 return "RenPrivateFileAttachments";
669 default:
670 break;
671 }
672
673 return "unknown";
674}
675
676bool VBoxClipboardWinDataObject::lookupFormatEtc(LPFORMATETC pFormatEtc, ULONG *puIndex)
677{
678 AssertReturn(pFormatEtc, false);
679 /* puIndex is optional. */
680
681 for (ULONG i = 0; i < m_cFormats; i++)
682 {
683 if( (pFormatEtc->tymed & m_pFormatEtc[i].tymed)
684 && pFormatEtc->cfFormat == m_pFormatEtc[i].cfFormat)
685 /* Note: Do *not* compare dwAspect here, as this can be dynamic, depending on how the object should be represented. */
686 //&& pFormatEtc->dwAspect == m_pFormatEtc[i].dwAspect)
687 {
688 LogRel3(("Clipboard: Format found: tyMed=%RI32, cfFormat=%RI16, sFormats=%s, dwAspect=%RI32, ulIndex=%RU32\n",
689 pFormatEtc->tymed, pFormatEtc->cfFormat, VBoxClipboardWinDataObject::ClipboardFormatToString(m_pFormatEtc[i].cfFormat),
690 pFormatEtc->dwAspect, i));
691 if (puIndex)
692 *puIndex = i;
693 return true;
694 }
695 }
696
697 LogRel3(("Clipboard: Format NOT found: tyMed=%RI32, cfFormat=%RI16, sFormats=%s, dwAspect=%RI32\n",
698 pFormatEtc->tymed, pFormatEtc->cfFormat, VBoxClipboardWinDataObject::ClipboardFormatToString(pFormatEtc->cfFormat),
699 pFormatEtc->dwAspect));
700
701 return false;
702}
703
704void VBoxClipboardWinDataObject::registerFormat(LPFORMATETC pFormatEtc, CLIPFORMAT clipFormat,
705 TYMED tyMed, LONG lIndex, DWORD dwAspect,
706 DVTARGETDEVICE *pTargetDevice)
707{
708 AssertPtr(pFormatEtc);
709
710 pFormatEtc->cfFormat = clipFormat;
711 pFormatEtc->tymed = tyMed;
712 pFormatEtc->lindex = lIndex;
713 pFormatEtc->dwAspect = dwAspect;
714 pFormatEtc->ptd = pTargetDevice;
715
716 LogFlowFunc(("Registered format=%ld, sFormat=%s\n",
717 pFormatEtc->cfFormat, VBoxClipboardWinDataObject::ClipboardFormatToString(pFormatEtc->cfFormat)));
718}
719
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