VirtualBox

source: vbox/trunk/include/VBox/hgcmsvc.h@ 104508

Last change on this file since 104508 was 98279, checked in by vboxsync, 23 months ago

Main/src-client: Some more rc -> hrc/vrc stuff found by grep. A build fix. bugref:10223

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 26.4 KB
Line 
1/** @file
2 * Host-Guest Communication Manager (HGCM) - Service library definitions.
3 */
4
5/*
6 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
7 *
8 * This file is part of VirtualBox base platform packages, as
9 * available from https://www.virtualbox.org.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation, in version 3 of the
14 * License.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, see <https://www.gnu.org/licenses>.
23 *
24 * The contents of this file may alternatively be used under the terms
25 * of the Common Development and Distribution License Version 1.0
26 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
27 * in the VirtualBox distribution, in which case the provisions of the
28 * CDDL are applicable instead of those of the GPL.
29 *
30 * You may elect to license modified versions of this file under the
31 * terms and conditions of either the GPL or the CDDL or both.
32 *
33 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
34 */
35
36#ifndef VBOX_INCLUDED_hgcmsvc_h
37#define VBOX_INCLUDED_hgcmsvc_h
38#ifndef RT_WITHOUT_PRAGMA_ONCE
39# pragma once
40#endif
41
42#include <iprt/assert.h>
43#include <iprt/stdarg.h>
44#include <iprt/string.h>
45#include <VBox/cdefs.h>
46#include <VBox/types.h>
47#include <iprt/err.h>
48#ifdef IN_RING3
49# include <iprt/mem.h>
50# include <VBox/err.h>
51# include <VBox/vmm/stam.h>
52# include <VBox/vmm/dbgf.h>
53# include <VBox/vmm/ssm.h>
54#endif
55#ifdef VBOX_TEST_HGCM_PARMS
56# include <iprt/test.h>
57#endif
58
59/** @todo proper comments. */
60
61/**
62 * Service interface version.
63 *
64 * Includes layout of both VBOXHGCMSVCFNTABLE and VBOXHGCMSVCHELPERS.
65 *
66 * A service can work with these structures if major version
67 * is equal and minor version of service is <= version of the
68 * structures.
69 *
70 * For example when a new helper is added at the end of helpers
71 * structure, then the minor version will be increased. All older
72 * services still can work because they have their old helpers
73 * unchanged.
74 *
75 * Revision history.
76 * 1.1->2.1 Because the pfnConnect now also has the pvClient parameter.
77 * 2.1->2.2 Because pfnSaveState and pfnLoadState were added
78 * 2.2->3.1 Because pfnHostCall is now synchronous, returns rc, and parameters were changed
79 * 3.1->3.2 Because pfnRegisterExtension was added
80 * 3.2->3.3 Because pfnDisconnectClient helper was added
81 * 3.3->4.1 Because the pvService entry and parameter was added
82 * 4.1->4.2 Because the VBOX_HGCM_SVC_PARM_CALLBACK parameter type was added
83 * 4.2->5.1 Removed the VBOX_HGCM_SVC_PARM_CALLBACK parameter type, as
84 * this problem is already solved by service extension callbacks
85 * 5.1->6.1 Because pfnCall got a new parameter. Also new helpers. (VBox 6.0)
86 * 6.1->6.2 Because pfnCallComplete starts returning a status code (VBox 6.0).
87 * 6.2->6.3 Because pfnGetRequestor was added (VBox 6.0).
88 * 6.3->6.4 Because pfnConnect got an additional parameter (VBox 6.0).
89 * 6.4->6.5 Because pfnGetVMMDevSessionId was added pfnLoadState got the version
90 * parameter (VBox 6.0).
91 * 6.5->7.1 Because pfnNotify was added (VBox 6.0).
92 * 7.1->8.1 Because pfnCancelled & pfnIsCallCancelled were added (VBox 6.0).
93 * 8.1->9.1 Because pfnDisconnectClient was (temporarily) removed, and
94 * acMaxClients and acMaxCallsPerClient added (VBox 6.1.26).
95 * 9.1->10.1 Because pfnDisconnectClient was added back (VBox 6.1.28).
96 * 10.1->11.1 Because pVMM added to pfnSaveState & pfnLoadState (VBox 7.0).
97 */
98#define VBOX_HGCM_SVC_VERSION_MAJOR (0x000b)
99#define VBOX_HGCM_SVC_VERSION_MINOR (0x0001)
100#define VBOX_HGCM_SVC_VERSION ((VBOX_HGCM_SVC_VERSION_MAJOR << 16) + VBOX_HGCM_SVC_VERSION_MINOR)
101
102
103/** Typed pointer to distinguish a call to service. */
104struct VBOXHGCMCALLHANDLE_TYPEDEF;
105typedef struct VBOXHGCMCALLHANDLE_TYPEDEF *VBOXHGCMCALLHANDLE;
106
107/** Service helpers pointers table. */
108typedef struct VBOXHGCMSVCHELPERS
109{
110 /** The service has processed the Call request. */
111 DECLR3CALLBACKMEMBER(int, pfnCallComplete, (VBOXHGCMCALLHANDLE callHandle, int32_t vrc));
112
113 void *pvInstance;
114
115 /**
116 * The service disconnects the client.
117 *
118 * This can only be used during VBOXHGCMSVCFNTABLE::pfnConnect or
119 * VBOXHGCMSVCFNTABLE::pfnDisconnect and will fail if called out side that
120 * context. Using this on the new client during VBOXHGCMSVCFNTABLE::pfnConnect
121 * is not advisable, it would be better to just return a failure status for that
122 * and it will be done automatically. (It is not possible to call this method
123 * on a client passed to VBOXHGCMSVCFNTABLE::pfnDisconnect.)
124 *
125 * There will be no VBOXHGCMSVCFNTABLE::pfnDisconnect callback for a client
126 * disconnected in this manner.
127 *
128 * @returns VBox status code.
129 * @retval VERR_NOT_FOUND if the client ID was not found.
130 * @retval VERR_INVALID_CONTEXT if not called during connect or disconnect.
131 *
132 * @remarks Used by external parties, so don't remove just because we don't use
133 * it ourselves.
134 */
135 DECLR3CALLBACKMEMBER(int, pfnDisconnectClient, (void *pvInstance, uint32_t idClient));
136
137 /**
138 * Check if the @a callHandle is for a call restored and re-submitted from saved state.
139 *
140 * @returns true if restored, false if not.
141 * @param callHandle The call we're checking up on.
142 */
143 DECLR3CALLBACKMEMBER(bool, pfnIsCallRestored, (VBOXHGCMCALLHANDLE callHandle));
144
145 /**
146 * Check if the @a callHandle is for a cancelled call.
147 *
148 * @returns true if cancelled, false if not.
149 * @param callHandle The call we're checking up on.
150 */
151 DECLR3CALLBACKMEMBER(bool, pfnIsCallCancelled, (VBOXHGCMCALLHANDLE callHandle));
152
153 /** Access to STAMR3RegisterV. */
154 DECLR3CALLBACKMEMBER(int, pfnStamRegisterV,(void *pvInstance, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
155 STAMUNIT enmUnit, const char *pszDesc, const char *pszName, va_list va)
156 RT_IPRT_FORMAT_ATTR(7, 0));
157 /** Access to STAMR3DeregisterV. */
158 DECLR3CALLBACKMEMBER(int, pfnStamDeregisterV,(void *pvInstance, const char *pszPatFmt, va_list va) RT_IPRT_FORMAT_ATTR(2, 0));
159
160 /** Access to DBGFR3InfoRegisterExternal. */
161 DECLR3CALLBACKMEMBER(int, pfnInfoRegister,(void *pvInstance, const char *pszName, const char *pszDesc,
162 PFNDBGFHANDLEREXT pfnHandler, void *pvUser));
163 /** Access to DBGFR3InfoDeregisterExternal. */
164 DECLR3CALLBACKMEMBER(int, pfnInfoDeregister,(void *pvInstance, const char *pszName));
165
166 /**
167 * Retrieves the VMMDevRequestHeader::fRequestor value.
168 *
169 * @returns The field value, VMMDEV_REQUESTOR_LEGACY if not supported by the
170 * guest, VMMDEV_REQUESTOR_LOWEST if invalid call.
171 * @param hCall The call we're checking up on.
172 */
173 DECLR3CALLBACKMEMBER(uint32_t, pfnGetRequestor, (VBOXHGCMCALLHANDLE hCall));
174
175 /**
176 * Retrieves VMMDevState::idSession.
177 *
178 * @returns current VMMDev session ID value.
179 */
180 DECLR3CALLBACKMEMBER(uint64_t, pfnGetVMMDevSessionId, (void *pvInstance));
181
182} VBOXHGCMSVCHELPERS;
183
184typedef VBOXHGCMSVCHELPERS *PVBOXHGCMSVCHELPERS;
185
186#if defined(IN_RING3) || defined(IN_SLICKEDIT)
187
188/** Wrapper around STAMR3RegisterF. */
189DECLINLINE(int) RT_IPRT_FORMAT_ATTR(7, 8)
190HGCMSvcHlpStamRegister(PVBOXHGCMSVCHELPERS pHlp, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
191 STAMUNIT enmUnit, const char *pszDesc, const char *pszName, ...)
192{
193 int rc;
194 va_list va;
195 va_start(va, pszName);
196 rc = pHlp->pfnStamRegisterV(pHlp->pvInstance, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, va);
197 va_end(va);
198 return rc;
199}
200
201/** Wrapper around STAMR3RegisterV. */
202DECLINLINE(int) RT_IPRT_FORMAT_ATTR(7, 0)
203HGCMSvcHlpStamRegisterV(PVBOXHGCMSVCHELPERS pHlp, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
204 STAMUNIT enmUnit, const char *pszDesc, const char *pszName, va_list va)
205{
206 return pHlp->pfnStamRegisterV(pHlp->pvInstance, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, va);
207}
208
209/** Wrapper around STAMR3DeregisterF. */
210DECLINLINE(int) RT_IPRT_FORMAT_ATTR(2, 3) HGCMSvcHlpStamDeregister(PVBOXHGCMSVCHELPERS pHlp, const char *pszPatFmt, ...)
211{
212 int rc;
213 va_list va;
214 va_start(va, pszPatFmt);
215 rc = pHlp->pfnStamDeregisterV(pHlp->pvInstance, pszPatFmt, va);
216 va_end(va);
217 return rc;
218}
219
220/** Wrapper around STAMR3DeregisterV. */
221DECLINLINE(int) RT_IPRT_FORMAT_ATTR(2, 0) HGCMSvcHlpStamDeregisterV(PVBOXHGCMSVCHELPERS pHlp, const char *pszPatFmt, va_list va)
222{
223 return pHlp->pfnStamDeregisterV(pHlp->pvInstance, pszPatFmt, va);
224}
225
226/** Wrapper around DBGFR3InfoRegisterExternal. */
227DECLINLINE(int) HGCMSvcHlpInfoRegister(PVBOXHGCMSVCHELPERS pHlp, const char *pszName, const char *pszDesc,
228 PFNDBGFHANDLEREXT pfnHandler, void *pvUser)
229{
230 return pHlp->pfnInfoRegister(pHlp->pvInstance, pszName, pszDesc, pfnHandler, pvUser);
231}
232
233/** Wrapper around DBGFR3InfoDeregisterExternal. */
234DECLINLINE(int) HGCMSvcHlpInfoDeregister(PVBOXHGCMSVCHELPERS pHlp, const char *pszName)
235{
236 return pHlp->pfnInfoDeregister(pHlp->pvInstance, pszName);
237}
238
239#endif /* IN_RING3 */
240
241
242#define VBOX_HGCM_SVC_PARM_INVALID (0U)
243#define VBOX_HGCM_SVC_PARM_32BIT (1U)
244#define VBOX_HGCM_SVC_PARM_64BIT (2U)
245#define VBOX_HGCM_SVC_PARM_PTR (3U)
246#define VBOX_HGCM_SVC_PARM_PAGES (4U)
247
248/** VBOX_HGCM_SVC_PARM_PAGES specific data. */
249typedef struct VBOXHGCMSVCPARMPAGES
250{
251 uint32_t cb;
252 uint16_t cPages;
253 uint16_t u16Padding;
254 void **papvPages;
255} VBOXHGCMSVCPARMPAGES;
256typedef VBOXHGCMSVCPARMPAGES *PVBOXHGCMSVCPARMPAGES;
257
258typedef struct VBOXHGCMSVCPARM
259{
260 /** VBOX_HGCM_SVC_PARM_* values. */
261 uint32_t type;
262
263 union
264 {
265 uint32_t uint32;
266 uint64_t uint64;
267 struct
268 {
269 uint32_t size;
270 void *addr;
271 } pointer;
272 /** VBOX_HGCM_SVC_PARM_PAGES */
273 VBOXHGCMSVCPARMPAGES Pages;
274 } u;
275} VBOXHGCMSVCPARM;
276
277/** Extract an uint32_t value from an HGCM parameter structure. */
278DECLINLINE(int) HGCMSvcGetU32(VBOXHGCMSVCPARM *pParm, uint32_t *pu32)
279{
280 int rc = VINF_SUCCESS;
281 AssertPtrReturn(pParm, VERR_INVALID_POINTER);
282 AssertPtrReturn(pParm, VERR_INVALID_POINTER);
283 AssertPtrReturn(pu32, VERR_INVALID_POINTER);
284 if (pParm->type != VBOX_HGCM_SVC_PARM_32BIT)
285 rc = VERR_INVALID_PARAMETER;
286 if (RT_SUCCESS(rc))
287 *pu32 = pParm->u.uint32;
288 return rc;
289}
290
291/** Extract an uint64_t value from an HGCM parameter structure. */
292DECLINLINE(int) HGCMSvcGetU64(VBOXHGCMSVCPARM *pParm, uint64_t *pu64)
293{
294 int rc = VINF_SUCCESS;
295 AssertPtrReturn(pParm, VERR_INVALID_POINTER);
296 AssertPtrReturn(pParm, VERR_INVALID_POINTER);
297 AssertPtrReturn(pu64, VERR_INVALID_POINTER);
298 if (pParm->type != VBOX_HGCM_SVC_PARM_64BIT)
299 rc = VERR_INVALID_PARAMETER;
300 if (RT_SUCCESS(rc))
301 *pu64 = pParm->u.uint64;
302 return rc;
303}
304
305/** Extract an pointer value from an HGCM parameter structure. */
306DECLINLINE(int) HGCMSvcGetPv(VBOXHGCMSVCPARM *pParm, void **ppv, uint32_t *pcb)
307{
308 AssertPtrReturn(pParm, VERR_INVALID_POINTER);
309 AssertPtrReturn(ppv, VERR_INVALID_POINTER);
310 AssertPtrReturn(pcb, VERR_INVALID_POINTER);
311 if (pParm->type == VBOX_HGCM_SVC_PARM_PTR)
312 {
313 *ppv = pParm->u.pointer.addr;
314 *pcb = pParm->u.pointer.size;
315 return VINF_SUCCESS;
316 }
317
318 return VERR_INVALID_PARAMETER;
319}
320
321/** Extract a constant pointer value from an HGCM parameter structure. */
322DECLINLINE(int) HGCMSvcGetPcv(VBOXHGCMSVCPARM *pParm, const void **ppv, uint32_t *pcb)
323{
324 AssertPtrReturn(pParm, VERR_INVALID_POINTER);
325 AssertPtrReturn(ppv, VERR_INVALID_POINTER);
326 AssertPtrReturn(pcb, VERR_INVALID_POINTER);
327 if (pParm->type == VBOX_HGCM_SVC_PARM_PTR)
328 {
329 *ppv = (const void *)pParm->u.pointer.addr;
330 *pcb = pParm->u.pointer.size;
331 return VINF_SUCCESS;
332 }
333
334 return VERR_INVALID_PARAMETER;
335}
336
337/** Extract a valid pointer to a non-empty buffer from an HGCM parameter
338 * structure. */
339DECLINLINE(int) HGCMSvcGetBuf(VBOXHGCMSVCPARM *pParm, void **ppv, uint32_t *pcb)
340{
341 AssertPtrReturn(pParm, VERR_INVALID_POINTER);
342 AssertPtrReturn(ppv, VERR_INVALID_POINTER);
343 AssertPtrReturn(pcb, VERR_INVALID_POINTER);
344 if ( pParm->type == VBOX_HGCM_SVC_PARM_PTR
345 && RT_VALID_PTR(pParm->u.pointer.addr)
346 && pParm->u.pointer.size > 0)
347 {
348 *ppv = pParm->u.pointer.addr;
349 *pcb = pParm->u.pointer.size;
350 return VINF_SUCCESS;
351 }
352
353 return VERR_INVALID_PARAMETER;
354}
355
356/** Extract a valid pointer to a non-empty constant buffer from an HGCM
357 * parameter structure. */
358DECLINLINE(int) HGCMSvcGetCBuf(VBOXHGCMSVCPARM *pParm, const void **ppv, uint32_t *pcb)
359{
360 AssertPtrReturn(pParm, VERR_INVALID_POINTER);
361 AssertPtrReturn(ppv, VERR_INVALID_POINTER);
362 AssertPtrReturn(pcb, VERR_INVALID_POINTER);
363 if ( pParm->type == VBOX_HGCM_SVC_PARM_PTR
364 && RT_VALID_PTR(pParm->u.pointer.addr)
365 && pParm->u.pointer.size > 0)
366 {
367 *ppv = (const void *)pParm->u.pointer.addr;
368 *pcb = pParm->u.pointer.size;
369 return VINF_SUCCESS;
370 }
371
372 return VERR_INVALID_PARAMETER;
373}
374
375/** Extract a string value from an HGCM parameter structure. */
376DECLINLINE(int) HGCMSvcGetStr(VBOXHGCMSVCPARM *pParm, char **ppch, uint32_t *pcb)
377{
378 AssertPtrReturn(pParm, VERR_INVALID_POINTER);
379 AssertPtrReturn(ppch, VERR_INVALID_POINTER);
380 AssertPtrReturn(pcb, VERR_INVALID_POINTER);
381 if ( pParm->type == VBOX_HGCM_SVC_PARM_PTR
382 && RT_VALID_PTR(pParm->u.pointer.addr)
383 && pParm->u.pointer.size > 0)
384 {
385 int rc = RTStrValidateEncodingEx((char *)pParm->u.pointer.addr,
386 pParm->u.pointer.size,
387 RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED);
388 if (RT_FAILURE(rc))
389 return rc;
390 *ppch = (char *)pParm->u.pointer.addr;
391 *pcb = pParm->u.pointer.size;
392 return VINF_SUCCESS;
393 }
394
395 return VERR_INVALID_PARAMETER;
396}
397
398/** Extract a constant string value from an HGCM parameter structure. */
399DECLINLINE(int) HGCMSvcGetCStr(VBOXHGCMSVCPARM *pParm, const char **ppch, uint32_t *pcb)
400{
401 AssertPtrReturn(pParm, VERR_INVALID_POINTER);
402 AssertPtrReturn(ppch, VERR_INVALID_POINTER);
403 AssertPtrReturn(pcb, VERR_INVALID_POINTER);
404 if ( pParm->type == VBOX_HGCM_SVC_PARM_PTR
405 && RT_VALID_PTR(pParm->u.pointer.addr)
406 && pParm->u.pointer.size > 0)
407 {
408 int rc = RTStrValidateEncodingEx((char *)pParm->u.pointer.addr,
409 pParm->u.pointer.size,
410 RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED);
411 if (RT_FAILURE(rc))
412 return rc;
413 *ppch = (char *)pParm->u.pointer.addr;
414 *pcb = pParm->u.pointer.size;
415 return VINF_SUCCESS;
416 }
417
418 return VERR_INVALID_PARAMETER;
419}
420
421/** Extract a constant string value from an HGCM parameter structure. */
422DECLINLINE(int) HGCMSvcGetPsz(VBOXHGCMSVCPARM *pParm, const char **ppch, uint32_t *pcb)
423{
424 AssertPtrReturn(pParm, VERR_INVALID_POINTER);
425 AssertPtrReturn(ppch, VERR_INVALID_POINTER);
426 AssertPtrReturn(pcb, VERR_INVALID_POINTER);
427 if ( pParm->type == VBOX_HGCM_SVC_PARM_PTR
428 && RT_VALID_PTR(pParm->u.pointer.addr)
429 && pParm->u.pointer.size > 0)
430 {
431 int rc = RTStrValidateEncodingEx((const char *)pParm->u.pointer.addr,
432 pParm->u.pointer.size,
433 RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED);
434 if (RT_FAILURE(rc))
435 return rc;
436 *ppch = (const char *)pParm->u.pointer.addr;
437 *pcb = pParm->u.pointer.size;
438 return VINF_SUCCESS;
439 }
440
441 return VERR_INVALID_PARAMETER;
442}
443
444/** Set a uint32_t value to an HGCM parameter structure */
445DECLINLINE(void) HGCMSvcSetU32(VBOXHGCMSVCPARM *pParm, uint32_t u32)
446{
447 AssertPtr(pParm);
448 pParm->type = VBOX_HGCM_SVC_PARM_32BIT;
449 pParm->u.uint32 = u32;
450}
451
452/** Set a uint64_t value to an HGCM parameter structure */
453DECLINLINE(void) HGCMSvcSetU64(VBOXHGCMSVCPARM *pParm, uint64_t u64)
454{
455 AssertPtr(pParm);
456 pParm->type = VBOX_HGCM_SVC_PARM_64BIT;
457 pParm->u.uint64 = u64;
458}
459
460/** Set a pointer value to an HGCM parameter structure */
461DECLINLINE(void) HGCMSvcSetPv(VBOXHGCMSVCPARM *pParm, void *pv, uint32_t cb)
462{
463 AssertPtr(pParm);
464 pParm->type = VBOX_HGCM_SVC_PARM_PTR;
465 pParm->u.pointer.addr = pv;
466 pParm->u.pointer.size = cb;
467}
468
469/** Set a pointer value to an HGCM parameter structure */
470DECLINLINE(void) HGCMSvcSetStr(VBOXHGCMSVCPARM *pParm, const char *psz)
471{
472 AssertPtr(pParm);
473 pParm->type = VBOX_HGCM_SVC_PARM_PTR;
474 pParm->u.pointer.addr = (void *)psz;
475 pParm->u.pointer.size = (uint32_t)strlen(psz) + 1;
476}
477
478#ifdef __cplusplus
479# ifdef IPRT_INCLUDED_cpp_ministring_h
480/** Set a const string value to an HGCM parameter structure */
481DECLINLINE(void) HGCMSvcSetRTCStr(VBOXHGCMSVCPARM *pParm, const RTCString &rString)
482{
483 AssertPtr(pParm);
484 pParm->type = VBOX_HGCM_SVC_PARM_PTR;
485 pParm->u.pointer.addr = (void *)rString.c_str();
486 pParm->u.pointer.size = (uint32_t)rString.length() + 1;
487}
488# endif
489#endif
490
491#if defined(IN_RING3) && defined(VBOX_INCLUDED_vmm_vmmr3vtable_h)
492
493/**
494 * Puts (serializes) a VBOXHGCMSVCPARM struct into SSM.
495 *
496 * @returns VBox status code.
497 * @param pParm VBOXHGCMSVCPARM to serialize.
498 * @param pSSM SSM handle to serialize to.
499 * @param pVMM The VMM vtable.
500 */
501DECLINLINE(int) HGCMSvcSSMR3Put(VBOXHGCMSVCPARM *pParm, PSSMHANDLE pSSM, PCVMMR3VTABLE pVMM)
502{
503 int rc;
504
505 AssertPtrReturn(pParm, VERR_INVALID_POINTER);
506 AssertPtrReturn(pSSM, VERR_INVALID_POINTER);
507
508 rc = pVMM->pfnSSMR3PutU32(pSSM, sizeof(VBOXHGCMSVCPARM));
509 AssertRCReturn(rc, rc);
510 rc = pVMM->pfnSSMR3PutU32(pSSM, pParm->type);
511 AssertRCReturn(rc, rc);
512
513 switch (pParm->type)
514 {
515 case VBOX_HGCM_SVC_PARM_32BIT:
516 rc = pVMM->pfnSSMR3PutU32(pSSM, pParm->u.uint32);
517 break;
518 case VBOX_HGCM_SVC_PARM_64BIT:
519 rc = pVMM->pfnSSMR3PutU64(pSSM, pParm->u.uint64);
520 break;
521 case VBOX_HGCM_SVC_PARM_PTR:
522 rc = pVMM->pfnSSMR3PutU32(pSSM, pParm->u.pointer.size);
523 if (RT_SUCCESS(rc))
524 rc = pVMM->pfnSSMR3PutMem(pSSM, pParm->u.pointer.addr, pParm->u.pointer.size);
525 break;
526 default:
527 AssertMsgFailed(("Paramter type %RU32 not implemented yet\n", pParm->type));
528 rc = VERR_NOT_IMPLEMENTED;
529 break;
530 }
531
532 return rc;
533}
534
535/**
536 * Gets (loads) a VBOXHGCMSVCPARM struct from SSM.
537 *
538 * @returns VBox status code.
539 * @param pParm VBOXHGCMSVCPARM to load into. Must be zero'ed.
540 * @param pSSM SSM handle to load from.
541 * @param pVMM The VMM vtable.
542 */
543DECLINLINE(int) HGCMSvcSSMR3Get(VBOXHGCMSVCPARM *pParm, PSSMHANDLE pSSM, PCVMMR3VTABLE pVMM)
544{
545 uint32_t cbParm;
546 int rc;
547
548 AssertPtrReturn(pParm, VERR_INVALID_POINTER);
549 AssertPtrReturn(pSSM, VERR_INVALID_POINTER);
550
551 rc = pVMM->pfnSSMR3GetU32(pSSM, &cbParm);
552 AssertRCReturn(rc, rc);
553 AssertReturn(cbParm == sizeof(VBOXHGCMSVCPARM), VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
554
555 rc = pVMM->pfnSSMR3GetU32(pSSM, &pParm->type);
556 AssertRCReturn(rc, rc);
557
558 switch (pParm->type)
559 {
560 case VBOX_HGCM_SVC_PARM_32BIT:
561 {
562 rc = pVMM->pfnSSMR3GetU32(pSSM, &pParm->u.uint32);
563 AssertRCReturn(rc, rc);
564 break;
565 }
566
567 case VBOX_HGCM_SVC_PARM_64BIT:
568 {
569 rc = pVMM->pfnSSMR3GetU64(pSSM, &pParm->u.uint64);
570 AssertRCReturn(rc, rc);
571 break;
572 }
573
574 case VBOX_HGCM_SVC_PARM_PTR:
575 {
576 AssertMsgReturn(pParm->u.pointer.size == 0,
577 ("Pointer size parameter already in use (or not initialized)\n"), VERR_INVALID_PARAMETER);
578
579 rc = pVMM->pfnSSMR3GetU32(pSSM, &pParm->u.pointer.size);
580 AssertRCReturn(rc, rc);
581
582 AssertMsgReturn(pParm->u.pointer.addr == NULL,
583 ("Pointer parameter already in use (or not initialized)\n"), VERR_INVALID_PARAMETER);
584
585 pParm->u.pointer.addr = RTMemAlloc(pParm->u.pointer.size);
586 AssertPtrReturn(pParm->u.pointer.addr, VERR_NO_MEMORY);
587 rc = pVMM->pfnSSMR3GetMem(pSSM, pParm->u.pointer.addr, pParm->u.pointer.size);
588
589 AssertRCReturn(rc, rc);
590 break;
591 }
592
593 default:
594 AssertMsgFailedReturn(("Paramter type %RU32 not implemented yet\n", pParm->type),
595 VERR_NOT_IMPLEMENTED);
596 break;
597 }
598
599 return VINF_SUCCESS;
600}
601
602#endif /* IN_RING3 */
603
604typedef VBOXHGCMSVCPARM *PVBOXHGCMSVCPARM;
605
606
607/** Service specific extension callback.
608 * This callback is called by the service to perform service specific operation.
609 *
610 * @param pvExtension The extension pointer.
611 * @param u32Function What the callback is supposed to do.
612 * @param pvParm The function parameters.
613 * @param cbParms The size of the function parameters.
614 */
615typedef DECLCALLBACKTYPE(int, FNHGCMSVCEXT,(void *pvExtension, uint32_t u32Function, void *pvParm, uint32_t cbParms));
616typedef FNHGCMSVCEXT *PFNHGCMSVCEXT;
617
618/**
619 * Notification event.
620 */
621typedef enum HGCMNOTIFYEVENT
622{
623 HGCMNOTIFYEVENT_INVALID = 0,
624 HGCMNOTIFYEVENT_POWER_ON,
625 HGCMNOTIFYEVENT_RESUME,
626 HGCMNOTIFYEVENT_SUSPEND,
627 HGCMNOTIFYEVENT_RESET,
628 HGCMNOTIFYEVENT_POWER_OFF,
629 HGCMNOTIFYEVENT_END,
630 HGCMNOTIFYEVENT_32BIT_HACK = 0x7fffffff
631} HGCMNOTIFYEVENT;
632
633/** @name HGCM_CLIENT_CATEGORY_XXX - Client categories
634 * @{ */
635#define HGCM_CLIENT_CATEGORY_KERNEL 0 /**< Guest kernel mode and legacy client. */
636#define HGCM_CLIENT_CATEGORY_ROOT 1 /**< Guest root or admin client. */
637#define HGCM_CLIENT_CATEGORY_USER 2 /**< Regular guest user client. */
638#define HGCM_CLIENT_CATEGORY_MAX 3 /**< Max number of categories. */
639/** @} */
640
641
642/** The Service DLL entry points.
643 *
644 * HGCM will call the DLL "VBoxHGCMSvcLoad"
645 * function and the DLL must fill in the VBOXHGCMSVCFNTABLE
646 * with function pointers.
647 *
648 * @note The structure is used in separately compiled binaries so an explicit
649 * packing is required.
650 */
651typedef struct VBOXHGCMSVCFNTABLE
652{
653 /** @name Filled by HGCM
654 * @{ */
655
656 /** Size of the structure. */
657 uint32_t cbSize;
658
659 /** Version of the structure, including the helpers. (VBOX_HGCM_SVC_VERSION) */
660 uint32_t u32Version;
661
662 PVBOXHGCMSVCHELPERS pHelpers;
663 /** @} */
664
665 /** @name Filled in by the service.
666 * @{ */
667
668 /** Size of client information the service want to have. */
669 uint32_t cbClient;
670
671 /** The maximum number of clients per category. Leave entries as zero for defaults. */
672 uint32_t acMaxClients[HGCM_CLIENT_CATEGORY_MAX];
673 /** The maximum number of concurrent calls per client for each category.
674 * Leave entries as as zero for default. */
675 uint32_t acMaxCallsPerClient[HGCM_CLIENT_CATEGORY_MAX];
676 /** The HGCM_CLIENT_CATEGORY_XXX value for legacy clients.
677 * Defaults to HGCM_CLIENT_CATEGORY_KERNEL. */
678 uint32_t idxLegacyClientCategory;
679
680 /** Uninitialize service */
681 DECLR3CALLBACKMEMBER(int, pfnUnload, (void *pvService));
682
683 /** Inform the service about a client connection. */
684 DECLR3CALLBACKMEMBER(int, pfnConnect, (void *pvService, uint32_t u32ClientID, void *pvClient, uint32_t fRequestor, bool fRestoring));
685
686 /** Inform the service that the client wants to disconnect. */
687 DECLR3CALLBACKMEMBER(int, pfnDisconnect, (void *pvService, uint32_t u32ClientID, void *pvClient));
688
689 /** Service entry point.
690 * Return code is passed to pfnCallComplete callback.
691 */
692 DECLR3CALLBACKMEMBER(void, pfnCall, (void *pvService, VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID, void *pvClient,
693 uint32_t function, uint32_t cParms, VBOXHGCMSVCPARM paParms[], uint64_t tsArrival));
694 /** Informs the service that a call was cancelled by the guest (optional).
695 *
696 * This is called for guest calls, connect requests and disconnect requests.
697 * There is unfortunately no way of obtaining the call handle for a guest call
698 * or otherwise identify the request, so that's left to the service to figure
699 * out using VBOXHGCMSVCHELPERS::pfnIsCallCancelled. Because this is an
700 * asynchronous call, the service may have completed the request already.
701 */
702 DECLR3CALLBACKMEMBER(void, pfnCancelled, (void *pvService, uint32_t idClient, void *pvClient));
703
704 /** Host Service entry point meant for privileged features invisible to the guest.
705 * Return code is passed to pfnCallComplete callback.
706 */
707 DECLR3CALLBACKMEMBER(int, pfnHostCall, (void *pvService, uint32_t function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]));
708
709 /** Inform the service about a VM save operation. */
710 DECLR3CALLBACKMEMBER(int, pfnSaveState, (void *pvService, uint32_t u32ClientID, void *pvClient,
711 PSSMHANDLE pSSM, PCVMMR3VTABLE pVMM));
712
713 /** Inform the service about a VM load operation. */
714 DECLR3CALLBACKMEMBER(int, pfnLoadState, (void *pvService, uint32_t u32ClientID, void *pvClient,
715 PSSMHANDLE pSSM, PCVMMR3VTABLE pVMM, uint32_t uVersion));
716
717 /** Register a service extension callback. */
718 DECLR3CALLBACKMEMBER(int, pfnRegisterExtension, (void *pvService, PFNHGCMSVCEXT pfnExtension, void *pvExtension));
719
720 /** Notification (VM state). */
721 DECLR3CALLBACKMEMBER(void, pfnNotify, (void *pvService, HGCMNOTIFYEVENT enmEvent));
722
723 /** User/instance data pointer for the service. */
724 void *pvService;
725
726 /** @} */
727} VBOXHGCMSVCFNTABLE;
728
729
730/** @name HGCM saved state
731 * @note Need to be here so we can add saved to service which doesn't have it.
732 * @{ */
733/** HGCM saved state version. */
734#define HGCM_SAVED_STATE_VERSION 3
735/** HGCM saved state version w/o client state indicators. */
736#define HGCM_SAVED_STATE_VERSION_V2 2
737/** @} */
738
739
740/** Service initialization entry point. */
741typedef DECLCALLBACKTYPE(int, FNVBOXHGCMSVCLOAD,(VBOXHGCMSVCFNTABLE *ptable));
742typedef FNVBOXHGCMSVCLOAD *PFNVBOXHGCMSVCLOAD;
743#define VBOX_HGCM_SVCLOAD_NAME "VBoxHGCMSvcLoad"
744
745#endif /* !VBOX_INCLUDED_hgcmsvc_h */
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