VirtualBox

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

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

DnD: SCM build fixes.

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