VirtualBox

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

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