VirtualBox

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

Last change on this file since 78416 was 76553, checked in by vboxsync, 6 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.9 KB
Line 
1/* $Id: VBoxDnDDataObject.cpp 76553 2019-01-01 01:45:53Z vboxsync $ */
2/** @file
3 * VBoxDnDDataObject.cpp - IDataObject implementation.
4 */
5
6/*
7 * Copyright (C) 2013-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#define LOG_GROUP LOG_GROUP_GUEST_DND
20#include <iprt/win/windows.h>
21#include <new> /* For bad_alloc. */
22#include <iprt/win/shlobj.h>
23
24#include <iprt/path.h>
25#include <iprt/semaphore.h>
26#include <iprt/uri.h>
27#include <iprt/utf16.h>
28
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(&mEventDropped);
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 LogRel2(("DnD: Waiting for drop event ...\n"));
209 int rc2 = RTSemEventWait(mEventDropped, RT_INDEFINITE_WAIT);
210 LogFlowFunc(("rc2=%Rrc, mStatus=%ld\n", rc2, mStatus)); RT_NOREF(rc2);
211 }
212
213 if (mStatus == Dropped)
214 {
215 LogRel2(("DnD: Drop event received\n"));
216 LogRel3(("DnD: cfFormat=%RI16, sFormat=%s, tyMed=%RU32, dwAspect=%RU32\n",
217 pThisFormat->cfFormat, VBoxDnDDataObject::ClipboardFormatToString(pFormatEtc->cfFormat),
218 pThisFormat->tymed, pThisFormat->dwAspect));
219 LogRel3(("DnD: Got strFormat=%s, pvData=%p, cbData=%RU32\n",
220 mstrFormat.c_str(), mpvData, mcbData));
221
222 /*
223 * Initialize default values.
224 */
225 pMedium->tymed = pThisFormat->tymed;
226 pMedium->pUnkForRelease = NULL;
227
228 /*
229 * URI list handling.
230 */
231 if (mstrFormat.equalsIgnoreCase("text/uri-list"))
232 {
233 int rc = VINF_SUCCESS;
234
235 RTCList<RTCString> lstFilesURI = RTCString((char*)mpvData, mcbData).split("\r\n");
236 RTCList<RTCString> lstFiles;
237 for (size_t i = 0; i < lstFilesURI.size(); i++)
238 {
239 char *pszFilePath = RTUriFilePath(lstFilesURI.at(i).c_str());
240 if (pszFilePath)
241 {
242 lstFiles.append(pszFilePath);
243 RTStrFree(pszFilePath);
244 }
245 else /* Unable to parse -- refuse entire request. */
246 {
247 lstFiles.clear();
248 rc = VERR_INVALID_PARAMETER;
249 break;
250 }
251 }
252
253 size_t cFiles = lstFiles.size();
254 if ( RT_SUCCESS(rc)
255 && cFiles)
256 {
257#ifdef DEBUG
258 LogFlowFunc(("Files (%zu)\n", cFiles));
259 for (size_t i = 0; i < cFiles; i++)
260 LogFlowFunc(("\tFile: %s\n", lstFiles.at(i).c_str()));
261#endif
262
263#if 0
264 if ( (pFormatEtc->tymed & TYMED_ISTREAM)
265 && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
266 && (pFormatEtc->cfFormat == CF_FILECONTENTS))
267 {
268
269 }
270 else if ( (pFormatEtc->tymed & TYMED_HGLOBAL)
271 && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
272 && (pFormatEtc->cfFormat == CF_FILEDESCRIPTOR))
273 {
274
275 }
276 else if ( (pFormatEtc->tymed & TYMED_HGLOBAL)
277 && (pFormatEtc->cfFormat == CF_PREFERREDDROPEFFECT))
278 {
279 HGLOBAL hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE | GMEM_ZEROINIT, sizeof(DWORD));
280 DWORD *pdwEffect = (DWORD *)GlobalLock(hData);
281 AssertPtr(pdwEffect);
282 *pdwEffect = DROPEFFECT_COPY;
283 GlobalUnlock(hData);
284
285 pMedium->hGlobal = hData;
286 pMedium->tymed = TYMED_HGLOBAL;
287 }
288 else
289#endif
290 if ( (pFormatEtc->tymed & TYMED_HGLOBAL)
291 && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
292 && (pFormatEtc->cfFormat == CF_TEXT))
293 {
294 pMedium->hGlobal = GlobalAlloc(GHND, mcbData + 1);
295 if (pMedium->hGlobal)
296 {
297 char *pcDst = (char *)GlobalLock(pMedium->hGlobal);
298 memcpy(pcDst, mpvData, mcbData);
299 pcDst[mcbData] = '\0';
300 GlobalUnlock(pMedium->hGlobal);
301
302 hr = S_OK;
303 }
304 }
305 else if ( (pFormatEtc->tymed & TYMED_HGLOBAL)
306 && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
307 && (pFormatEtc->cfFormat == CF_HDROP))
308 {
309 size_t cchFiles = 0; /* Number of ASCII characters. */
310 for (size_t i = 0; i < cFiles; i++)
311 {
312 cchFiles += strlen(lstFiles.at(i).c_str());
313 cchFiles += 1; /* Terminating '\0'. */
314 }
315
316 size_t cbBuf = sizeof(DROPFILES) + ((cchFiles + 1) * sizeof(RTUTF16));
317 DROPFILES *pBuf = (DROPFILES *)RTMemAllocZ(cbBuf);
318 if (pBuf)
319 {
320 pBuf->pFiles = sizeof(DROPFILES);
321 pBuf->fWide = 1; /* We use unicode. Always. */
322
323 uint8_t *pCurFile = (uint8_t *)pBuf + pBuf->pFiles;
324 AssertPtr(pCurFile);
325
326 for (size_t i = 0; i < cFiles && RT_SUCCESS(rc); i++)
327 {
328 size_t cchCurFile;
329 PRTUTF16 pwszFile;
330 rc = RTStrToUtf16(lstFiles.at(i).c_str(), &pwszFile);
331 if (RT_SUCCESS(rc))
332 {
333 cchCurFile = RTUtf16Len(pwszFile);
334 Assert(cchCurFile);
335 memcpy(pCurFile, pwszFile, cchCurFile * sizeof(RTUTF16));
336 RTUtf16Free(pwszFile);
337 }
338 else
339 break;
340
341 pCurFile += cchCurFile * sizeof(RTUTF16);
342
343 /* Terminate current file name. */
344 *pCurFile = L'\0';
345 pCurFile += sizeof(RTUTF16);
346 }
347
348 if (RT_SUCCESS(rc))
349 {
350 *pCurFile = L'\0'; /* Final list terminator. */
351
352 pMedium->tymed = TYMED_HGLOBAL;
353 pMedium->pUnkForRelease = NULL;
354 pMedium->hGlobal = GlobalAlloc( GMEM_ZEROINIT
355 | GMEM_MOVEABLE
356 | GMEM_DDESHARE, cbBuf);
357 if (pMedium->hGlobal)
358 {
359 LPVOID pMem = GlobalLock(pMedium->hGlobal);
360 if (pMem)
361 {
362 memcpy(pMem, pBuf, cbBuf);
363 GlobalUnlock(pMedium->hGlobal);
364
365 hr = S_OK;
366 }
367 }
368 }
369
370 RTMemFree(pBuf);
371 }
372 else
373 rc = VERR_NO_MEMORY;
374 }
375 }
376
377 if (RT_FAILURE(rc))
378 hr = DV_E_FORMATETC;
379 }
380 /*
381 * Plain text handling.
382 */
383 else if ( mstrFormat.equalsIgnoreCase("text/plain")
384 || mstrFormat.equalsIgnoreCase("text/html")
385 || mstrFormat.equalsIgnoreCase("text/plain;charset=utf-8")
386 || mstrFormat.equalsIgnoreCase("text/plain;charset=utf-16")
387 || mstrFormat.equalsIgnoreCase("text/richtext")
388 || mstrFormat.equalsIgnoreCase("UTF8_STRING")
389 || mstrFormat.equalsIgnoreCase("TEXT")
390 || mstrFormat.equalsIgnoreCase("STRING"))
391 {
392 pMedium->hGlobal = GlobalAlloc(GHND, mcbData + 1);
393 if (pMedium->hGlobal)
394 {
395 char *pcDst = (char *)GlobalLock(pMedium->hGlobal);
396 memcpy(pcDst, mpvData, mcbData);
397 pcDst[mcbData] = '\0';
398 GlobalUnlock(pMedium->hGlobal);
399
400 hr = S_OK;
401 }
402 }
403 else
404 LogRel(("DnD: Error: Format '%s' not implemented\n", mstrFormat.c_str()));
405 }
406
407 /* Error handling; at least return some basic data. */
408 if (FAILED(hr))
409 {
410 LogFlowFunc(("Copying medium ...\n"));
411 switch (pThisMedium->tymed)
412 {
413
414 case TYMED_HGLOBAL:
415 pMedium->hGlobal = (HGLOBAL)OleDuplicateData(pThisMedium->hGlobal,
416 pThisFormat->cfFormat, NULL);
417 break;
418
419 default:
420 break;
421 }
422
423 pMedium->tymed = pThisFormat->tymed;
424 pMedium->pUnkForRelease = NULL;
425 }
426
427 if (hr == DV_E_FORMATETC)
428 LogRel(("DnD: Error handling format '%s' (%RU32 bytes)\n", mstrFormat.c_str(), mcbData));
429
430 LogFlowFunc(("hr=%Rhrc\n", hr));
431 return hr;
432}
433
434/**
435 * Only required for IStream / IStorage interfaces.
436 *
437 * @return IPRT status code.
438 * @return HRESULT
439 * @param pFormatEtc
440 * @param pMedium
441 */
442STDMETHODIMP VBoxDnDDataObject::GetDataHere(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium)
443{
444 RT_NOREF(pFormatEtc, pMedium);
445 LogFlowFunc(("\n"));
446 return DATA_E_FORMATETC;
447}
448
449/**
450 * Query if this objects supports a specific format.
451 *
452 * @return IPRT status code.
453 * @return HRESULT
454 * @param pFormatEtc
455 */
456STDMETHODIMP VBoxDnDDataObject::QueryGetData(LPFORMATETC pFormatEtc)
457{
458 LogFlowFunc(("\n"));
459 return (LookupFormatEtc(pFormatEtc, NULL /* puIndex */)) ? S_OK : DV_E_FORMATETC;
460}
461
462STDMETHODIMP VBoxDnDDataObject::GetCanonicalFormatEtc(LPFORMATETC pFormatEtc, LPFORMATETC pFormatEtcOut)
463{
464 RT_NOREF(pFormatEtc);
465 LogFlowFunc(("\n"));
466
467 /* Set this to NULL in any case. */
468 pFormatEtcOut->ptd = NULL;
469 return E_NOTIMPL;
470}
471
472STDMETHODIMP VBoxDnDDataObject::SetData(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium, BOOL fRelease)
473{
474 RT_NOREF(pFormatEtc, pMedium, fRelease);
475 return E_NOTIMPL;
476}
477
478STDMETHODIMP VBoxDnDDataObject::EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppEnumFormatEtc)
479{
480 LogFlowFunc(("dwDirection=%RI32, mcFormats=%RI32, mpFormatEtc=%p\n", dwDirection, mcFormats, mpFormatEtc));
481
482 HRESULT hr;
483 if (dwDirection == DATADIR_GET)
484 hr = VBoxDnDEnumFormatEtc::CreateEnumFormatEtc(mcFormats, mpFormatEtc, ppEnumFormatEtc);
485 else
486 hr = E_NOTIMPL;
487
488 LogFlowFunc(("hr=%Rhrc\n", hr));
489 return hr;
490}
491
492STDMETHODIMP VBoxDnDDataObject::DAdvise(LPFORMATETC pFormatEtc, DWORD fAdvise, IAdviseSink *pAdvSink, DWORD *pdwConnection)
493{
494 RT_NOREF(pFormatEtc, fAdvise, pAdvSink, pdwConnection);
495 return OLE_E_ADVISENOTSUPPORTED;
496}
497
498STDMETHODIMP VBoxDnDDataObject::DUnadvise(DWORD dwConnection)
499{
500 RT_NOREF(dwConnection);
501 return OLE_E_ADVISENOTSUPPORTED;
502}
503
504STDMETHODIMP VBoxDnDDataObject::EnumDAdvise(IEnumSTATDATA **ppEnumAdvise)
505{
506 RT_NOREF(ppEnumAdvise);
507 return OLE_E_ADVISENOTSUPPORTED;
508}
509
510/*
511 * Own stuff.
512 */
513
514int VBoxDnDDataObject::Abort(void)
515{
516 LogFlowFunc(("Aborting ...\n"));
517 mStatus = Aborted;
518 return RTSemEventSignal(mEventDropped);
519}
520
521/* static */
522const char* VBoxDnDDataObject::ClipboardFormatToString(CLIPFORMAT fmt)
523{
524#if 0
525 char szFormat[128];
526 if (GetClipboardFormatName(fmt, szFormat, sizeof(szFormat)))
527 LogFlowFunc(("wFormat=%RI16, szName=%s\n", fmt, szFormat));
528#endif
529
530 switch (fmt)
531 {
532
533 case 1:
534 return "CF_TEXT";
535 case 2:
536 return "CF_BITMAP";
537 case 3:
538 return "CF_METAFILEPICT";
539 case 4:
540 return "CF_SYLK";
541 case 5:
542 return "CF_DIF";
543 case 6:
544 return "CF_TIFF";
545 case 7:
546 return "CF_OEMTEXT";
547 case 8:
548 return "CF_DIB";
549 case 9:
550 return "CF_PALETTE";
551 case 10:
552 return "CF_PENDATA";
553 case 11:
554 return "CF_RIFF";
555 case 12:
556 return "CF_WAVE";
557 case 13:
558 return "CF_UNICODETEXT";
559 case 14:
560 return "CF_ENHMETAFILE";
561 case 15:
562 return "CF_HDROP";
563 case 16:
564 return "CF_LOCALE";
565 case 17:
566 return "CF_DIBV5";
567 case 18:
568 return "CF_MAX";
569 case 49158:
570 return "FileName";
571 case 49159:
572 return "FileNameW";
573 case 49161:
574 return "DATAOBJECT";
575 case 49171:
576 return "Ole Private Data";
577 case 49314:
578 return "Shell Object Offsets";
579 case 49316:
580 return "File Contents";
581 case 49317:
582 return "File Group Descriptor";
583 case 49323:
584 return "Preferred Drop Effect";
585 case 49380:
586 return "Shell Object Offsets";
587 case 49382:
588 return "FileContents";
589 case 49383:
590 return "FileGroupDescriptor";
591 case 49389:
592 return "Preferred DropEffect";
593 case 49268:
594 return "Shell IDList Array";
595 case 49619:
596 return "RenPrivateFileAttachments";
597 default:
598 break;
599 }
600
601 return "unknown";
602}
603
604bool VBoxDnDDataObject::LookupFormatEtc(LPFORMATETC pFormatEtc, ULONG *puIndex)
605{
606 AssertReturn(pFormatEtc, false);
607 /* puIndex is optional. */
608
609 for (ULONG i = 0; i < mcFormats; i++)
610 {
611 if( (pFormatEtc->tymed & mpFormatEtc[i].tymed)
612 && pFormatEtc->cfFormat == mpFormatEtc[i].cfFormat
613 && pFormatEtc->dwAspect == mpFormatEtc[i].dwAspect)
614 {
615 LogRel3(("DnD: Format found: tyMed=%RI32, cfFormat=%RI16, sFormats=%s, dwAspect=%RI32, ulIndex=%RU32\n",
616 pFormatEtc->tymed, pFormatEtc->cfFormat, VBoxDnDDataObject::ClipboardFormatToString(mpFormatEtc[i].cfFormat),
617 pFormatEtc->dwAspect, i));
618 if (puIndex)
619 *puIndex = i;
620 return true;
621 }
622 }
623
624 LogRel3(("DnD: Format NOT found: tyMed=%RI32, cfFormat=%RI16, sFormats=%s, dwAspect=%RI32\n",
625 pFormatEtc->tymed, pFormatEtc->cfFormat, VBoxDnDDataObject::ClipboardFormatToString(pFormatEtc->cfFormat),
626 pFormatEtc->dwAspect));
627
628 return false;
629}
630
631/* static */
632HGLOBAL VBoxDnDDataObject::MemDup(HGLOBAL hMemSource)
633{
634 DWORD dwLen = GlobalSize(hMemSource);
635 AssertReturn(dwLen, NULL);
636 PVOID pvSource = GlobalLock(hMemSource);
637 if (pvSource)
638 {
639 PVOID pvDest = GlobalAlloc(GMEM_FIXED, dwLen);
640 if (pvDest)
641 memcpy(pvDest, pvSource, dwLen);
642
643 GlobalUnlock(hMemSource);
644 return pvDest;
645 }
646
647 return NULL;
648}
649
650void VBoxDnDDataObject::RegisterFormat(LPFORMATETC pFormatEtc, CLIPFORMAT clipFormat,
651 TYMED tyMed, LONG lIndex, DWORD dwAspect,
652 DVTARGETDEVICE *pTargetDevice)
653{
654 AssertPtr(pFormatEtc);
655
656 pFormatEtc->cfFormat = clipFormat;
657 pFormatEtc->tymed = tyMed;
658 pFormatEtc->lindex = lIndex;
659 pFormatEtc->dwAspect = dwAspect;
660 pFormatEtc->ptd = pTargetDevice;
661
662 LogFlowFunc(("Registered format=%ld, sFormat=%s\n",
663 pFormatEtc->cfFormat, VBoxDnDDataObject::ClipboardFormatToString(pFormatEtc->cfFormat)));
664}
665
666void VBoxDnDDataObject::SetStatus(Status status)
667{
668 LogFlowFunc(("Setting status to %ld\n", status));
669 mStatus = status;
670}
671
672int VBoxDnDDataObject::Signal(const RTCString &strFormat,
673 const void *pvData, uint32_t cbData)
674{
675 int rc;
676
677 if (cbData)
678 {
679 mpvData = RTMemAlloc(cbData);
680 if (mpvData)
681 {
682 memcpy(mpvData, pvData, cbData);
683 mcbData = cbData;
684 rc = VINF_SUCCESS;
685 }
686 else
687 rc = VERR_NO_MEMORY;
688 }
689 else
690 rc = VINF_SUCCESS;
691
692 if (RT_SUCCESS(rc))
693 {
694 mStatus = Dropped;
695 mstrFormat = strFormat;
696 }
697 else
698 {
699 mStatus = Aborted;
700 }
701
702 /* Signal in any case. */
703 LogRel2(("DnD: Signalling drop event\n"));
704
705 int rc2 = RTSemEventSignal(mEventDropped);
706 if (RT_SUCCESS(rc))
707 rc = rc2;
708
709 LogFunc(("mStatus=%RU32, rc=%Rrc\n", mStatus, rc));
710 return rc;
711}
712
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