VirtualBox

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

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