VirtualBox

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

Last change on this file since 92839 was 91312, checked in by vboxsync, 3 years ago

Main: bugref:1909: Prepared the API translation engine to using in ExtPacks and VBoxManage. Added using API translation engine in ExtPacks. Allowed VBox compilation with NLS enabled and GUI disabled. Allowed ExtPacks only compilation with NLS translation enabled.

  • 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 91312 2021-09-20 11:06:57Z vboxsync $ */
2/** @file
3 * Private guest drag and drop code, used by GuestDnDTarget +
4 * GuestDnDSource.
5 */
6
7/*
8 * Copyright (C) 2011-2020 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.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette