VirtualBox

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

Last change on this file since 55854 was 55640, checked in by vboxsync, 10 years ago

DnD:

  • Overhauled "dropped files" directory + general file handling: Keep the directories/files open when doing the actual transfers (only protocol >= 2)
  • Unified "dropped files" directory creation/rollback handling for guest/host parts.
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.4 KB
Line 
1/* $Id: GuestDnDPrivate.h 55640 2015-05-04 12:38:57Z vboxsync $ */
2/** @file
3 * Private guest drag and drop code, used by GuestDnDTarget +
4 * GuestDnDSource.
5 */
6
7/*
8 * Copyright (C) 2011-2015 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 ____H_GUESTDNDPRIVATE
20#define ____H_GUESTDNDPRIVATE
21
22#include <iprt/dir.h>
23#include <iprt/file.h>
24
25#include "VBox/hgcmsvc.h" /* For PVBOXHGCMSVCPARM. */
26#include "VBox/GuestHost/DragAndDrop.h"
27
28/**
29 * Forward prototype declarations.
30 */
31class Guest;
32class GuestDnDBase;
33class GuestDnDResponse;
34class GuestDnDSource;
35class GuestDnDTarget;
36class Progress;
37
38class GuestDnDCallbackEvent
39{
40public:
41
42 GuestDnDCallbackEvent(void)
43 : mSemEvent(NIL_RTSEMEVENT)
44 , mRc(VINF_SUCCESS) { }
45
46 virtual ~GuestDnDCallbackEvent(void);
47
48public:
49
50 int Reset(void);
51
52 int Notify(int rc);
53
54 int Result(void) const { return mRc; }
55
56 int Wait(RTMSINTERVAL msTimeout);
57
58protected:
59
60 /** Event semaphore to notify on error/completion. */
61 RTSEMEVENT mSemEvent;
62 /** Callback result. */
63 int mRc;
64};
65
66/**
67 * Structure for keeping the (URI) data to be sent/received.
68 */
69typedef struct GuestDnDData
70{
71 GuestDnDData(void)
72 : cbToProcess(0)
73 , cbProcessed(0) { }
74
75 void Reset(void)
76 {
77 vecData.clear();
78 cbToProcess = 0;
79 cbProcessed = 0;
80 }
81
82 /** Array (vector) of guest DnD data. This might be an URI list, according
83 * to the format being set. */
84 std::vector<BYTE> vecData;
85 /** Overall size (in bytes) of data to send. */
86 uint64_t cbToProcess;
87 /** Overall size (in bytes) of processed file data. */
88 uint64_t cbProcessed;
89
90} GuestDnDData;
91
92/**
93 * Structure for keeping around URI (list) data.
94 */
95typedef struct GuestDnDURIData
96{
97 GuestDnDURIData(void)
98 : pvScratchBuf(NULL)
99 , cbScratchBuf(0) { }
100
101 virtual ~GuestDnDURIData(void)
102 {
103 Reset();
104 }
105
106 void Reset(void)
107 {
108 lstURI.Clear();
109#if 0 /* Currently the scratch buffer will be maintained elswewhere. */
110 if (pvScratchBuf)
111 {
112 RTMemFree(pvScratchBuf);
113 pvScratchBuf = NULL;
114 }
115 cbScratchBuf = 0;
116#else
117 pvScratchBuf = NULL;
118 cbScratchBuf = 0;
119#endif
120 }
121
122 DNDDIRDROPPEDFILES mDropDir;
123 /** (Non-recursive) List of root URI objects to receive. */
124 DnDURIList lstURI;
125 /** Current object to receive. */
126 DnDURIObject objURI;
127 /** Pointer to an optional scratch buffer to use for
128 * doing the actual chunk transfers. */
129 void *pvScratchBuf;
130 /** Size (in bytes) of scratch buffer. */
131 size_t cbScratchBuf;
132
133} GuestDnDURIData;
134
135/**
136 * Context structure for sending data to the guest.
137 */
138typedef struct SENDDATACTX
139{
140 /** Pointer to guest target class this context belongs to. */
141 GuestDnDTarget *mpTarget;
142 /** Pointer to guest response class this context belongs to. */
143 GuestDnDResponse *mpResp;
144 /** Flag indicating whether a file transfer is active and
145 * initiated by the host. */
146 bool mIsActive;
147 /** Target (VM) screen ID. */
148 uint32_t mScreenID;
149 /** Drag'n drop format to send. */
150 com::Utf8Str mFormat;
151 /** Drag'n drop data to send.
152 * This can be arbitrary data or an URI list. */
153 GuestDnDData mData;
154 /** URI data structure. */
155 GuestDnDURIData mURI;
156 /** Callback event to use. */
157 GuestDnDCallbackEvent mCallback;
158
159} SENDDATACTX, *PSENDDATACTX;
160
161/**
162 * Context structure for receiving data from the guest.
163 */
164typedef struct RECVDATACTX
165{
166 /** Pointer to guest source class this context belongs to. */
167 GuestDnDSource *mpSource;
168 /** Pointer to guest response class this context belongs to. */
169 GuestDnDResponse *mpResp;
170 /** Flag indicating whether a file transfer is active and
171 * initiated by the host. */
172 bool mIsActive;
173 /** Drag'n drop format to send. */
174 com::Utf8Str mFormat;
175 /** Desired drop action to perform on the host.
176 * Needed to tell the guest if data has to be
177 * deleted e.g. when moving instead of copying. */
178 uint32_t mAction;
179 /** Drag'n drop received from the guest.
180 * This can be arbitrary data or an URI list. */
181 GuestDnDData mData;
182 /** URI data structure. */
183 GuestDnDURIData mURI;
184 /** Callback event to use. */
185 GuestDnDCallbackEvent mCallback;
186
187} RECVDATACTX, *PRECVDATACTX;
188
189/**
190 * Simple structure for a buffered guest DnD message.
191 */
192class GuestDnDMsg
193{
194public:
195
196 GuestDnDMsg(void)
197 : uMsg(0)
198 , cParms(0)
199 , cParmsAlloc(0)
200 , paParms(NULL) { }
201
202 virtual ~GuestDnDMsg(void)
203 {
204 if (paParms)
205 {
206 /* Remove deep copies. */
207 for (uint32_t i = 0; i < cParms; i++)
208 {
209 if ( paParms[i].type == VBOX_HGCM_SVC_PARM_PTR
210 && paParms[i].u.pointer.addr)
211 {
212 RTMemFree(paParms[i].u.pointer.addr);
213 }
214 }
215
216 delete paParms;
217 }
218 }
219
220public:
221
222 PVBOXHGCMSVCPARM getNextParam(void)
223 {
224 if (cParms >= cParmsAlloc)
225 {
226 paParms = (PVBOXHGCMSVCPARM)RTMemRealloc(paParms, (cParmsAlloc + 4) * sizeof(VBOXHGCMSVCPARM));
227 if (!paParms)
228 throw VERR_NO_MEMORY;
229 RT_BZERO(&paParms[cParmsAlloc], 4 * sizeof(VBOXHGCMSVCPARM));
230 cParmsAlloc += 4;
231 }
232
233 return &paParms[cParms++];
234 }
235
236 uint32_t getCount(void) const { return cParms; }
237 PVBOXHGCMSVCPARM getParms(void) const { return paParms; }
238 uint32_t getType(void) const { return uMsg; }
239
240 int setNextPointer(void *pvBuf, uint32_t cbBuf)
241 {
242 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
243 AssertReturn(cbBuf, VERR_INVALID_PARAMETER);
244
245 PVBOXHGCMSVCPARM pParm = getNextParam();
246 if (!pParm)
247 return VERR_NO_MEMORY;
248
249 void *pvTmp = RTMemDup(pvBuf, cbBuf);
250 if (!pvTmp)
251 {
252 RTMemFree(pParm);
253 return VERR_NO_MEMORY;
254 }
255
256 pParm->setPointer(pvTmp, cbBuf);
257 return VINF_SUCCESS;
258 }
259
260 int setNextString(const char *pszString)
261 {
262 PVBOXHGCMSVCPARM pParm = getNextParam();
263 if (!pParm)
264 return VERR_NO_MEMORY;
265
266 char *pszTemp = RTStrDup(pszString);
267 if (!pszTemp)
268 {
269 RTMemFree(pParm);
270 return VERR_NO_MEMORY;
271 }
272
273 pParm->setString(pszTemp);
274 return VINF_SUCCESS;
275 }
276
277 int setNextUInt32(uint32_t u32Val)
278 {
279 PVBOXHGCMSVCPARM pParm = getNextParam();
280 if (!pParm)
281 return VERR_NO_MEMORY;
282
283 pParm->setUInt32(u32Val);
284 return VINF_SUCCESS;
285 }
286
287 int setNextUInt64(uint64_t u64Val)
288 {
289 PVBOXHGCMSVCPARM pParm = getNextParam();
290 if (!pParm)
291 return VERR_NO_MEMORY;
292
293 pParm->setUInt64(u64Val);
294 return VINF_SUCCESS;
295 }
296
297 void setType(uint32_t uMsgType) { uMsg = uMsgType; }
298
299protected:
300
301 /** Message type. */
302 uint32_t uMsg;
303 /** Message parameters. */
304 uint32_t cParms;
305 /** Size of array. */
306 uint32_t cParmsAlloc;
307 /** Array of HGCM parameters */
308 PVBOXHGCMSVCPARM paParms;
309};
310
311/** Guest DnD callback function definition. */
312typedef DECLCALLBACKPTR(int, PFNGUESTDNDCALLBACK) (uint32_t uMsg, void *pvParms, size_t cbParms, void *pvUser);
313
314/**
315 * Structure for keeping a guest DnD callback.
316 * Each callback can handle one HGCM message, however, multiple HGCM messages can be registered
317 * to the same callback (function).
318 */
319typedef struct GuestDnDCallback
320{
321 GuestDnDCallback(void)
322 : uMessgage(0)
323 , pfnCallback(NULL)
324 , pvUser(NULL) { }
325
326 GuestDnDCallback(PFNGUESTDNDCALLBACK pvCB, uint32_t uMsg, void *pvUsr = NULL)
327 : uMessgage(uMsg)
328 , pfnCallback(pvCB)
329 , pvUser(pvUsr) { }
330
331 /** The HGCM message ID to handle. */
332 uint32_t uMessgage;
333 /** Pointer to callback function. */
334 PFNGUESTDNDCALLBACK pfnCallback;
335 /** Pointer to user-supplied data. */
336 void *pvUser;
337
338} GuestDnDCallback;
339
340/** Contains registered callback pointers for specific HGCM message types. */
341typedef std::map<uint32_t, GuestDnDCallback> GuestDnDCallbackMap;
342
343class GuestDnDResponse
344{
345
346public:
347
348 GuestDnDResponse(const ComObjPtr<Guest>& pGuest);
349 virtual ~GuestDnDResponse(void);
350
351public:
352
353 int notifyAboutGuestResponse(void) const;
354 int waitForGuestResponse(RTMSINTERVAL msTimeout = 500) const;
355
356 void setAllActions(uint32_t a) { m_allActions = a; }
357 uint32_t allActions(void) const { return m_allActions; }
358
359 void setDefAction(uint32_t a) { m_defAction = a; }
360 uint32_t defAction(void) const { return m_defAction; }
361
362 void setFormat(const Utf8Str &strFormat) { m_strFormat = strFormat; }
363 Utf8Str format(void) const { return m_strFormat; }
364
365 void reset(void);
366
367 bool isProgressCanceled(void) const;
368 int setCallback(uint32_t uMsg, PFNGUESTDNDCALLBACK pfnCallback, void *pvUser = NULL);
369 int setProgress(unsigned uPercentage, uint32_t uState, int rcOp = VINF_SUCCESS);
370 HRESULT resetProgress(const ComObjPtr<Guest>& pParent);
371 HRESULT queryProgressTo(IProgress **ppProgress);
372
373public:
374
375 /** @name HGCM callback handling.
376 @{ */
377 int onDispatch(uint32_t u32Function, void *pvParms, uint32_t cbParms);
378 /** @} */
379
380public:
381
382 Utf8Str errorToString(const ComObjPtr<Guest>& pGuest, int guestRc);
383
384protected:
385
386 /** Pointer to context this class is tied to. */
387 void *m_pvCtx;
388 RTSEMEVENT m_EventSem;
389 uint32_t m_defAction;
390 uint32_t m_allActions;
391 Utf8Str m_strFormat;
392
393 /** Pointer to IGuest parent object. */
394 ComObjPtr<Guest> m_parent;
395 /** Pointer to associated progress object. Optional. */
396 ComObjPtr<Progress> m_progress;
397 /** Callback map. */
398 GuestDnDCallbackMap m_mapCallbacks;
399};
400
401/**
402 * Private singleton class for the guest's DnD
403 * implementation. Can't be instanciated directly, only via
404 * the factory pattern.
405 */
406class GuestDnD
407{
408public:
409
410 static GuestDnD *createInstance(const ComObjPtr<Guest>& pGuest)
411 {
412 Assert(NULL == GuestDnD::s_pInstance);
413 GuestDnD::s_pInstance = new GuestDnD(pGuest);
414 return GuestDnD::s_pInstance;
415 }
416
417 static void destroyInstance(void)
418 {
419 if (GuestDnD::s_pInstance)
420 {
421 delete GuestDnD::s_pInstance;
422 GuestDnD::s_pInstance = NULL;
423 }
424 }
425
426 static inline GuestDnD *getInstance(void)
427 {
428 AssertPtr(GuestDnD::s_pInstance);
429 return GuestDnD::s_pInstance;
430 }
431
432protected:
433
434 GuestDnD(const ComObjPtr<Guest>& pGuest);
435 virtual ~GuestDnD(void);
436
437public:
438
439 /** @name Public helper functions.
440 * @{ */
441 int adjustScreenCoordinates(ULONG uScreenId, ULONG *puX, ULONG *puY) const;
442 int hostCall(uint32_t u32Function, uint32_t cParms, PVBOXHGCMSVCPARM paParms) const;
443 GuestDnDResponse *response(void) { return m_pResponse; }
444 std::vector<com::Utf8Str> defaultFormats(void) const { return m_strDefaultFormats; }
445 /** @} */
446
447public:
448
449 /** @name Static low-level HGCM callback handler.
450 * @{ */
451 static DECLCALLBACK(int) notifyDnDDispatcher(void *pvExtension, uint32_t u32Function, void *pvParms, uint32_t cbParms);
452 /** @} */
453
454 /** @name Static helper methods.
455 * @{ */
456 static com::Utf8Str toFormatString(const std::vector<com::Utf8Str> &lstSupportedFormats, const std::vector<com::Utf8Str> &lstFormats);
457 static void toFormatVector(const std::vector<com::Utf8Str> &lstSupportedFormats, const com::Utf8Str &strFormats, std::vector<com::Utf8Str> &vecformats);
458 static DnDAction_T toMainAction(uint32_t uAction);
459 static void toMainActions(uint32_t uActions, std::vector<DnDAction_T> &vecActions);
460 static uint32_t toHGCMAction(DnDAction_T enmAction);
461 static void toHGCMActions(DnDAction_T enmDefAction, uint32_t *puDefAction, const std::vector<DnDAction_T> vecAllowedActions, uint32_t *puAllowedActions);
462 /** @} */
463
464protected:
465
466 /** @name Singleton properties.
467 * @{ */
468 /** List of supported default MIME/Content-type formats. */
469 std::vector<com::Utf8Str> m_strDefaultFormats;
470 /** Pointer to guest implementation. */
471 const ComObjPtr<Guest> m_pGuest;
472 /** The current (last) response from the guest. At the
473 * moment we only support only response a time (ARQ-style). */
474 GuestDnDResponse *m_pResponse;
475 /** @} */
476
477private:
478
479 /** Staic pointer to singleton instance. */
480 static GuestDnD *s_pInstance;
481};
482
483/** Access to the GuestDnD's singleton instance. */
484#define GuestDnDInst() GuestDnD::getInstance()
485
486/** List of pointers to guest DnD Messages. */
487typedef std::list<GuestDnDMsg *> GuestDnDMsgList;
488
489/**
490 * IDnDBase class implementation for sharing code between
491 * IGuestDnDSource and IGuestDnDTarget implementation.
492 */
493class GuestDnDBase
494{
495protected:
496
497 GuestDnDBase(void);
498
499protected:
500
501 /** Shared (internal) IDnDBase method implementations.
502 * @{ */
503 HRESULT i_isFormatSupported(const com::Utf8Str &aFormat, BOOL *aSupported);
504 HRESULT i_getFormats(std::vector<com::Utf8Str> &aFormats);
505 HRESULT i_addFormats(const std::vector<com::Utf8Str> &aFormats);
506 HRESULT i_removeFormats(const std::vector<com::Utf8Str> &aFormats);
507
508 HRESULT i_getProtocolVersion(ULONG *puVersion);
509 /** @} */
510
511protected:
512
513 int getProtocolVersion(uint32_t *puVersion);
514
515 /** @name Functions for handling a simple host HGCM message queue.
516 * @{ */
517 int msgQueueAdd(GuestDnDMsg *pMsg);
518 GuestDnDMsg *msgQueueGetNext(void);
519 void msgQueueRemoveNext(void);
520 void msgQueueClear(void);
521 /** @} */
522
523 int sendCancel(void);
524 int waitForEvent(RTMSINTERVAL msTimeout, GuestDnDCallbackEvent &Event, GuestDnDResponse *pResp);
525
526protected:
527
528 /** @name Public attributes (through getters/setters).
529 * @{ */
530 /** Pointer to guest implementation. */
531 const ComObjPtr<Guest> m_pGuest;
532 /** List of supported MIME/Content-type formats. */
533 std::vector<com::Utf8Str> m_strFormats;
534 /** @} */
535
536 struct
537 {
538 /** Flag indicating whether a drop operation currently
539 * is in progress or not. */
540 bool mfTransferIsPending;
541 /** The DnD protocol version to use, depending on the
542 * installed Guest Additions. */
543 uint32_t mProtocolVersion;
544 /** Outgoing message queue. */
545 GuestDnDMsgList mListOutgoing;
546 } mDataBase;
547};
548#endif /* ____H_GUESTDNDPRIVATE */
549
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