VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnDDataObject.cpp@ 63566

Last change on this file since 63566 was 63311, checked in by vboxsync, 8 years ago

Use shlobj.h wrapper.

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