VirtualBox

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

Last change on this file since 95960 was 95960, checked in by vboxsync, 22 months ago

Additions/VBoxTray: More logging cleanups: don't define default stuff which is already defined by default; include files reordering (IPRT/ first, VBox/ second).

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

© 2023 Oracle
ContactPrivacy policyTerms of Use