VirtualBox

source: vbox/trunk/src/VBox/Additions/common/VBoxGuestLib/HGCMInternal.cpp@ 3097

Last change on this file since 3097 was 3097, checked in by vboxsync, 17 years ago

prevent warnings if compiled as C files (Linux guest modules)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.3 KB
Line 
1/** @file
2 *
3 * VBoxGuestLib - A support library for VirtualBox guest additions:
4 * Host-Guest Communication Manager internal functions, implemented by VBoxGuest
5 */
6
7/*
8 * Copyright (C) 2006-2007 innotek GmbH
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License as published by the Free Software Foundation,
14 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
15 * distribution. VirtualBox OSE is distributed in the hope that it will
16 * be useful, but WITHOUT ANY WARRANTY of any kind.
17 *
18 * If you received this file as part of a commercial VirtualBox
19 * distribution, then only the terms of your commercial VirtualBox
20 * license agreement apply instead of the previous paragraph.
21 */
22
23/* Entire file is ifdef'ed with VBGL_VBOXGUEST */
24#ifdef VBGL_VBOXGUEST
25
26#include <VBox/VBoxGuestLib.h>
27#include "VBGLInternal.h"
28#include <iprt/string.h>
29#include <iprt/assert.h>
30#include <iprt/alloca.h>
31
32/* These functions can be only used by VBoxGuest. */
33
34DECLVBGL(int) VbglHGCMConnect (VBoxGuestHGCMConnectInfo *pConnectInfo,
35 VBGLHGCMCALLBACK *pAsyncCallback, void *pvAsyncData,
36 uint32_t u32AsyncData)
37{
38 VMMDevHGCMConnect *pHGCMConnect;
39 int rc;
40
41 if (!pConnectInfo || !pAsyncCallback)
42 return VERR_INVALID_PARAMETER;
43
44 pHGCMConnect = NULL;
45
46 /* Allocate request */
47 rc = VbglGRAlloc ((VMMDevRequestHeader **)&pHGCMConnect, sizeof (VMMDevHGCMConnect), VMMDevReq_HGCMConnect);
48
49 if (VBOX_SUCCESS(rc))
50 {
51 /* Initialize request memory */
52 pHGCMConnect->header.fu32Flags = 0;
53
54 memcpy (&pHGCMConnect->loc, &pConnectInfo->Loc, sizeof (HGCMServiceLocation));
55 pHGCMConnect->u32ClientID = 0;
56
57 /* Issue request */
58 rc = VbglGRPerform (&pHGCMConnect->header.header);
59
60 if (VBOX_SUCCESS(rc))
61 {
62 /* Check if host decides to process the request asynchronously. */
63 if (rc == VINF_HGCM_ASYNC_EXECUTE)
64 {
65 /* Wait for request completion interrupt notification from host */
66 pAsyncCallback (&pHGCMConnect->header, pvAsyncData, u32AsyncData);
67 }
68
69 pConnectInfo->result = pHGCMConnect->header.result;
70
71 if (VBOX_SUCCESS (pConnectInfo->result))
72 pConnectInfo->u32ClientID = pHGCMConnect->u32ClientID;
73 }
74
75 VbglGRFree (&pHGCMConnect->header.header);
76 }
77
78 return rc;
79}
80
81
82DECLVBGL(int) VbglHGCMDisconnect (VBoxGuestHGCMDisconnectInfo *pDisconnectInfo,
83 VBGLHGCMCALLBACK *pAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData)
84{
85 VMMDevHGCMDisconnect *pHGCMDisconnect;
86 int rc;
87
88 if (!pDisconnectInfo || !pAsyncCallback)
89 return VERR_INVALID_PARAMETER;
90
91 pHGCMDisconnect = NULL;
92
93 /* Allocate request */
94 rc = VbglGRAlloc ((VMMDevRequestHeader **)&pHGCMDisconnect, sizeof (VMMDevHGCMDisconnect), VMMDevReq_HGCMDisconnect);
95
96 if (VBOX_SUCCESS(rc))
97 {
98 /* Initialize request memory */
99 pHGCMDisconnect->header.fu32Flags = 0;
100
101 pHGCMDisconnect->u32ClientID = pDisconnectInfo->u32ClientID;
102
103 /* Issue request */
104 rc = VbglGRPerform (&pHGCMDisconnect->header.header);
105
106 if (VBOX_SUCCESS(rc))
107 {
108 /* Check if host decides to process the request asynchronously. */
109 if (rc == VINF_HGCM_ASYNC_EXECUTE)
110 {
111 /* Wait for request completion interrupt notification from host */
112 pAsyncCallback (&pHGCMDisconnect->header, pvAsyncData, u32AsyncData);
113 }
114
115 pDisconnectInfo->result = pHGCMDisconnect->header.result;
116 }
117
118 VbglGRFree (&pHGCMDisconnect->header.header);
119 }
120
121 return rc;
122}
123
124
125DECLVBGL(int) VbglHGCMCall (VBoxGuestHGCMCallInfo *pCallInfo,
126 VBGLHGCMCALLBACK *pAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData)
127{
128 VMMDevHGCMCall *pHGCMCall;
129 uint32_t cbParms;
130 int rc;
131
132 if (!pCallInfo || !pAsyncCallback || pCallInfo->cParms > VBOX_HGCM_MAX_PARMS)
133 return VERR_INVALID_PARAMETER;
134
135 dprintf (("VbglHGCMCall: pCallInfo->cParms = %d, pHGCMCall->u32Function = %d\n", pCallInfo->cParms, pCallInfo->u32Function));
136
137 pHGCMCall = NULL;
138
139 cbParms = pCallInfo->cParms * sizeof (HGCMFunctionParameter);
140
141 /* Allocate request */
142 rc = VbglGRAlloc ((VMMDevRequestHeader **)&pHGCMCall, sizeof (VMMDevHGCMCall) + cbParms, VMMDevReq_HGCMCall);
143
144 dprintf (("VbglHGCMCall Allocated gr %p, rc = %Vrc, cbParms = %d\n", pHGCMCall, rc, cbParms));
145
146 if (VBOX_SUCCESS(rc))
147 {
148 void **papvCtx = NULL;
149
150 /* Initialize request memory */
151 pHGCMCall->header.fu32Flags = 0;
152 pHGCMCall->header.result = VINF_SUCCESS;
153
154 pHGCMCall->u32ClientID = pCallInfo->u32ClientID;
155 pHGCMCall->u32Function = pCallInfo->u32Function;
156 pHGCMCall->cParms = pCallInfo->cParms;
157
158 if (cbParms)
159 {
160 HGCMFunctionParameter *pParm;
161
162 memcpy (VMMDEV_HGCM_CALL_PARMS(pHGCMCall), VBOXGUEST_HGCM_CALL_PARMS(pCallInfo), cbParms);
163
164 /* Lock user buffers. */
165 if (pCallInfo->cParms > 0)
166 {
167 papvCtx = (void **)alloca(pCallInfo->cParms * sizeof (papvCtx[0]));
168 memset (papvCtx, 0, pCallInfo->cParms * sizeof (papvCtx[0]));
169 }
170
171 pParm = VBOXGUEST_HGCM_CALL_PARMS(pCallInfo);
172 unsigned iParm = 0;
173 for (; iParm < pCallInfo->cParms; iParm++, pParm++)
174 {
175 if ( pParm->type == VMMDevHGCMParmType_LinAddr_In
176 || pParm->type == VMMDevHGCMParmType_LinAddr_Out
177 || pParm->type == VMMDevHGCMParmType_LinAddr)
178 {
179 rc = vbglLockLinear (&papvCtx[iParm], (void *)pParm->u.Pointer.u.linearAddr, pParm->u.Pointer.size);
180
181 if (VBOX_FAILURE (rc))
182 {
183 break;
184 }
185 }
186 }
187 }
188
189 /* Check that the parameter locking was ok. */
190 if (VBOX_SUCCESS(rc))
191 {
192 dprintf (("calling VbglGRPerform\n"));
193
194 /* Issue request */
195 rc = VbglGRPerform (&pHGCMCall->header.header);
196
197 dprintf (("VbglGRPerform rc = %Vrc (header rc=%d)\n", rc, pHGCMCall->header.result));
198
199 /** If the call failed, but as a result of the request itself, then pretend success
200 * Upper layers will interpret the result code in the packet.
201 */
202 if (VBOX_FAILURE(rc) && rc == pHGCMCall->header.result)
203 {
204 Assert(pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_DONE);
205 rc = VINF_SUCCESS;
206 }
207
208 if (VBOX_SUCCESS(rc))
209 {
210 /* Check if host decides to process the request asynchronously. */
211 if (rc == VINF_HGCM_ASYNC_EXECUTE)
212 {
213 /* Wait for request completion interrupt notification from host */
214 pAsyncCallback (&pHGCMCall->header, pvAsyncData, u32AsyncData);
215 }
216
217 if (pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_DONE)
218 {
219 if (cbParms)
220 {
221 memcpy (VBOXGUEST_HGCM_CALL_PARMS(pCallInfo), VMMDEV_HGCM_CALL_PARMS(pHGCMCall), cbParms);
222 }
223 pCallInfo->result = pHGCMCall->header.result;
224 }
225 else
226 {
227 /* The callback returns without completing the request,
228 * that means the wait was interrrupted. That can happen
229 * if system reboots or the VBoxService ended abnormally.
230 * In both cases it is OK to just leave the allocated memory
231 * in the physical heap. The memory leak does not affect normal
232 * operations.
233 * @todo VbglGRCancel (&pHGCMCall->header.header) need to be implemented.
234 * The host will not write to the cancelled memory.
235 */
236 pHGCMCall->header.fu32Flags |= VBOX_HGCM_REQ_CANCELLED;
237 }
238 }
239 }
240
241 /* Unlock user buffers. */
242 if (papvCtx != NULL)
243 {
244 HGCMFunctionParameter *pParm = VBOXGUEST_HGCM_CALL_PARMS(pCallInfo);
245
246 unsigned iParm = 0;
247 for (; iParm < pCallInfo->cParms; iParm++, pParm++)
248 {
249 if ( pParm->type == VMMDevHGCMParmType_LinAddr_In
250 || pParm->type == VMMDevHGCMParmType_LinAddr_Out
251 || pParm->type == VMMDevHGCMParmType_LinAddr)
252 {
253 if (papvCtx[iParm] != NULL)
254 {
255 vbglUnlockLinear (papvCtx[iParm], (void *)pParm->u.Pointer.u.linearAddr, pParm->u.Pointer.size);
256 }
257 }
258 }
259 }
260
261 if ((pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_CANCELLED) == 0)
262 VbglGRFree (&pHGCMCall->header.header);
263 else
264 rc = VERR_INTERRUPTED;
265 }
266
267 return rc;
268}
269
270#endif /* VBGL_VBOXGUEST */
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