VirtualBox

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

Last change on this file since 96407 was 96407, checked in by vboxsync, 2 years ago

scm copyright and license note update

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.9 KB
Line 
1/* $Id: message.cpp 96407 2022-08-22 17:43:14Z vboxsync $ */
2/** @file
3 * Base class for wrapping HCGM messages.
4 */
5
6/*
7 * Copyright (C) 2018-2022 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
30using namespace HGCM;
31
32Message::Message(void)
33 : m_uMsg(0)
34 , m_cParms(0)
35 , m_paParms(NULL)
36{
37}
38
39Message::Message(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM aParms[])
40 : m_uMsg(0)
41 , m_cParms(0)
42 , m_paParms(NULL)
43{
44 initData(uMsg, cParms, aParms);
45}
46
47Message::~Message(void)
48{
49 reset();
50}
51
52/**
53 * Resets the message by free'ing all allocated parameters and resetting the rest.
54 */
55void Message::reset(void) RT_NOEXCEPT
56{
57 if (m_paParms)
58 {
59 for (uint32_t i = 0; i < m_cParms; ++i)
60 {
61 switch (m_paParms[i].type)
62 {
63 case VBOX_HGCM_SVC_PARM_PTR:
64 if (m_paParms[i].u.pointer.size)
65 RTMemFree(m_paParms[i].u.pointer.addr);
66 break;
67 }
68 }
69 RTMemFree(m_paParms);
70 m_paParms = 0;
71 }
72 m_cParms = 0;
73 m_uMsg = 0;
74}
75
76/**
77 * Returns the parameter count of this message.
78 *
79 * @returns Parameter count.
80 */
81uint32_t Message::GetParamCount(void) const RT_NOEXCEPT
82{
83 return m_cParms;
84}
85
86/**
87 * Retrieves the raw HGCM parameter data
88 *
89 * @returns IPRT status code.
90 * @param uMsg Message type to retrieve the parameter data for. Needed for sanity.
91 * @param cParms Size (in parameters) of @a aParms array.
92 * @param aParms Where to store the HGCM parameter data.
93 */
94int Message::GetData(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM aParms[]) const RT_NOEXCEPT
95{
96 if (m_uMsg != uMsg)
97 {
98 LogFlowFunc(("Stored message type (%RU32) does not match request (%RU32)\n", m_uMsg, uMsg));
99 return VERR_INVALID_PARAMETER;
100 }
101 if (m_cParms > cParms)
102 {
103 LogFlowFunc(("Stored parameter count (%RU32) exceeds request buffer (%RU32)\n", m_cParms, cParms));
104 return VERR_INVALID_PARAMETER;
105 }
106
107 return Message::CopyParms(&aParms[0], cParms, m_paParms, m_cParms, false /* fDeepCopy */);
108}
109
110/**
111 * Retrieves a specific parameter value as uint32_t.
112 *
113 * @returns IPRT status code.
114 * @param uParm Index of parameter to retrieve.
115 * @param pu32Info Where to store the parameter value.
116 */
117int Message::GetParmU32(uint32_t uParm, uint32_t *pu32Info) const RT_NOEXCEPT
118{
119 AssertPtrReturn(pu32Info, VERR_INVALID_PARAMETER);
120 AssertReturn(uParm < m_cParms, VERR_INVALID_PARAMETER);
121 AssertReturn(m_paParms[uParm].type == VBOX_HGCM_SVC_PARM_32BIT, VERR_INVALID_PARAMETER);
122
123 *pu32Info = m_paParms[uParm].u.uint32;
124
125 return VINF_SUCCESS;
126}
127
128/**
129 * Retrieves a specific parameter value as uint64_t.
130 *
131 * @returns IPRT status code.
132 * @param uParm Index of parameter to retrieve.
133 * @param pu64Info Where to store the parameter value.
134 */
135int Message::GetParmU64(uint32_t uParm, uint64_t *pu64Info) const RT_NOEXCEPT
136{
137 AssertPtrReturn(pu64Info, VERR_INVALID_PARAMETER);
138 AssertReturn(uParm < m_cParms, VERR_INVALID_PARAMETER);
139 AssertReturn(m_paParms[uParm].type == VBOX_HGCM_SVC_PARM_64BIT, VERR_INVALID_PARAMETER);
140
141 *pu64Info = m_paParms[uParm].u.uint64;
142
143 return VINF_SUCCESS;
144}
145
146/**
147 * Retrieves a specific parameter value as a data address + size.
148 *
149 * @returns IPRT status code.
150 * @param uParm Index of parameter to retrieve.
151 * @param ppvAddr Where to store the data address.
152 * @param pcbSize Where to store the data size (in bytes).
153 *
154 * @remarks Does not copy (store) the actual content of the pointer (deep copy).
155 */
156int Message::GetParmPtr(uint32_t uParm, void **ppvAddr, uint32_t *pcbSize) const RT_NOEXCEPT
157{
158 AssertPtrReturn(ppvAddr, VERR_INVALID_PARAMETER);
159 AssertPtrReturn(pcbSize, VERR_INVALID_PARAMETER);
160 AssertReturn(uParm < m_cParms, VERR_INVALID_PARAMETER);
161 AssertReturn(m_paParms[uParm].type == VBOX_HGCM_SVC_PARM_PTR, VERR_INVALID_PARAMETER);
162
163 *ppvAddr = m_paParms[uParm].u.pointer.addr;
164 *pcbSize = m_paParms[uParm].u.pointer.size;
165
166 return VINF_SUCCESS;
167}
168
169/**
170 * Returns the type of this message.
171 *
172 * @returns Message type.
173 */
174uint32_t Message::GetType(void) const RT_NOEXCEPT
175{
176 return m_uMsg;
177}
178
179/**
180 * Copies HGCM parameters from source to destination.
181 *
182 * @returns IPRT status code.
183 * @param paParmsDst Destination array to copy parameters to.
184 * @param cParmsDst Size (in parameters) of destination array.
185 * @param paParmsSrc Source array to copy parameters from.
186 * @param cParmsSrc Size (in parameters) of source array.
187 * @param fDeepCopy Whether to perform a deep copy of pointer parameters or not.
188 *
189 * @remark Static convenience function.
190 */
191/* static */
192int Message::CopyParms(PVBOXHGCMSVCPARM paParmsDst, uint32_t cParmsDst,
193 PVBOXHGCMSVCPARM paParmsSrc, uint32_t cParmsSrc,
194 bool fDeepCopy) RT_NOEXCEPT
195{
196 AssertPtrReturn(paParmsSrc, VERR_INVALID_POINTER);
197 AssertPtrReturn(paParmsDst, VERR_INVALID_POINTER);
198
199 if (cParmsSrc > cParmsDst)
200 return VERR_BUFFER_OVERFLOW;
201
202 for (uint32_t i = 0; i < cParmsSrc; i++)
203 {
204 paParmsDst[i].type = paParmsSrc[i].type;
205 switch (paParmsSrc[i].type)
206 {
207 case VBOX_HGCM_SVC_PARM_32BIT:
208 {
209 paParmsDst[i].u.uint32 = paParmsSrc[i].u.uint32;
210 break;
211 }
212 case VBOX_HGCM_SVC_PARM_64BIT:
213 {
214 paParmsDst[i].u.uint64 = paParmsSrc[i].u.uint64;
215 break;
216 }
217 case VBOX_HGCM_SVC_PARM_PTR:
218 {
219 /* Do we have to perform a deep copy? */
220 if (fDeepCopy)
221 {
222 /* Yes, do so. */
223 paParmsDst[i].u.pointer.size = paParmsSrc[i].u.pointer.size;
224 if (paParmsDst[i].u.pointer.size > 0)
225 {
226 paParmsDst[i].u.pointer.addr = RTMemAlloc(paParmsDst[i].u.pointer.size);
227 if (!paParmsDst[i].u.pointer.addr)
228 return VERR_NO_MEMORY;
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 return VERR_BUFFER_OVERFLOW;
236 }
237
238 if (paParmsSrc[i].u.pointer.size)
239 {
240 if ( paParmsDst[i].u.pointer.addr
241 && paParmsDst[i].u.pointer.size)
242 memcpy(paParmsDst[i].u.pointer.addr,
243 paParmsSrc[i].u.pointer.addr,
244 RT_MIN(paParmsDst[i].u.pointer.size, paParmsSrc[i].u.pointer.size));
245 else
246 return VERR_INVALID_POINTER;
247 }
248 break;
249 }
250 default:
251 {
252 AssertMsgFailed(("Unknown HGCM type %u\n", paParmsSrc[i].type));
253 return VERR_INVALID_PARAMETER;
254 }
255 }
256 }
257 return VINF_SUCCESS;
258}
259
260/**
261 * Initializes the message with a message type and parameters.
262 *
263 * @returns IPRT status code.
264 * @param uMsg Message type to set.
265 * @param cParms Number of parameters to set.
266 * @param aParms Array of parameters to set.
267 */
268int Message::initData(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM aParms[]) RT_NOEXCEPT
269{
270 /** @todo r=bird: There is a define for the max number of HGCM parameters,
271 * it's way smaller than 256, something like 61 IIRC. */
272 AssertReturn(cParms < 256, VERR_INVALID_PARAMETER);
273 AssertPtrReturn(aParms, VERR_INVALID_PARAMETER);
274
275 /* Cleanup any eventual old stuff. */
276 reset();
277
278 m_uMsg = uMsg;
279 m_cParms = cParms;
280
281 int rc = VINF_SUCCESS;
282
283 if (cParms)
284 {
285 m_paParms = (VBOXHGCMSVCPARM*)RTMemAllocZ(sizeof(VBOXHGCMSVCPARM) * m_cParms);
286 if (m_paParms)
287 {
288 rc = Message::CopyParms(m_paParms, m_cParms, &aParms[0], cParms, true /* fDeepCopy */);
289 if (RT_FAILURE(rc))
290 reset();
291 }
292 else
293 rc = VERR_NO_MEMORY;
294 }
295
296 return rc;
297}
298
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