VirtualBox

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

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

DnD: Added VBGLR3DNDEVENTTYPE to abstract the DnD protocol from the actual DnD events more; that way the client don't need to know exactly how the actual protocol works, but only react on events they care for.

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