VirtualBox

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

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