VirtualBox

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

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