VirtualBox

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

Last change on this file since 93622 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

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