VirtualBox

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

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

Shared Clipboard/URI: SCM fixes.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.3 KB
Line 
1/* $Id: ClipboardDataObjectImpl-win.cpp 78443 2019-05-07 18:00:52Z 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
25#include <iprt/win/windows.h>
26#include <new> /* For bad_alloc. */
27#include <iprt/win/shlobj.h>
28
29#include <iprt/path.h>
30#include <iprt/semaphore.h>
31#include <iprt/uri.h>
32#include <iprt/utf16.h>
33
34#include <VBox/log.h>
35
36VBoxClipboardWinDataObject::VBoxClipboardWinDataObject(LPFORMATETC pFormatEtc, LPSTGMEDIUM pStgMed, ULONG cFormats)
37 : mStatus(Uninitialized),
38 mRefCount(1),
39 mcFormats(0),
40 mpvData(NULL),
41 mcbData(0)
42{
43 HRESULT hr;
44
45 ULONG cFixedFormats = 1;
46 ULONG cAllFormats = cFormats + cFixedFormats;
47
48 try
49 {
50 mpFormatEtc = new FORMATETC[cAllFormats];
51 RT_BZERO(mpFormatEtc, sizeof(FORMATETC) * cAllFormats);
52 mpStgMedium = new STGMEDIUM[cAllFormats];
53 RT_BZERO(mpStgMedium, sizeof(STGMEDIUM) * cAllFormats);
54
55 /*
56 * Registration of dynamic formats needed?
57 */
58 LogFlowFunc(("%RU32 dynamic formats\n", cFormats));
59 if (cFormats)
60 {
61 AssertPtr(pFormatEtc);
62 AssertPtr(pStgMed);
63
64 for (ULONG i = 0; i < cFormats; i++)
65 {
66 LogFlowFunc(("Format %RU32: cfFormat=%RI16, tyMed=%RU32, dwAspect=%RU32\n",
67 i, pFormatEtc[i].cfFormat, pFormatEtc[i].tymed, pFormatEtc[i].dwAspect));
68 mpFormatEtc[i] = pFormatEtc[i];
69 mpStgMedium[i] = pStgMed[i];
70 }
71 }
72
73 hr = S_OK;
74 }
75 catch (std::bad_alloc &)
76 {
77 hr = E_OUTOFMEMORY;
78 }
79
80 if (SUCCEEDED(hr))
81 {
82 int rc2 = RTSemEventCreate(&mEventDropped);
83 AssertRC(rc2);
84
85 /*
86 * Register fixed formats.
87 */
88#if 0
89 /* CF_HDROP. */
90 RegisterFormat(&mpFormatEtc[cFormats], CF_HDROP);
91 mpStgMedium[cFormats++].tymed = TYMED_HGLOBAL;
92
93 /* IStream. */
94 RegisterFormat(&mpFormatEtc[cFormats++],
95 RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR));
96 RegisterFormat(&mpFormatEtc[cFormats++],
97 RegisterClipboardFormat(CFSTR_FILECONTENTS),
98 TYMED_ISTREAM, 0 /* lIndex */);
99
100 /* Required for e.g. Windows Media Player. */
101 RegisterFormat(&mpFormatEtc[cFormats++],
102 RegisterClipboardFormat(CFSTR_FILENAME));
103 RegisterFormat(&mpFormatEtc[cFormats++],
104 RegisterClipboardFormat(CFSTR_FILENAMEW));
105 RegisterFormat(&mpFormatEtc[cFormats++],
106 RegisterClipboardFormat(CFSTR_SHELLIDLIST));
107 RegisterFormat(&mpFormatEtc[cFormats++],
108 RegisterClipboardFormat(CFSTR_SHELLIDLISTOFFSET));
109#endif
110 mcFormats = cFormats;
111 mStatus = Initialized;
112 }
113
114 LogFlowFunc(("cFormats=%RU32, hr=%Rhrc\n", cFormats, hr));
115}
116
117VBoxClipboardWinDataObject::~VBoxClipboardWinDataObject(void)
118{
119 if (mpFormatEtc)
120 delete[] mpFormatEtc;
121
122 if (mpStgMedium)
123 delete[] mpStgMedium;
124
125 if (mpvData)
126 RTMemFree(mpvData);
127
128 LogFlowFunc(("mRefCount=%RI32\n", mRefCount));
129}
130
131/*
132 * IUnknown methods.
133 */
134
135STDMETHODIMP_(ULONG) VBoxClipboardWinDataObject::AddRef(void)
136{
137 return InterlockedIncrement(&mRefCount);
138}
139
140STDMETHODIMP_(ULONG) VBoxClipboardWinDataObject::Release(void)
141{
142 LONG lCount = InterlockedDecrement(&mRefCount);
143 if (lCount == 0)
144 {
145 delete this;
146 return 0;
147 }
148
149 return lCount;
150}
151
152STDMETHODIMP VBoxClipboardWinDataObject::QueryInterface(REFIID iid, void **ppvObject)
153{
154 AssertPtrReturn(ppvObject, E_INVALIDARG);
155
156 if ( iid == IID_IDataObject
157 || iid == IID_IUnknown)
158 {
159 AddRef();
160 *ppvObject = this;
161 return S_OK;
162 }
163
164 *ppvObject = 0;
165 return E_NOINTERFACE;
166}
167
168/**
169 * Retrieves the data stored in this object and store the result in
170 * pMedium.
171 *
172 * @return IPRT status code.
173 * @return HRESULT
174 * @param pFormatEtc
175 * @param pMedium
176 */
177STDMETHODIMP VBoxClipboardWinDataObject::GetData(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium)
178{
179 AssertPtrReturn(pFormatEtc, DV_E_FORMATETC);
180 AssertPtrReturn(pMedium, DV_E_FORMATETC);
181
182 ULONG lIndex;
183 if (!LookupFormatEtc(pFormatEtc, &lIndex)) /* Format supported? */
184 return DV_E_FORMATETC;
185 if (lIndex >= mcFormats) /* Paranoia. */
186 return DV_E_FORMATETC;
187
188 LPFORMATETC pThisFormat = &mpFormatEtc[lIndex];
189 AssertPtr(pThisFormat);
190
191 LPSTGMEDIUM pThisMedium = &mpStgMedium[lIndex];
192 AssertPtr(pThisMedium);
193
194 LogFlowFunc(("Using pThisFormat=%p, pThisMedium=%p\n", pThisFormat, pThisMedium));
195
196 HRESULT hr = DV_E_FORMATETC; /* Play safe. */
197
198 LogFlowFunc(("mStatus=%ld\n", mStatus));
199 if (mStatus == Dropping)
200 {
201 LogRel2(("Clipboard: Waiting for drop event ...\n"));
202 int rc2 = RTSemEventWait(mEventDropped, RT_INDEFINITE_WAIT);
203 LogFlowFunc(("rc2=%Rrc, mStatus=%ld\n", rc2, mStatus)); RT_NOREF(rc2);
204 }
205
206 if (mStatus == Dropped)
207 {
208 LogRel2(("Clipboard: Drop event received\n"));
209 LogRel3(("Clipboard: cfFormat=%RI16, sFormat=%s, tyMed=%RU32, dwAspect=%RU32\n",
210 pThisFormat->cfFormat, VBoxClipboardWinDataObject::ClipboardFormatToString(pFormatEtc->cfFormat),
211 pThisFormat->tymed, pThisFormat->dwAspect));
212 LogRel3(("Clipboard: Got strFormat=%s, pvData=%p, cbData=%RU32\n",
213 mstrFormat.c_str(), mpvData, mcbData));
214
215 /*
216 * Initialize default values.
217 */
218 pMedium->tymed = pThisFormat->tymed;
219 pMedium->pUnkForRelease = NULL;
220
221 /*
222 * URI list handling.
223 */
224 if (mstrFormat.equalsIgnoreCase("text/uri-list"))
225 {
226 int rc = VINF_SUCCESS;
227
228 RTCList<RTCString> lstFilesURI = RTCString((char*)mpvData, mcbData).split("\r\n");
229 RTCList<RTCString> lstFiles;
230 for (size_t i = 0; i < lstFilesURI.size(); i++)
231 {
232 char *pszFilePath = RTUriFilePath(lstFilesURI.at(i).c_str());
233 if (pszFilePath)
234 {
235 lstFiles.append(pszFilePath);
236 RTStrFree(pszFilePath);
237 }
238 else /* Unable to parse -- refuse entire request. */
239 {
240 lstFiles.clear();
241 rc = VERR_INVALID_PARAMETER;
242 break;
243 }
244 }
245
246 size_t cFiles = lstFiles.size();
247 if ( RT_SUCCESS(rc)
248 && cFiles)
249 {
250#ifdef DEBUG
251 LogFlowFunc(("Files (%zu)\n", cFiles));
252 for (size_t i = 0; i < cFiles; i++)
253 LogFlowFunc(("\tFile: %s\n", lstFiles.at(i).c_str()));
254#endif
255
256#if 0
257 if ( (pFormatEtc->tymed & TYMED_ISTREAM)
258 && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
259 && (pFormatEtc->cfFormat == CF_FILECONTENTS))
260 {
261
262 }
263 else if ( (pFormatEtc->tymed & TYMED_HGLOBAL)
264 && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
265 && (pFormatEtc->cfFormat == CF_FILEDESCRIPTOR))
266 {
267
268 }
269 else if ( (pFormatEtc->tymed & TYMED_HGLOBAL)
270 && (pFormatEtc->cfFormat == CF_PREFERREDDROPEFFECT))
271 {
272 HGLOBAL hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE | GMEM_ZEROINIT, sizeof(DWORD));
273 DWORD *pdwEffect = (DWORD *)GlobalLock(hData);
274 AssertPtr(pdwEffect);
275 *pdwEffect = DROPEFFECT_COPY;
276 GlobalUnlock(hData);
277
278 pMedium->hGlobal = hData;
279 pMedium->tymed = TYMED_HGLOBAL;
280 }
281 else
282#endif
283 if ( (pFormatEtc->tymed & TYMED_HGLOBAL)
284 && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
285 && (pFormatEtc->cfFormat == CF_TEXT))
286 {
287 pMedium->hGlobal = GlobalAlloc(GHND, mcbData + 1);
288 if (pMedium->hGlobal)
289 {
290 char *pcDst = (char *)GlobalLock(pMedium->hGlobal);
291 memcpy(pcDst, mpvData, mcbData);
292 pcDst[mcbData] = '\0';
293 GlobalUnlock(pMedium->hGlobal);
294
295 hr = S_OK;
296 }
297 }
298 else if ( (pFormatEtc->tymed & TYMED_HGLOBAL)
299 && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
300 && (pFormatEtc->cfFormat == CF_HDROP))
301 {
302 size_t cchFiles = 0; /* Number of ASCII characters. */
303 for (size_t i = 0; i < cFiles; i++)
304 {
305 cchFiles += strlen(lstFiles.at(i).c_str());
306 cchFiles += 1; /* Terminating '\0'. */
307 }
308
309 size_t cbBuf = sizeof(DROPFILES) + ((cchFiles + 1) * sizeof(RTUTF16));
310 DROPFILES *pBuf = (DROPFILES *)RTMemAllocZ(cbBuf);
311 if (pBuf)
312 {
313 pBuf->pFiles = sizeof(DROPFILES);
314 pBuf->fWide = 1; /* We use unicode. Always. */
315
316 uint8_t *pCurFile = (uint8_t *)pBuf + pBuf->pFiles;
317 AssertPtr(pCurFile);
318
319 for (size_t i = 0; i < cFiles && RT_SUCCESS(rc); i++)
320 {
321 size_t cchCurFile;
322 PRTUTF16 pwszFile;
323 rc = RTStrToUtf16(lstFiles.at(i).c_str(), &pwszFile);
324 if (RT_SUCCESS(rc))
325 {
326 cchCurFile = RTUtf16Len(pwszFile);
327 Assert(cchCurFile);
328 memcpy(pCurFile, pwszFile, cchCurFile * sizeof(RTUTF16));
329 RTUtf16Free(pwszFile);
330 }
331 else
332 break;
333
334 pCurFile += cchCurFile * sizeof(RTUTF16);
335
336 /* Terminate current file name. */
337 *pCurFile = L'\0';
338 pCurFile += sizeof(RTUTF16);
339 }
340
341 if (RT_SUCCESS(rc))
342 {
343 *pCurFile = L'\0'; /* Final list terminator. */
344
345 pMedium->tymed = TYMED_HGLOBAL;
346 pMedium->pUnkForRelease = NULL;
347 pMedium->hGlobal = GlobalAlloc( GMEM_ZEROINIT
348 | GMEM_MOVEABLE
349 | GMEM_DDESHARE, cbBuf);
350 if (pMedium->hGlobal)
351 {
352 LPVOID pMem = GlobalLock(pMedium->hGlobal);
353 if (pMem)
354 {
355 memcpy(pMem, pBuf, cbBuf);
356 GlobalUnlock(pMedium->hGlobal);
357
358 hr = S_OK;
359 }
360 }
361 }
362
363 RTMemFree(pBuf);
364 }
365 else
366 rc = VERR_NO_MEMORY;
367 }
368 }
369
370 if (RT_FAILURE(rc))
371 hr = DV_E_FORMATETC;
372 }
373 /*
374 * Plain text handling.
375 */
376 else if ( mstrFormat.equalsIgnoreCase("text/plain")
377 || mstrFormat.equalsIgnoreCase("text/html")
378 || mstrFormat.equalsIgnoreCase("text/plain;charset=utf-8")
379 || mstrFormat.equalsIgnoreCase("text/plain;charset=utf-16")
380 || mstrFormat.equalsIgnoreCase("text/richtext")
381 || mstrFormat.equalsIgnoreCase("UTF8_STRING")
382 || mstrFormat.equalsIgnoreCase("TEXT")
383 || mstrFormat.equalsIgnoreCase("STRING"))
384 {
385 pMedium->hGlobal = GlobalAlloc(GHND, mcbData + 1);
386 if (pMedium->hGlobal)
387 {
388 char *pcDst = (char *)GlobalLock(pMedium->hGlobal);
389 memcpy(pcDst, mpvData, mcbData);
390 pcDst[mcbData] = '\0';
391 GlobalUnlock(pMedium->hGlobal);
392
393 hr = S_OK;
394 }
395 }
396 else
397 LogRel(("Clipboard: Error: Format '%s' not implemented\n", mstrFormat.c_str()));
398 }
399
400 /* Error handling; at least return some basic data. */
401 if (FAILED(hr))
402 {
403 LogFlowFunc(("Copying medium ...\n"));
404 switch (pThisMedium->tymed)
405 {
406
407 case TYMED_HGLOBAL:
408 pMedium->hGlobal = (HGLOBAL)OleDuplicateData(pThisMedium->hGlobal,
409 pThisFormat->cfFormat, NULL);
410 break;
411
412 default:
413 break;
414 }
415
416 pMedium->tymed = pThisFormat->tymed;
417 pMedium->pUnkForRelease = NULL;
418 }
419
420 if (hr == DV_E_FORMATETC)
421 LogRel(("Clipboard: Error handling format '%s' (%RU32 bytes)\n", mstrFormat.c_str(), mcbData));
422
423 LogFlowFunc(("hr=%Rhrc\n", hr));
424 return hr;
425}
426
427/**
428 * Only required for IStream / IStorage interfaces.
429 *
430 * @return IPRT status code.
431 * @return HRESULT
432 * @param pFormatEtc
433 * @param pMedium
434 */
435STDMETHODIMP VBoxClipboardWinDataObject::GetDataHere(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium)
436{
437 RT_NOREF(pFormatEtc, pMedium);
438 LogFlowFunc(("\n"));
439 return DATA_E_FORMATETC;
440}
441
442/**
443 * Query if this objects supports a specific format.
444 *
445 * @return IPRT status code.
446 * @return HRESULT
447 * @param pFormatEtc
448 */
449STDMETHODIMP VBoxClipboardWinDataObject::QueryGetData(LPFORMATETC pFormatEtc)
450{
451 LogFlowFunc(("\n"));
452 return (LookupFormatEtc(pFormatEtc, NULL /* puIndex */)) ? S_OK : DV_E_FORMATETC;
453}
454
455STDMETHODIMP VBoxClipboardWinDataObject::GetCanonicalFormatEtc(LPFORMATETC pFormatEtc, LPFORMATETC pFormatEtcOut)
456{
457 RT_NOREF(pFormatEtc);
458 LogFlowFunc(("\n"));
459
460 /* Set this to NULL in any case. */
461 pFormatEtcOut->ptd = NULL;
462 return E_NOTIMPL;
463}
464
465STDMETHODIMP VBoxClipboardWinDataObject::SetData(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium, BOOL fRelease)
466{
467 RT_NOREF(pFormatEtc, pMedium, fRelease);
468 return E_NOTIMPL;
469}
470
471STDMETHODIMP VBoxClipboardWinDataObject::EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppEnumFormatEtc)
472{
473 LogFlowFunc(("dwDirection=%RI32, mcFormats=%RI32, mpFormatEtc=%p\n", dwDirection, mcFormats, mpFormatEtc));
474
475 HRESULT hr;
476 if (dwDirection == DATADIR_GET)
477 hr = VBoxClipboardWinEnumFormatEtc::CreateEnumFormatEtc(mcFormats, mpFormatEtc, ppEnumFormatEtc);
478 else
479 hr = E_NOTIMPL;
480
481 LogFlowFunc(("hr=%Rhrc\n", hr));
482 return hr;
483}
484
485STDMETHODIMP VBoxClipboardWinDataObject::DAdvise(LPFORMATETC pFormatEtc, DWORD fAdvise, IAdviseSink *pAdvSink, DWORD *pdwConnection)
486{
487 RT_NOREF(pFormatEtc, fAdvise, pAdvSink, pdwConnection);
488 return OLE_E_ADVISENOTSUPPORTED;
489}
490
491STDMETHODIMP VBoxClipboardWinDataObject::DUnadvise(DWORD dwConnection)
492{
493 RT_NOREF(dwConnection);
494 return OLE_E_ADVISENOTSUPPORTED;
495}
496
497STDMETHODIMP VBoxClipboardWinDataObject::EnumDAdvise(IEnumSTATDATA **ppEnumAdvise)
498{
499 RT_NOREF(ppEnumAdvise);
500 return OLE_E_ADVISENOTSUPPORTED;
501}
502
503/*
504 * Own stuff.
505 */
506
507int VBoxClipboardWinDataObject::Abort(void)
508{
509 LogFlowFunc(("Aborting ...\n"));
510 mStatus = Aborted;
511 return RTSemEventSignal(mEventDropped);
512}
513
514/* static */
515const char* VBoxClipboardWinDataObject::ClipboardFormatToString(CLIPFORMAT fmt)
516{
517#if 0
518 char szFormat[128];
519 if (GetClipboardFormatName(fmt, szFormat, sizeof(szFormat)))
520 LogFlowFunc(("wFormat=%RI16, szName=%s\n", fmt, szFormat));
521#endif
522
523 switch (fmt)
524 {
525
526 case 1:
527 return "CF_TEXT";
528 case 2:
529 return "CF_BITMAP";
530 case 3:
531 return "CF_METAFILEPICT";
532 case 4:
533 return "CF_SYLK";
534 case 5:
535 return "CF_DIF";
536 case 6:
537 return "CF_TIFF";
538 case 7:
539 return "CF_OEMTEXT";
540 case 8:
541 return "CF_DIB";
542 case 9:
543 return "CF_PALETTE";
544 case 10:
545 return "CF_PENDATA";
546 case 11:
547 return "CF_RIFF";
548 case 12:
549 return "CF_WAVE";
550 case 13:
551 return "CF_UNICODETEXT";
552 case 14:
553 return "CF_ENHMETAFILE";
554 case 15:
555 return "CF_HDROP";
556 case 16:
557 return "CF_LOCALE";
558 case 17:
559 return "CF_DIBV5";
560 case 18:
561 return "CF_MAX";
562 case 49158:
563 return "FileName";
564 case 49159:
565 return "FileNameW";
566 case 49161:
567 return "DATAOBJECT";
568 case 49171:
569 return "Ole Private Data";
570 case 49314:
571 return "Shell Object Offsets";
572 case 49316:
573 return "File Contents";
574 case 49317:
575 return "File Group Descriptor";
576 case 49323:
577 return "Preferred Drop Effect";
578 case 49380:
579 return "Shell Object Offsets";
580 case 49382:
581 return "FileContents";
582 case 49383:
583 return "FileGroupDescriptor";
584 case 49389:
585 return "Preferred DropEffect";
586 case 49268:
587 return "Shell IDList Array";
588 case 49619:
589 return "RenPrivateFileAttachments";
590 default:
591 break;
592 }
593
594 return "unknown";
595}
596
597bool VBoxClipboardWinDataObject::LookupFormatEtc(LPFORMATETC pFormatEtc, ULONG *puIndex)
598{
599 AssertReturn(pFormatEtc, false);
600 /* puIndex is optional. */
601
602 for (ULONG i = 0; i < mcFormats; i++)
603 {
604 if( (pFormatEtc->tymed & mpFormatEtc[i].tymed)
605 && pFormatEtc->cfFormat == mpFormatEtc[i].cfFormat
606 && pFormatEtc->dwAspect == mpFormatEtc[i].dwAspect)
607 {
608 LogRel3(("Clipboard: Format found: tyMed=%RI32, cfFormat=%RI16, sFormats=%s, dwAspect=%RI32, ulIndex=%RU32\n",
609 pFormatEtc->tymed, pFormatEtc->cfFormat, VBoxClipboardWinDataObject::ClipboardFormatToString(mpFormatEtc[i].cfFormat),
610 pFormatEtc->dwAspect, i));
611 if (puIndex)
612 *puIndex = i;
613 return true;
614 }
615 }
616
617 LogRel3(("Clipboard: Format NOT found: tyMed=%RI32, cfFormat=%RI16, sFormats=%s, dwAspect=%RI32\n",
618 pFormatEtc->tymed, pFormatEtc->cfFormat, VBoxClipboardWinDataObject::ClipboardFormatToString(pFormatEtc->cfFormat),
619 pFormatEtc->dwAspect));
620
621 return false;
622}
623
624/* static */
625HGLOBAL VBoxClipboardWinDataObject::MemDup(HGLOBAL hMemSource)
626{
627 DWORD dwLen = GlobalSize(hMemSource);
628 AssertReturn(dwLen, NULL);
629 PVOID pvSource = GlobalLock(hMemSource);
630 if (pvSource)
631 {
632 PVOID pvDest = GlobalAlloc(GMEM_FIXED, dwLen);
633 if (pvDest)
634 memcpy(pvDest, pvSource, dwLen);
635
636 GlobalUnlock(hMemSource);
637 return pvDest;
638 }
639
640 return NULL;
641}
642
643void VBoxClipboardWinDataObject::RegisterFormat(LPFORMATETC pFormatEtc, CLIPFORMAT clipFormat,
644 TYMED tyMed, LONG lIndex, DWORD dwAspect,
645 DVTARGETDEVICE *pTargetDevice)
646{
647 AssertPtr(pFormatEtc);
648
649 pFormatEtc->cfFormat = clipFormat;
650 pFormatEtc->tymed = tyMed;
651 pFormatEtc->lindex = lIndex;
652 pFormatEtc->dwAspect = dwAspect;
653 pFormatEtc->ptd = pTargetDevice;
654
655 LogFlowFunc(("Registered format=%ld, sFormat=%s\n",
656 pFormatEtc->cfFormat, VBoxClipboardWinDataObject::ClipboardFormatToString(pFormatEtc->cfFormat)));
657}
658
659void VBoxClipboardWinDataObject::SetStatus(Status status)
660{
661 LogFlowFunc(("Setting status to %ld\n", status));
662 mStatus = status;
663}
664
665int VBoxClipboardWinDataObject::Signal(const RTCString &strFormat,
666 const void *pvData, uint32_t cbData)
667{
668 int rc;
669
670 if (cbData)
671 {
672 mpvData = RTMemAlloc(cbData);
673 if (mpvData)
674 {
675 memcpy(mpvData, pvData, cbData);
676 mcbData = cbData;
677 rc = VINF_SUCCESS;
678 }
679 else
680 rc = VERR_NO_MEMORY;
681 }
682 else
683 rc = VINF_SUCCESS;
684
685 if (RT_SUCCESS(rc))
686 {
687 mStatus = Dropped;
688 mstrFormat = strFormat;
689 }
690 else
691 {
692 mStatus = Aborted;
693 }
694
695 /* Signal in any case. */
696 LogRel2(("Clipboard: Signalling drop event\n"));
697
698 int rc2 = RTSemEventSignal(mEventDropped);
699 if (RT_SUCCESS(rc))
700 rc = rc2;
701
702 LogFunc(("mStatus=%RU32, rc=%Rrc\n", mStatus, rc));
703 return rc;
704}
705
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