VirtualBox

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

Last change on this file was 98103, checked in by vboxsync, 17 months ago

Copyright year updates by scm.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use