VirtualBox

source: vbox/trunk/src/VBox/HostServices/DragAndDrop/dndmanager.cpp@ 57286

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

DnD/HostService: Check for bad_alloc, report if host callbacks are missing, logging.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.5 KB
Line 
1/* $Id: dndmanager.cpp 57286 2015-08-12 11:33:22Z vboxsync $ */
2/** @file
3 * Drag and Drop manager: Handling of DnD messages on the host side.
4 */
5
6/*
7 * Copyright (C) 2011-2015 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 * Header Files *
20 ******************************************************************************/
21
22#ifdef LOG_GROUP
23 #undef LOG_GROUP
24#endif
25#define LOG_GROUP LOG_GROUP_GUEST_DND
26
27#include "dndmanager.h"
28
29#include <VBox/log.h>
30#include <iprt/file.h>
31#include <iprt/dir.h>
32#include <iprt/path.h>
33#include <iprt/uri.h>
34
35/******************************************************************************
36 * DnDManager *
37 ******************************************************************************/
38
39int DnDManager::addMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[], bool fAppend /* = true */)
40{
41 int rc = VINF_SUCCESS;
42
43 LogFlowFunc(("uMsg=%RU32, cParms=%RU32, fAppend=%RTbool\n", uMsg, cParms, fAppend));
44
45 try
46 {
47 DnDMessage *pMessage = NULL;
48
49 switch (uMsg)
50 {
51 case DragAndDropSvc::HOST_DND_HG_EVT_ENTER:
52 {
53 clear();
54 LogFlowFunc(("HOST_DND_HG_EVT_ENTER\n"));
55 break;
56 }
57
58 case DragAndDropSvc::HOST_DND_HG_EVT_MOVE:
59 {
60 LogFlowFunc(("HOST_DND_HG_EVT_MOVE\n"));
61 break;
62 }
63
64 case DragAndDropSvc::HOST_DND_HG_EVT_LEAVE:
65 {
66 LogFlowFunc(("HOST_DND_HG_EVT_LEAVE\n"));
67 break;
68 }
69
70 case DragAndDropSvc::HOST_DND_HG_EVT_DROPPED:
71 {
72 LogFlowFunc(("HOST_DND_HG_EVT_DROPPED\n"));
73 break;
74 }
75
76 case DragAndDropSvc::HOST_DND_HG_EVT_CANCEL:
77 {
78 LogFlowFunc(("HOST_DND_HG_EVT_CANCEL\n"));
79
80 pMessage = new DnDHGCancelMessage();
81 break;
82 }
83
84 case DragAndDropSvc::HOST_DND_HG_SND_DATA:
85 {
86 LogFlowFunc(("HOST_DND_HG_SND_DATA\n"));
87 break;
88 }
89
90 case DragAndDropSvc::HOST_DND_HG_SND_DIR:
91 {
92 LogFlowFunc(("HOST_DND_HG_SND_DIR\n"));
93 break;
94 }
95
96 /* New since protocol version 2 (VBox 5.0). */
97 case DragAndDropSvc::HOST_DND_HG_SND_FILE_HDR:
98 {
99 LogFlowFunc(("HOST_DND_HG_SND_FILE_HDR\n"));
100 break;
101 }
102
103 case DragAndDropSvc::HOST_DND_HG_SND_FILE_DATA:
104 {
105 LogFlowFunc(("HOST_DND_HG_SND_FILE\n"));
106
107 /* No parameter verification here as, depending on the protocol version
108 * being used, the parameter count + types might change. */
109 break;
110 }
111
112#ifdef VBOX_WITH_DRAG_AND_DROP_GH
113 case DragAndDropSvc::HOST_DND_GH_REQ_PENDING:
114 {
115 LogFlowFunc(("HOST_DND_GH_REQ_PENDING\n"));
116
117 /* Verify parameter count and types. */
118 if ( cParms != 1
119 || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* screen id */)
120 {
121 rc = VERR_INVALID_PARAMETER;
122 }
123 break;
124 }
125
126 case DragAndDropSvc::HOST_DND_GH_EVT_DROPPED:
127 {
128 LogFlowFunc(("HOST_DND_GH_EVT_DROPPED\n"));
129
130 /* Verify parameter count and types. */
131 if ( cParms != 3
132 || paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* format */
133 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* format size */
134 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* action */)
135 {
136 rc = VERR_INVALID_PARAMETER;
137 }
138 break;
139 }
140#endif /* VBOX_WITH_DRAG_AND_DROP_GH */
141
142 default:
143 rc = VERR_NOT_IMPLEMENTED;
144 break;
145 }
146
147 if (!pMessage) /* Generic message needed? */
148 pMessage = new DnDGenericMessage(uMsg, cParms, paParms);
149
150 if (fAppend)
151 m_dndMessageQueue.append(pMessage);
152 else
153 m_dndMessageQueue.prepend(pMessage);
154 }
155 catch(std::bad_alloc &)
156 {
157 rc = VERR_NO_MEMORY;
158 }
159
160 return rc;
161}
162
163HGCM::Message* DnDManager::nextHGCMMessage(void)
164{
165 if (m_pCurMsg)
166 return m_pCurMsg->nextHGCMMessage();
167
168 if (m_dndMessageQueue.isEmpty())
169 return NULL;
170
171 return m_dndMessageQueue.first()->nextHGCMMessage();
172}
173
174int DnDManager::nextMessageInfo(uint32_t *puMsg, uint32_t *pcParms)
175{
176 AssertPtrReturn(puMsg, VERR_INVALID_POINTER);
177 AssertPtrReturn(pcParms, VERR_INVALID_POINTER);
178
179 int rc;
180 if (m_pCurMsg)
181 rc = m_pCurMsg->currentMessageInfo(puMsg, pcParms);
182 else
183 {
184 if (m_dndMessageQueue.isEmpty())
185 rc = VERR_NO_DATA;
186 else
187 rc = m_dndMessageQueue.first()->currentMessageInfo(puMsg, pcParms);
188 }
189
190 LogFlowFunc(("Returning puMsg=%RU32, pcParms=%RU32, rc=%Rrc\n", *puMsg, *pcParms, rc));
191 return rc;
192}
193
194int DnDManager::nextMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
195{
196 LogFlowFunc(("uMsg=%RU32, cParms=%RU32\n", uMsg, cParms));
197
198 if (!m_pCurMsg)
199 {
200 /* Check for pending messages in our queue. */
201 if (m_dndMessageQueue.isEmpty())
202 return VERR_NO_DATA;
203
204 m_pCurMsg = m_dndMessageQueue.first();
205 AssertPtr(m_pCurMsg);
206 m_dndMessageQueue.removeFirst();
207 }
208
209 /* Fetch the current message info */
210 int rc = m_pCurMsg->currentMessage(uMsg, cParms, paParms);
211 /* If this message doesn't provide any additional sub messages, clear it. */
212 if (!m_pCurMsg->isMessageWaiting())
213 {
214 delete m_pCurMsg;
215 m_pCurMsg = NULL;
216 }
217
218 /*
219 * If there was an error handling the current message or the user has canceled
220 * the operation, we need to cleanup all pending events and inform the progress
221 * callback about our exit.
222 */
223 if (RT_FAILURE(rc))
224 {
225 /* Clear any pending messages. */
226 clear();
227
228 /* Create a new cancel message to inform the guest + call
229 * the host whether the current transfer was canceled or aborted
230 * due to an error. */
231 try
232 {
233 if (rc == VERR_CANCELLED)
234 LogFlowFunc(("Operation was cancelled\n"));
235
236 Assert(!m_pCurMsg);
237 m_pCurMsg = new DnDHGCancelMessage();
238
239 if (m_pfnProgressCallback)
240 {
241 LogFlowFunc(("Notifying host about aborting operation (%Rrc) ...\n", rc));
242 m_pfnProgressCallback( rc == VERR_CANCELLED
243 ? DragAndDropSvc::DND_PROGRESS_CANCELLED
244 : DragAndDropSvc::DND_PROGRESS_ERROR,
245 100 /* Percent */, rc,
246 m_pvProgressUser);
247 }
248 }
249 catch(std::bad_alloc &)
250 {
251 rc = VERR_NO_MEMORY;
252 }
253 }
254
255 LogFlowFunc(("Message processed with rc=%Rrc\n", rc));
256 return rc;
257}
258
259void DnDManager::clear(void)
260{
261 if (m_pCurMsg)
262 {
263 delete m_pCurMsg;
264 m_pCurMsg = NULL;
265 }
266
267 while (!m_dndMessageQueue.isEmpty())
268 {
269 delete m_dndMessageQueue.last();
270 m_dndMessageQueue.removeLast();
271 }
272}
273
274/**
275 * Triggers a rescheduling of the manager's message queue by setting the first
276 * message available in the queue as the current one to process.
277 *
278 * @return IPRT status code. VERR_NO_DATA if not message to process is available at
279 * the time of calling.
280 */
281int DnDManager::doReschedule(void)
282{
283 LogFlowFunc(("Rescheduling ...\n"));
284
285 if (!m_dndMessageQueue.isEmpty())
286 {
287 m_pCurMsg = m_dndMessageQueue.first();
288 m_dndMessageQueue.removeFirst();
289
290 return VINF_SUCCESS;
291 }
292
293 return VERR_NO_DATA;
294}
295
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