VirtualBox

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

Last change on this file since 69500 was 69500, checked in by vboxsync, 7 years ago

*: scm --update-copyright-year

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