VirtualBox

source: vbox/trunk/src/VBox/Main/include/GuestDnDPrivate.h@ 94521

Last change on this file since 94521 was 93115, checked in by vboxsync, 2 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 28.7 KB
Line 
1/* $Id: GuestDnDPrivate.h 93115 2022-01-01 11:31:46Z vboxsync $ */
2/** @file
3 * Private guest drag and drop code, used by GuestDnDTarget +
4 * GuestDnDSource.
5 */
6
7/*
8 * Copyright (C) 2011-2022 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19#ifndef MAIN_INCLUDED_GuestDnDPrivate_h
20#define MAIN_INCLUDED_GuestDnDPrivate_h
21#ifndef RT_WITHOUT_PRAGMA_ONCE
22# pragma once
23#endif
24
25#include <iprt/dir.h>
26#include <iprt/file.h>
27#include <iprt/path.h>
28
29#include <VBox/hgcmsvc.h> /* For PVBOXHGCMSVCPARM. */
30#include <VBox/GuestHost/DragAndDrop.h>
31#include <VBox/GuestHost/DragAndDropDefs.h>
32#include <VBox/HostServices/DragAndDropSvc.h>
33
34/**
35 * Forward prototype declarations.
36 */
37class Guest;
38class GuestDnDBase;
39class GuestDnDState;
40class GuestDnDSource;
41class GuestDnDTarget;
42class Progress;
43
44/**
45 * Type definitions.
46 */
47
48/** List (vector) of MIME types. */
49typedef std::vector<com::Utf8Str> GuestDnDMIMEList;
50
51/**
52 * Class to handle a guest DnD callback event.
53 */
54class GuestDnDCallbackEvent
55{
56public:
57
58 GuestDnDCallbackEvent(void)
59 : m_SemEvent(NIL_RTSEMEVENT)
60 , m_Rc(VINF_SUCCESS) { }
61
62 virtual ~GuestDnDCallbackEvent(void);
63
64public:
65
66 int Reset(void);
67
68 int Notify(int rc = VINF_SUCCESS);
69
70 int Result(void) const { return m_Rc; }
71
72 int Wait(RTMSINTERVAL msTimeout);
73
74protected:
75
76 /** Event semaphore to notify on error/completion. */
77 RTSEMEVENT m_SemEvent;
78 /** Callback result. */
79 int m_Rc;
80};
81
82/**
83 * Struct for handling the (raw) meta data.
84 */
85struct GuestDnDMetaData
86{
87 GuestDnDMetaData(void)
88 : pvData(NULL)
89 , cbData(0)
90 , cbAllocated(0)
91 , cbAnnounced(0) { }
92
93 virtual ~GuestDnDMetaData(void)
94 {
95 reset();
96 }
97
98 /**
99 * Adds new meta data.
100 *
101 * @returns New (total) meta data size in bytes.
102 * @param pvDataAdd Pointer of data to add.
103 * @param cbDataAdd Size (in bytes) of data to add.
104 */
105 size_t add(const void *pvDataAdd, size_t cbDataAdd)
106 {
107 LogFlowThisFunc(("cbAllocated=%zu, cbAnnounced=%zu, pvDataAdd=%p, cbDataAdd=%zu\n",
108 cbAllocated, cbAnnounced, pvDataAdd, cbDataAdd));
109 if (!cbDataAdd)
110 return 0;
111 AssertPtrReturn(pvDataAdd, 0);
112
113 const size_t cbAllocatedTmp = cbData + cbDataAdd;
114 if (cbAllocatedTmp > cbAllocated)
115 {
116 int rc = resize(cbAllocatedTmp);
117 if (RT_FAILURE(rc))
118 return 0;
119 }
120
121 Assert(cbAllocated >= cbData + cbDataAdd);
122 memcpy((uint8_t *)pvData + cbData, pvDataAdd, cbDataAdd);
123
124 cbData += cbDataAdd;
125 cbAnnounced = cbData;
126
127 return cbData;
128 }
129
130 /**
131 * Adds new meta data.
132 *
133 * @returns New (total) meta data size in bytes.
134 * @param vecAdd Meta data to add.
135 */
136 size_t add(const std::vector<BYTE> &vecAdd)
137 {
138 if (!vecAdd.size())
139 return 0;
140
141 if (vecAdd.size() > UINT32_MAX) /* Paranoia. */
142 return 0;
143
144 return add(&vecAdd.front(), (uint32_t)vecAdd.size());
145 }
146
147 /**
148 * Resets (clears) all data.
149 */
150 void reset(void)
151 {
152 strFmt = "";
153
154 if (pvData)
155 {
156 Assert(cbAllocated);
157 RTMemFree(pvData);
158 pvData = NULL;
159 }
160
161 cbData = 0;
162 cbAllocated = 0;
163 cbAnnounced = 0;
164 }
165
166 /**
167 * Resizes the allocation size.
168 *
169 * @returns VBox status code.
170 * @param cbSize New allocation size (in bytes).
171 */
172 int resize(size_t cbSize)
173 {
174 if (!cbSize)
175 {
176 reset();
177 return VINF_SUCCESS;
178 }
179
180 if (cbSize == cbAllocated)
181 return VINF_SUCCESS;
182
183 cbSize = RT_ALIGN_Z(cbSize, PAGE_SIZE);
184
185 if (cbSize > _32M) /* Meta data can be up to 32MB. */
186 return VERR_BUFFER_OVERFLOW;
187
188 void *pvTmp = NULL;
189 if (!cbAllocated)
190 {
191 Assert(cbData == 0);
192 pvTmp = RTMemAllocZ(cbSize);
193 }
194 else
195 {
196 AssertPtr(pvData);
197 pvTmp = RTMemRealloc(pvData, cbSize);
198 }
199
200 if (pvTmp)
201 {
202 pvData = pvTmp;
203 cbAllocated = cbSize;
204 return VINF_SUCCESS;
205 }
206
207 return VERR_NO_MEMORY;
208 }
209
210 /** Format string of this meta data. */
211 com::Utf8Str strFmt;
212 /** Pointer to allocated meta data. */
213 void *pvData;
214 /** Used bytes of meta data. Must not exceed cbAllocated. */
215 size_t cbData;
216 /** Size (in bytes) of allocated meta data. */
217 size_t cbAllocated;
218 /** Size (in bytes) of announced meta data. */
219 size_t cbAnnounced;
220};
221
222/**
223 * Struct for accounting shared DnD data to be sent/received.
224 */
225struct GuestDnDData
226{
227 GuestDnDData(void)
228 : cbExtra(0)
229 , cbProcessed(0) { }
230
231 virtual ~GuestDnDData(void)
232 {
233 reset();
234 }
235
236 /**
237 * Adds processed data to the internal accounting.
238 *
239 * @returns New processed data size.
240 * @param cbDataAdd Bytes to add as done processing.
241 */
242 size_t addProcessed(size_t cbDataAdd)
243 {
244 const size_t cbTotal = getTotalAnnounced(); RT_NOREF(cbTotal);
245 AssertReturn(cbProcessed + cbDataAdd <= cbTotal, 0);
246 cbProcessed += cbDataAdd;
247 return cbProcessed;
248 }
249
250 /**
251 * Returns whether all data has been processed or not.
252 *
253 * @returns \c true if all data has been processed, \c false if not.
254 */
255 bool isComplete(void) const
256 {
257 const size_t cbTotal = getTotalAnnounced();
258 LogFlowFunc(("cbProcessed=%zu, cbTotal=%zu\n", cbProcessed, cbTotal));
259 AssertReturn(cbProcessed <= cbTotal, true);
260 return (cbProcessed == cbTotal);
261 }
262
263 /**
264 * Returns the percentage (0-100) of the already processed data.
265 *
266 * @returns Percentage (0-100) of the already processed data.
267 */
268 uint8_t getPercentComplete(void) const
269 {
270 const size_t cbTotal = getTotalAnnounced();
271 return (uint8_t)(cbProcessed * 100 / RT_MAX(cbTotal, 1));
272 }
273
274 /**
275 * Returns the remaining (outstanding) data left for processing.
276 *
277 * @returns Remaining (outstanding) data (in bytes) left for processing.
278 */
279 size_t getRemaining(void) const
280 {
281 const size_t cbTotal = getTotalAnnounced();
282 AssertReturn(cbProcessed <= cbTotal, 0);
283 return cbTotal - cbProcessed;
284 }
285
286 /**
287 * Returns the total data size (in bytes) announced.
288 *
289 * @returns Total data size (in bytes) announced.
290 */
291 size_t getTotalAnnounced(void) const
292 {
293 return Meta.cbAnnounced + cbExtra;
294 }
295
296 /**
297 * Returns the total data size (in bytes) available.
298 * For receiving data, this represents the already received data.
299 * For sending data, this represents the data left to send.
300 *
301 * @returns Total data size (in bytes) available.
302 */
303 size_t getTotalAvailable(void) const
304 {
305 return Meta.cbData + cbExtra;
306 }
307
308 /**
309 * Resets all data.
310 */
311 void reset(void)
312 {
313 Meta.reset();
314
315 cbExtra = 0;
316 cbProcessed = 0;
317 }
318
319 /** For storing the actual meta data.
320 * This might be an URI list or just plain raw data,
321 * according to the format being sent. */
322 GuestDnDMetaData Meta;
323 /** Extra data to send/receive (in bytes). Can be 0 for raw data.
324 * For (file) transfers this is the total size for all files. */
325 size_t cbExtra;
326 /** Overall size (in bytes) of processed data. */
327 size_t cbProcessed;
328};
329
330/** Initial object context state / no state set. */
331#define DND_OBJ_STATE_NONE 0
332/** The header was received / sent. */
333#define DND_OBJ_STATE_HAS_HDR RT_BIT(0)
334/** Validation mask for object context state. */
335#define DND_OBJ_STATE_VALID_MASK UINT32_C(0x00000001)
336
337/**
338 * Base class for keeping around DnD (file) transfer data.
339 * Used for sending / receiving transfer data.
340 */
341struct GuestDnDTransferData
342{
343
344public:
345
346 GuestDnDTransferData(void)
347 : cObjToProcess(0)
348 , cObjProcessed(0)
349 , pvScratchBuf(NULL)
350 , cbScratchBuf(0) { }
351
352 virtual ~GuestDnDTransferData(void)
353 {
354 destroy();
355 }
356
357 /**
358 * Initializes a transfer data object.
359 *
360 * @param cbBuf Scratch buffer size (in bytes) to use.
361 * If not specified, DND_DEFAULT_CHUNK_SIZE will be used.
362 */
363 int init(size_t cbBuf = DND_DEFAULT_CHUNK_SIZE)
364 {
365 reset();
366
367 pvScratchBuf = RTMemAlloc(cbBuf);
368 if (!pvScratchBuf)
369 return VERR_NO_MEMORY;
370
371 cbScratchBuf = cbBuf;
372 return VINF_SUCCESS;
373 }
374
375 /**
376 * Destroys a transfer data object.
377 */
378 void destroy(void)
379 {
380 reset();
381
382 if (pvScratchBuf)
383 {
384 Assert(cbScratchBuf);
385 RTMemFree(pvScratchBuf);
386 pvScratchBuf = NULL;
387 }
388 cbScratchBuf = 0;
389 }
390
391 /**
392 * Resets a transfer data object.
393 */
394 void reset(void)
395 {
396 LogFlowFuncEnter();
397
398 cObjToProcess = 0;
399 cObjProcessed = 0;
400 }
401
402 /**
403 * Returns whether this transfer object is complete or not.
404 *
405 * @returns \c true if complete, \c false if not.
406 */
407 bool isComplete(void) const
408 {
409 return (cObjProcessed == cObjToProcess);
410 }
411
412 /** Number of objects to process. */
413 uint64_t cObjToProcess;
414 /** Number of objects already processed. */
415 uint64_t cObjProcessed;
416 /** Pointer to an optional scratch buffer to use for
417 * doing the actual chunk transfers. */
418 void *pvScratchBuf;
419 /** Size (in bytes) of scratch buffer. */
420 size_t cbScratchBuf;
421};
422
423/**
424 * Class for keeping around DnD transfer send data (Host -> Guest).
425 */
426struct GuestDnDTransferSendData : public GuestDnDTransferData
427{
428 GuestDnDTransferSendData()
429 : fObjState(0)
430 {
431 RT_ZERO(List);
432 int rc2 = DnDTransferListInit(&List);
433 AssertRC(rc2);
434 }
435
436 virtual ~GuestDnDTransferSendData()
437 {
438 destroy();
439 }
440
441 /**
442 * Destroys the object.
443 */
444 void destroy(void)
445 {
446 DnDTransferListDestroy(&List);
447 }
448
449 /**
450 * Resets the object.
451 */
452 void reset(void)
453 {
454 DnDTransferListReset(&List);
455 fObjState = 0;
456
457 GuestDnDTransferData::reset();
458 }
459
460 /** Transfer List to handle. */
461 DNDTRANSFERLIST List;
462 /** Current state of object in transfer.
463 * This is needed for keeping compatibility to old(er) DnD HGCM protocols.
464 *
465 * At the moment we only support transferring one object at a time. */
466 uint32_t fObjState;
467};
468
469/**
470 * Context structure for sending data to the guest.
471 */
472struct GuestDnDSendCtx : public GuestDnDData
473{
474 GuestDnDSendCtx(void);
475
476 /**
477 * Resets the object.
478 */
479 void reset(void);
480
481 /** Pointer to guest target class this context belongs to. */
482 GuestDnDTarget *pTarget;
483 /** Pointer to guest state this context belongs to. */
484 GuestDnDState *pState;
485 /** Target (VM) screen ID. */
486 uint32_t uScreenID;
487 /** Transfer data structure. */
488 GuestDnDTransferSendData Transfer;
489 /** Callback event to use. */
490 GuestDnDCallbackEvent EventCallback;
491};
492
493struct GuestDnDTransferRecvData : public GuestDnDTransferData
494{
495 GuestDnDTransferRecvData()
496 {
497 RT_ZERO(DroppedFiles);
498 int rc2 = DnDDroppedFilesInit(&DroppedFiles);
499 AssertRC(rc2);
500
501 RT_ZERO(List);
502 rc2 = DnDTransferListInit(&List);
503 AssertRC(rc2);
504
505 RT_ZERO(ObjCur);
506 rc2 = DnDTransferObjectInit(&ObjCur);
507 AssertRC(rc2);
508 }
509
510 virtual ~GuestDnDTransferRecvData()
511 {
512 destroy();
513 }
514
515 /**
516 * Destroys the object.
517 */
518 void destroy(void)
519 {
520 DnDTransferListDestroy(&List);
521 }
522
523 /**
524 * Resets the object.
525 */
526 void reset(void)
527 {
528 DnDDroppedFilesClose(&DroppedFiles);
529 DnDTransferListReset(&List);
530 DnDTransferObjectReset(&ObjCur);
531
532 GuestDnDTransferData::reset();
533 }
534
535 /** The "VirtualBox Dropped Files" directory on the host we're going
536 * to utilize for transferring files from guest to the host. */
537 DNDDROPPEDFILES DroppedFiles;
538 /** Transfer List to handle.
539 * Currently we only support one transfer list at a time. */
540 DNDTRANSFERLIST List;
541 /** Current transfer object being handled.
542 * Currently we only support one transfer object at a time. */
543 DNDTRANSFEROBJECT ObjCur;
544};
545
546/**
547 * Context structure for receiving data from the guest.
548 */
549struct GuestDnDRecvCtx : public GuestDnDData
550{
551 GuestDnDRecvCtx(void);
552
553 /**
554 * Resets the object.
555 */
556 void reset(void);
557
558 /** Pointer to guest source class this context belongs to. */
559 GuestDnDSource *pSource;
560 /** Pointer to guest state this context belongs to. */
561 GuestDnDState *pState;
562 /** Formats offered by the guest (and supported by the host). */
563 GuestDnDMIMEList lstFmtOffered;
564 /** Original drop format requested to receive from the guest. */
565 com::Utf8Str strFmtReq;
566 /** Intermediate drop format to be received from the guest.
567 * Some original drop formats require a different intermediate
568 * drop format:
569 *
570 * Receiving a file link as "text/plain" requires still to
571 * receive the file from the guest as "text/uri-list" first,
572 * then pointing to the file path on the host with the data
573 * in "text/plain" format returned. */
574 com::Utf8Str strFmtRecv;
575 /** Desired drop action to perform on the host.
576 * Needed to tell the guest if data has to be
577 * deleted e.g. when moving instead of copying. */
578 VBOXDNDACTION enmAction;
579 /** Transfer data structure. */
580 GuestDnDTransferRecvData Transfer;
581 /** Callback event to use. */
582 GuestDnDCallbackEvent EventCallback;
583};
584
585/**
586 * Class for maintainig a (buffered) guest DnD message.
587 */
588class GuestDnDMsg
589{
590public:
591
592 GuestDnDMsg(void)
593 : uMsg(0)
594 , cParms(0)
595 , cParmsAlloc(0)
596 , paParms(NULL) { }
597
598 virtual ~GuestDnDMsg(void)
599 {
600 reset();
601 }
602
603public:
604
605 /**
606 * Appends a new HGCM parameter to the message and returns the pointer to it.
607 */
608 PVBOXHGCMSVCPARM getNextParam(void)
609 {
610 if (cParms >= cParmsAlloc)
611 {
612 if (!paParms)
613 paParms = (PVBOXHGCMSVCPARM)RTMemAlloc(4 * sizeof(VBOXHGCMSVCPARM));
614 else
615 paParms = (PVBOXHGCMSVCPARM)RTMemRealloc(paParms, (cParmsAlloc + 4) * sizeof(VBOXHGCMSVCPARM));
616 if (!paParms)
617 throw VERR_NO_MEMORY;
618 RT_BZERO(&paParms[cParmsAlloc], 4 * sizeof(VBOXHGCMSVCPARM));
619 cParmsAlloc += 4;
620 }
621
622 return &paParms[cParms++];
623 }
624
625 /**
626 * Returns the current parameter count.
627 *
628 * @returns Current parameter count.
629 */
630 uint32_t getCount(void) const { return cParms; }
631
632 /**
633 * Returns the pointer to the beginning of the HGCM parameters array. Use with care.
634 *
635 * @returns Pointer to the beginning of the HGCM parameters array.
636 */
637 PVBOXHGCMSVCPARM getParms(void) const { return paParms; }
638
639 /**
640 * Returns the message type.
641 *
642 * @returns Message type.
643 */
644 uint32_t getType(void) const { return uMsg; }
645
646 /**
647 * Resets the object.
648 */
649 void reset(void)
650 {
651 if (paParms)
652 {
653 /* Remove deep copies. */
654 for (uint32_t i = 0; i < cParms; i++)
655 {
656 if ( paParms[i].type == VBOX_HGCM_SVC_PARM_PTR
657 && paParms[i].u.pointer.size)
658 {
659 AssertPtr(paParms[i].u.pointer.addr);
660 RTMemFree(paParms[i].u.pointer.addr);
661 }
662 }
663
664 RTMemFree(paParms);
665 paParms = NULL;
666 }
667
668 uMsg = cParms = cParmsAlloc = 0;
669 }
670
671 /**
672 * Appends a new message parameter of type pointer.
673 *
674 * @returns VBox status code.
675 * @param pvBuf Pointer to data to use.
676 * @param cbBuf Size (in bytes) of data to use.
677 */
678 int appendPointer(void *pvBuf, uint32_t cbBuf)
679 {
680 PVBOXHGCMSVCPARM pParm = getNextParam();
681 if (!pParm)
682 return VERR_NO_MEMORY;
683
684 void *pvTmp = NULL;
685 if (cbBuf)
686 {
687 AssertPtr(pvBuf);
688 pvTmp = RTMemDup(pvBuf, cbBuf);
689 if (!pvTmp)
690 return VERR_NO_MEMORY;
691 }
692
693 HGCMSvcSetPv(pParm, pvTmp, cbBuf);
694 return VINF_SUCCESS;
695 }
696
697 /**
698 * Appends a new message parameter of type string.
699 *
700 * @returns VBox status code.
701 * @param pszString Pointer to string data to use.
702 */
703 int appendString(const char *pszString)
704 {
705 PVBOXHGCMSVCPARM pParm = getNextParam();
706 if (!pParm)
707 return VERR_NO_MEMORY;
708
709 char *pszTemp = RTStrDup(pszString);
710 if (!pszTemp)
711 return VERR_NO_MEMORY;
712
713 HGCMSvcSetStr(pParm, pszTemp);
714 return VINF_SUCCESS;
715 }
716
717 /**
718 * Appends a new message parameter of type uint32_t.
719 *
720 * @returns VBox status code.
721 * @param u32Val uint32_t value to use.
722 */
723 int appendUInt32(uint32_t u32Val)
724 {
725 PVBOXHGCMSVCPARM pParm = getNextParam();
726 if (!pParm)
727 return VERR_NO_MEMORY;
728
729 HGCMSvcSetU32(pParm, u32Val);
730 return VINF_SUCCESS;
731 }
732
733 /**
734 * Appends a new message parameter of type uint64_t.
735 *
736 * @returns VBox status code.
737 * @param u64Val uint64_t value to use.
738 */
739 int appendUInt64(uint64_t u64Val)
740 {
741 PVBOXHGCMSVCPARM pParm = getNextParam();
742 if (!pParm)
743 return VERR_NO_MEMORY;
744
745 HGCMSvcSetU64(pParm, u64Val);
746 return VINF_SUCCESS;
747 }
748
749 /**
750 * Sets the HGCM message type (function number).
751 *
752 * @param uMsgType Message type to set.
753 */
754 void setType(uint32_t uMsgType) { uMsg = uMsgType; }
755
756protected:
757
758 /** Message type. */
759 uint32_t uMsg;
760 /** Message parameters. */
761 uint32_t cParms;
762 /** Size of array. */
763 uint32_t cParmsAlloc;
764 /** Array of HGCM parameters */
765 PVBOXHGCMSVCPARM paParms;
766};
767
768/** Guest DnD callback function definition. */
769typedef DECLCALLBACKPTR(int, PFNGUESTDNDCALLBACK,(uint32_t uMsg, void *pvParms, size_t cbParms, void *pvUser));
770
771/**
772 * Structure for keeping a guest DnD callback.
773 * Each callback can handle one HGCM message, however, multiple HGCM messages can be registered
774 * to the same callback (function).
775 */
776typedef struct GuestDnDCallback
777{
778 GuestDnDCallback(void)
779 : uMessgage(0)
780 , pfnCallback(NULL)
781 , pvUser(NULL) { }
782
783 GuestDnDCallback(PFNGUESTDNDCALLBACK pvCB, uint32_t uMsg, void *pvUsr = NULL)
784 : uMessgage(uMsg)
785 , pfnCallback(pvCB)
786 , pvUser(pvUsr) { }
787
788 /** The HGCM message ID to handle. */
789 uint32_t uMessgage;
790 /** Pointer to callback function. */
791 PFNGUESTDNDCALLBACK pfnCallback;
792 /** Pointer to user-supplied data. */
793 void *pvUser;
794} GuestDnDCallback;
795
796/** Contains registered callback pointers for specific HGCM message types. */
797typedef std::map<uint32_t, GuestDnDCallback> GuestDnDCallbackMap;
798
799/**
800 * Class for keeping a DnD guest state around.
801 */
802class GuestDnDState
803{
804
805public:
806 DECLARE_TRANSLATE_METHODS(GuestDnDState)
807
808 GuestDnDState(const ComObjPtr<Guest>& pGuest);
809 virtual ~GuestDnDState(void);
810
811public:
812
813 int notifyAboutGuestResponse(void) const;
814 int waitForGuestResponse(RTMSINTERVAL msTimeout = 500) const;
815
816 void setActionsAllowed(VBOXDNDACTIONLIST a) { m_dndLstActionsAllowed = a; }
817 VBOXDNDACTIONLIST getActionsAllowed(void) const { return m_dndLstActionsAllowed; }
818
819 void setActionDefault(VBOXDNDACTION a) { m_dndActionDefault = a; }
820 VBOXDNDACTION getActionDefault(void) const { return m_dndActionDefault; }
821
822 void setFormats(const GuestDnDMIMEList &lstFormats) { m_lstFormats = lstFormats; }
823 GuestDnDMIMEList formats(void) const { return m_lstFormats; }
824
825 void reset(void);
826
827 bool isProgressCanceled(void) const;
828 int setCallback(uint32_t uMsg, PFNGUESTDNDCALLBACK pfnCallback, void *pvUser = NULL);
829 int setProgress(unsigned uPercentage, uint32_t uState, int rcOp = VINF_SUCCESS, const Utf8Str &strMsg = "");
830 HRESULT resetProgress(const ComObjPtr<Guest>& pParent);
831 HRESULT queryProgressTo(IProgress **ppProgress);
832
833public:
834
835 /** @name HGCM callback handling.
836 @{ */
837 int onDispatch(uint32_t u32Function, void *pvParms, uint32_t cbParms);
838 /** @} */
839
840public:
841
842 /** Pointer to context this class is tied to. */
843 void *m_pvCtx;
844 /** The DnD protocol version to use, depending on the
845 * installed Guest Additions. See DragAndDropSvc.h for
846 * a protocol changelog. */
847 uint32_t m_uProtocolVersion;
848 /** The guest feature flags reported to the host (VBOX_DND_GF_XXX). */
849 uint64_t m_fGuestFeatures0;
850 /** Event for waiting for response. */
851 RTSEMEVENT m_EventSem;
852 /** Default action to perform in case of a
853 * successful drop. */
854 VBOXDNDACTION m_dndActionDefault;
855 /** Actions supported by the guest in case of a successful drop. */
856 VBOXDNDACTIONLIST m_dndLstActionsAllowed;
857 /** Format(s) requested/supported from the guest. */
858 GuestDnDMIMEList m_lstFormats;
859 /** Pointer to IGuest parent object. */
860 ComObjPtr<Guest> m_pParent;
861 /** Pointer to associated progress object. Optional. */
862 ComObjPtr<Progress> m_pProgress;
863 /** Callback map. */
864 GuestDnDCallbackMap m_mapCallbacks;
865};
866
867/**
868 * Private singleton class for the guest's DnD implementation.
869 *
870 * Can't be instanciated directly, only via the factory pattern.
871 * Keeps track of all ongoing DnD transfers.
872 */
873class GuestDnD
874{
875public:
876
877 /**
878 * Creates the Singleton GuestDnD object.
879 *
880 * @returns Newly created Singleton object, or NULL on failure.
881 */
882 static GuestDnD *createInstance(const ComObjPtr<Guest>& pGuest)
883 {
884 Assert(NULL == GuestDnD::s_pInstance);
885 GuestDnD::s_pInstance = new GuestDnD(pGuest);
886 return GuestDnD::s_pInstance;
887 }
888
889 /**
890 * Destroys the Singleton GuestDnD object.
891 */
892 static void destroyInstance(void)
893 {
894 if (GuestDnD::s_pInstance)
895 {
896 delete GuestDnD::s_pInstance;
897 GuestDnD::s_pInstance = NULL;
898 }
899 }
900
901 /**
902 * Returns the Singleton GuestDnD object.
903 *
904 * @returns Pointer to Singleton GuestDnD object, or NULL if not created yet.
905 */
906 static inline GuestDnD *getInstance(void)
907 {
908 AssertPtr(GuestDnD::s_pInstance);
909 return GuestDnD::s_pInstance;
910 }
911
912protected:
913
914 /** List of registered DnD sources. */
915 typedef std::list< ComObjPtr<GuestDnDSource> > GuestDnDSrcList;
916 /** List of registered DnD targets. */
917 typedef std::list< ComObjPtr<GuestDnDTarget> > GuestDnDTgtList;
918
919 /** Constructor; will throw rc on failure. */
920 GuestDnD(const ComObjPtr<Guest>& pGuest);
921 virtual ~GuestDnD(void);
922
923public:
924
925 /** @name Public helper functions.
926 * @{ */
927 HRESULT adjustScreenCoordinates(ULONG uScreenId, ULONG *puX, ULONG *puY) const;
928 GuestDnDState *getState(uint32_t = 0) const;
929 int hostCall(uint32_t u32Function, uint32_t cParms, PVBOXHGCMSVCPARM paParms) const;
930 GuestDnDMIMEList defaultFormats(void) const { return m_strDefaultFormats; }
931 /** @} */
932
933 /** @name Source / target management.
934 * @{ */
935 int registerSource(const ComObjPtr<GuestDnDSource> &Source);
936 int unregisterSource(const ComObjPtr<GuestDnDSource> &Source);
937 size_t getSourceCount(void);
938
939 int registerTarget(const ComObjPtr<GuestDnDTarget> &Target);
940 int unregisterTarget(const ComObjPtr<GuestDnDTarget> &Target);
941 size_t getTargetCount(void);
942 /** @} */
943
944public:
945
946 /** @name Static low-level HGCM callback handler.
947 * @{ */
948 static DECLCALLBACK(int) notifyDnDDispatcher(void *pvExtension, uint32_t u32Function, void *pvParms, uint32_t cbParms);
949 /** @} */
950
951 /** @name Static helper methods.
952 * @{ */
953 static bool isFormatInFormatList(const com::Utf8Str &strFormat, const GuestDnDMIMEList &lstFormats);
954 static GuestDnDMIMEList toFormatList(const com::Utf8Str &strFormats, const com::Utf8Str &strSep = DND_FORMATS_SEPARATOR_STR);
955 static com::Utf8Str toFormatString(const GuestDnDMIMEList &lstFormats);
956 static GuestDnDMIMEList toFilteredFormatList(const GuestDnDMIMEList &lstFormatsSupported, const GuestDnDMIMEList &lstFormatsWanted);
957 static GuestDnDMIMEList toFilteredFormatList(const GuestDnDMIMEList &lstFormatsSupported, const com::Utf8Str &strFormatsWanted);
958 static DnDAction_T toMainAction(VBOXDNDACTION dndAction);
959 static std::vector<DnDAction_T> toMainActions(VBOXDNDACTIONLIST dndActionList);
960 static VBOXDNDACTION toHGCMAction(DnDAction_T enmAction);
961 static void toHGCMActions(DnDAction_T enmDefAction, VBOXDNDACTION *pDefAction, const std::vector<DnDAction_T> vecAllowedActions, VBOXDNDACTIONLIST *pLstAllowedActions);
962 /** @} */
963
964protected:
965
966 /** @name Singleton properties.
967 * @{ */
968 /** List of supported default MIME/Content-type formats. */
969 GuestDnDMIMEList m_strDefaultFormats;
970 /** Pointer to guest implementation. */
971 const ComObjPtr<Guest> m_pGuest;
972 /** The current state from the guest. At the
973 * moment we only support only state a time (ARQ-style). */
974 GuestDnDState *m_pState;
975 /** Critical section to serialize access. */
976 RTCRITSECT m_CritSect;
977 /** Number of active transfers (guest->host or host->guest). */
978 uint32_t m_cTransfersPending;
979 GuestDnDSrcList m_lstSrc;
980 GuestDnDTgtList m_lstTgt;
981 /** @} */
982
983private:
984
985 /** Static pointer to singleton instance. */
986 static GuestDnD *s_pInstance;
987};
988
989/** Access to the GuestDnD's singleton instance. */
990#define GuestDnDInst() GuestDnD::getInstance()
991
992/** List of pointers to guest DnD Messages. */
993typedef std::list<GuestDnDMsg *> GuestDnDMsgList;
994
995/**
996 * IDnDBase class implementation for sharing code between
997 * IGuestDnDSource and IGuestDnDTarget implementation.
998 */
999class GuestDnDBase
1000{
1001protected:
1002
1003 GuestDnDBase(void);
1004
1005protected:
1006
1007 /** Shared (internal) IDnDBase method implementations.
1008 * @{ */
1009 bool i_isFormatSupported(const com::Utf8Str &aFormat) const;
1010 const GuestDnDMIMEList &i_getFormats(void) const;
1011 HRESULT i_addFormats(const GuestDnDMIMEList &aFormats);
1012 HRESULT i_removeFormats(const GuestDnDMIMEList &aFormats);
1013 /** @} */
1014
1015protected:
1016
1017 /** @name Functions for handling a simple host HGCM message queue.
1018 * @{ */
1019 int msgQueueAdd(GuestDnDMsg *pMsg);
1020 GuestDnDMsg *msgQueueGetNext(void);
1021 void msgQueueRemoveNext(void);
1022 void msgQueueClear(void);
1023 /** @} */
1024
1025 int sendCancel(void);
1026 int updateProgress(GuestDnDData *pData, GuestDnDState *pState, size_t cbDataAdd = 0);
1027 int waitForEvent(GuestDnDCallbackEvent *pEvent, GuestDnDState *pState, RTMSINTERVAL msTimeout);
1028
1029protected:
1030
1031 /** @name Public attributes (through getters/setters).
1032 * @{ */
1033 /** Pointer to guest implementation. */
1034 const ComObjPtr<Guest> m_pGuest;
1035 /** List of supported MIME types by the source. */
1036 GuestDnDMIMEList m_lstFmtSupported;
1037 /** List of offered MIME types to the counterpart. */
1038 GuestDnDMIMEList m_lstFmtOffered;
1039 /** Whether the object still is in pending state. */
1040 bool m_fIsPending;
1041 /** Pointer to state bound to this object. */
1042 GuestDnDState *m_pState;
1043 /** @} */
1044
1045 /**
1046 * Internal stuff.
1047 */
1048 struct
1049 {
1050 /** Outgoing message queue (FIFO). */
1051 GuestDnDMsgList lstMsgOut;
1052 } m_DataBase;
1053};
1054#endif /* !MAIN_INCLUDED_GuestDnDPrivate_h */
1055
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use