VirtualBox

source: vbox/trunk/src/VBox/HostServices/common/message.cpp@ 74205

Last change on this file since 74205 was 74205, checked in by vboxsync, 6 years ago

DnD/HostService: Refactored out more code to the common client and message classes, added documentation (also about deferred client states).

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 9.1 KB
Line 
1/** @file
2 * Base class for wrapping HCGM messages.
3 */
4
5/*
6 * Copyright (C) 2018 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 *
16 * The contents of this file may alternatively be used under the terms
17 * of the Common Development and Distribution License Version 1.0
18 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
19 * VirtualBox OSE distribution, in which case the provisions of the
20 * CDDL are applicable instead of those of the GPL.
21 *
22 * You may elect to license modified versions of this file under the
23 * terms and conditions of either the GPL or the CDDL or both.
24 */
25
26#include <VBox/HostServices/Service.h>
27
28using namespace HGCM;
29
30Message::Message(void)
31 : m_uMsg(0)
32 , m_cParms(0)
33 , m_paParms(NULL) { }
34
35Message::Message(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM aParms[])
36 : m_uMsg(0)
37 , m_cParms(0)
38 , m_paParms(NULL)
39{
40 initData(uMsg, cParms, aParms);
41}
42
43Message::~Message(void)
44{
45 reset();
46}
47
48/**
49 * Resets the message by free'ing all allocated parameters and resetting the rest.
50 */
51void Message::reset(void)
52{
53 if (m_paParms)
54 {
55 for (uint32_t i = 0; i < m_cParms; ++i)
56 {
57 switch (m_paParms[i].type)
58 {
59 case VBOX_HGCM_SVC_PARM_PTR:
60 if (m_paParms[i].u.pointer.size)
61 RTMemFree(m_paParms[i].u.pointer.addr);
62 break;
63 }
64 }
65 RTMemFree(m_paParms);
66 m_paParms = 0;
67 }
68 m_cParms = 0;
69 m_uMsg = 0;
70}
71
72/**
73 * Returns the parameter count of this message.
74 *
75 * @returns Parameter count.
76 */
77uint32_t Message::GetParamCount(void) const
78{
79 return m_cParms;
80}
81
82/**
83 * Retrieves the raw HGCM parameter data
84 *
85 * @returns IPRT status code.
86 * @param uMsg Message type to retrieve the parameter data for. Needed for sanity.
87 * @param cParms Size (in parameters) of @a aParms array.
88 * @param aParms Where to store the HGCM parameter data.
89 */
90int Message::GetData(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM aParms[]) const
91{
92 if (m_uMsg != uMsg)
93 {
94 LogFlowFunc(("Stored message type (%RU32) does not match request (%RU32)\n", m_uMsg, uMsg));
95 return VERR_INVALID_PARAMETER;
96 }
97 if (m_cParms > cParms)
98 {
99 LogFlowFunc(("Stored parameter count (%RU32) exceeds request buffer (%RU32)\n", m_cParms, cParms));
100 return VERR_INVALID_PARAMETER;
101 }
102
103 return Message::CopyParms(&aParms[0], cParms, m_paParms, m_cParms, false /* fDeepCopy */);
104}
105
106/**
107 * Retrieves a specific parameter value as uint32_t.
108 *
109 * @returns IPRT status code.
110 * @param uParm Index of parameter to retrieve.
111 * @param pu32Info Where to store the parameter value.
112 */
113int Message::GetParmU32(uint32_t uParm, uint32_t *pu32Info) const
114{
115 AssertPtrNullReturn(pu32Info, VERR_INVALID_PARAMETER);
116 AssertReturn(uParm < m_cParms, VERR_INVALID_PARAMETER);
117 AssertReturn(m_paParms[uParm].type == VBOX_HGCM_SVC_PARM_32BIT, VERR_INVALID_PARAMETER);
118
119 *pu32Info = m_paParms[uParm].u.uint32;
120
121 return VINF_SUCCESS;
122}
123
124/**
125 * Retrieves a specific parameter value as uint64_t.
126 *
127 * @returns IPRT status code.
128 * @param uParm Index of parameter to retrieve.
129 * @param pu64Info Where to store the parameter value.
130 */
131int Message::GetParmU64(uint32_t uParm, uint64_t *pu64Info) const
132{
133 AssertPtrNullReturn(pu64Info, VERR_INVALID_PARAMETER);
134 AssertReturn(uParm < m_cParms, VERR_INVALID_PARAMETER);
135 AssertReturn(m_paParms[uParm].type == VBOX_HGCM_SVC_PARM_64BIT, VERR_INVALID_PARAMETER);
136
137 *pu64Info = m_paParms[uParm].u.uint64;
138
139 return VINF_SUCCESS;
140}
141
142/**
143 * Retrieves a specific parameter value as a data address + size.
144 *
145 * @returns IPRT status code.
146 * @param uParm Index of parameter to retrieve.
147 * @param ppvAddr Where to store the data address.
148 * @param pcbSize Where to store the data size (in bytes).
149 *
150 * @remarks Does not copy (store) the actual content of the pointer (deep copy).
151 */
152int Message::GetParmPtr(uint32_t uParm, void **ppvAddr, uint32_t *pcbSize) const
153{
154 AssertPtrNullReturn(ppvAddr, VERR_INVALID_PARAMETER);
155 AssertPtrNullReturn(pcbSize, VERR_INVALID_PARAMETER);
156 AssertReturn(uParm < m_cParms, VERR_INVALID_PARAMETER);
157 AssertReturn(m_paParms[uParm].type == VBOX_HGCM_SVC_PARM_PTR, VERR_INVALID_PARAMETER);
158
159 *ppvAddr = m_paParms[uParm].u.pointer.addr;
160 *pcbSize = m_paParms[uParm].u.pointer.size;
161
162 return VINF_SUCCESS;
163}
164
165/**
166 * Returns the type of this message.
167 *
168 * @returns Message type.
169 */
170uint32_t Message::GetType(void) const
171{
172 return m_uMsg;
173}
174
175/**
176 * Copies HGCM parameters from source to destination.
177 *
178 * @returns IPRT status code.
179 * @param paParmsDst Destination array to copy parameters to.
180 * @param cParmsDst Size (in parameters) of destination array.
181 * @param paParmsSrc Source array to copy parameters from.
182 * @param cParmsSrc Size (in parameters) of source array.
183 * @param fDeepCopy Whether to perform a deep copy of pointer parameters or not.
184 *
185 * @remark Static convenience function.
186 */
187/* static */
188int Message::CopyParms(PVBOXHGCMSVCPARM paParmsDst, uint32_t cParmsDst,
189 PVBOXHGCMSVCPARM paParmsSrc, uint32_t cParmsSrc,
190 bool fDeepCopy)
191{
192 AssertPtrReturn(paParmsSrc, VERR_INVALID_POINTER);
193 AssertPtrReturn(paParmsDst, VERR_INVALID_POINTER);
194
195 if (cParmsSrc > cParmsDst)
196 return VERR_BUFFER_OVERFLOW;
197
198 int rc = VINF_SUCCESS;
199 for (uint32_t i = 0; i < cParmsSrc; i++)
200 {
201 paParmsDst[i].type = paParmsSrc[i].type;
202 switch (paParmsSrc[i].type)
203 {
204 case VBOX_HGCM_SVC_PARM_32BIT:
205 {
206 paParmsDst[i].u.uint32 = paParmsSrc[i].u.uint32;
207 break;
208 }
209 case VBOX_HGCM_SVC_PARM_64BIT:
210 {
211 paParmsDst[i].u.uint64 = paParmsSrc[i].u.uint64;
212 break;
213 }
214 case VBOX_HGCM_SVC_PARM_PTR:
215 {
216 /* Do we have to perform a deep copy? */
217 if (fDeepCopy)
218 {
219 /* Yes, do so. */
220 paParmsDst[i].u.pointer.size = paParmsSrc[i].u.pointer.size;
221 if (paParmsDst[i].u.pointer.size > 0)
222 {
223 paParmsDst[i].u.pointer.addr = RTMemAlloc(paParmsDst[i].u.pointer.size);
224 if (!paParmsDst[i].u.pointer.addr)
225 {
226 rc = VERR_NO_MEMORY;
227 break;
228 }
229 }
230 }
231 else
232 {
233 /* No, but we have to check if there is enough room. */
234 if (paParmsDst[i].u.pointer.size < paParmsSrc[i].u.pointer.size)
235 {
236 rc = VERR_BUFFER_OVERFLOW;
237 break;
238 }
239 }
240
241 if (paParmsSrc[i].u.pointer.size)
242 {
243 if ( paParmsDst[i].u.pointer.addr
244 && paParmsDst[i].u.pointer.size)
245 {
246 memcpy(paParmsDst[i].u.pointer.addr,
247 paParmsSrc[i].u.pointer.addr,
248 RT_MIN(paParmsDst[i].u.pointer.size, paParmsSrc[i].u.pointer.size));
249 }
250 else
251 rc = VERR_INVALID_POINTER;
252 }
253 break;
254 }
255 default:
256 {
257 AssertMsgFailed(("Unknown HGCM type %u\n", paParmsSrc[i].type));
258 rc = VERR_INVALID_PARAMETER;
259 break;
260 }
261 }
262 if (RT_FAILURE(rc))
263 break;
264 }
265 return rc;
266}
267
268/**
269 * Initializes the message with a message type and parameters.
270 *
271 * @returns IPRT status code.
272 * @param uMsg Message type to set.
273 * @param cParms Number of parameters to set.
274 * @param aParms Array of parameters to set.
275 */
276int Message::initData(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM aParms[])
277{
278 AssertReturn(cParms < 256, VERR_INVALID_PARAMETER);
279 AssertPtrNullReturn(aParms, VERR_INVALID_PARAMETER);
280
281 /* Cleanup any eventual old stuff. */
282 reset();
283
284 m_uMsg = uMsg;
285 m_cParms = cParms;
286
287 int rc = VINF_SUCCESS;
288
289 if (cParms)
290 {
291 m_paParms = (VBOXHGCMSVCPARM*)RTMemAllocZ(sizeof(VBOXHGCMSVCPARM) * m_cParms);
292 if (m_paParms)
293 {
294 rc = Message::CopyParms(m_paParms, m_cParms, &aParms[0], cParms, true /* fDeepCopy */);
295 if (RT_FAILURE(rc))
296 reset();
297 }
298 else
299 rc = VERR_NO_MEMORY;
300 }
301
302 return rc;
303}
304
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