VirtualBox

source: vbox/trunk/src/VBox/Additions/common/VBoxGuestLib/SysHlp.cpp@ 15606

Last change on this file since 15606 was 15606, checked in by vboxsync, 16 years ago

Linux additions: recover the R0 hack which was removed in r39344 to make the shared folders work again

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.4 KB
Line 
1/** @file
2 *
3 * VBoxGuestLib - A support library for VirtualBox guest additions:
4 * Physical memory heap
5 */
6
7/*
8 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
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 (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 *
18 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
19 * Clara, CA 95054 USA or visit http://www.sun.com if you need
20 * additional information or have any questions.
21 */
22#define LOG_GROUP LOG_GROUP_HGCM
23#include <VBox/log.h>
24
25#include <VBox/VBoxGuestLib.h>
26#include "SysHlp.h"
27
28#include <iprt/assert.h>
29#if !defined(RT_OS_WINDOWS) && !defined(RT_OS_LINUX)
30#include <iprt/memobj.h>
31#endif
32
33
34int vbglLockLinear (void **ppvCtx, void *pv, uint32_t u32Size, bool fWriteAccess)
35{
36 int rc = VINF_SUCCESS;
37
38#ifdef RT_OS_WINDOWS
39 PMDL pMdl = IoAllocateMdl (pv, u32Size, FALSE, FALSE, NULL);
40
41 if (pMdl == NULL)
42 {
43 rc = VERR_NOT_SUPPORTED;
44 AssertMsgFailed(("IoAllocateMdl %p %x failed!!\n", pv, u32Size));
45 }
46 else
47 {
48 __try {
49 /* Calls to MmProbeAndLockPages must be enclosed in a try/except block. */
50 MmProbeAndLockPages (pMdl,
51 KernelMode,
52 (fWriteAccess) ? IoModifyAccess : IoReadAccess);
53
54 *ppvCtx = pMdl;
55
56 } __except(EXCEPTION_EXECUTE_HANDLER) {
57
58 IoFreeMdl (pMdl);
59 rc = VERR_INVALID_PARAMETER;
60 AssertMsgFailed(("MmProbeAndLockPages %p %x failed!!\n", pv, u32Size));
61 }
62 }
63
64#elif defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD)
65 /** @todo r=bird: I don't think FreeBSD shouldn't go here, solaris and OS/2 doesn't
66 * That said, the assumption below might be wrong for in kernel calls... */
67
68 /** @todo r=frank: Linux: pv is at least in some cases, e.g. with VBoxMapFolder,
69 * an R0 address -- the memory was allocated with kmalloc(). I don't know
70 * if this is true in any case. */
71 NOREF(ppvCtx);
72 NOREF(pv);
73 NOREF(u32Size);
74
75#else
76 /* Default to IPRT - this ASSUMES that it is USER addresses we're locking. */
77 RTR0MEMOBJ MemObj;
78 rc = RTR0MemObjLockUser(&MemObj, (RTR3PTR)pv, u32Size, NIL_RTR0PROCESS);
79 if (RT_SUCCESS(rc))
80 *ppvCtx = MemObj;
81 else
82 *ppvCtx = NIL_RTR0MEMOBJ;
83
84#endif
85
86 return rc;
87}
88
89void vbglUnlockLinear (void *pvCtx, void *pv, uint32_t u32Size)
90{
91 NOREF(pv);
92 NOREF(u32Size);
93
94#ifdef RT_OS_WINDOWS
95 PMDL pMdl = (PMDL)pvCtx;
96
97 Assert(pMdl);
98 if (pMdl != NULL)
99 {
100 MmUnlockPages (pMdl);
101 IoFreeMdl (pMdl);
102 }
103
104#elif defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD)
105 NOREF(pvCtx);
106
107#else
108 /* default to IPRT */
109 RTR0MEMOBJ MemObj = (RTR0MEMOBJ)pvCtx;
110 int rc = RTR0MemObjFree(MemObj, false);
111 AssertRC(rc);
112
113#endif
114}
115
116#ifndef VBGL_VBOXGUEST
117
118#if defined (RT_OS_LINUX) && !defined (__KERNEL__)
119# include <unistd.h>
120# include <errno.h>
121# include <sys/fcntl.h>
122# include <sys/ioctl.h>
123#endif
124
125#ifdef RT_OS_LINUX
126__BEGIN_DECLS
127extern DECLVBGL(void *) vboxadd_cmc_open (void);
128extern DECLVBGL(void) vboxadd_cmc_close (void *);
129extern DECLVBGL(int) vboxadd_cmc_call (void *opaque, uint32_t func, void *data);
130__END_DECLS
131#endif /* RT_OS_LINUX */
132
133#ifdef RT_OS_OS2
134__BEGIN_DECLS
135/*
136 * On OS/2 we'll do the connecting in the assembly code of the
137 * client driver, exporting a g_VBoxGuestIDC symbol containing
138 * the connection information obtained from the 16-bit IDC.
139 */
140extern VBOXGUESTOS2IDCCONNECT g_VBoxGuestIDC;
141__END_DECLS
142#endif
143
144#ifdef RT_OS_SOLARIS
145__BEGIN_DECLS
146extern DECLVBGL(void *) VBoxGuestSolarisServiceOpen (uint32_t *pu32Version);
147extern DECLVBGL(void) VBoxGuestSolarisServiceClose (void *pvOpaque);
148extern DECLVBGL(int) VBoxGuestSolarisServiceCall (void *pvOpaque, unsigned int iCmd, void *pvData, size_t cbSize, size_t *pcbReturn);
149__END_DECLS
150
151#elif defined (RT_OS_FREEBSD)
152__BEGIN_DECLS
153extern DECLVBGL(void *) VBoxGuestFreeBSDServiceOpen (uint32_t *pu32Version);
154extern DECLVBGL(void) VBoxGuestFreeBSDServiceClose (void *pvOpaque);
155extern DECLVBGL(int) VBoxGuestFreeBSDServiceCall (void *pvOpaque, unsigned int iCmd, void *pvData, size_t cbSize, size_t *pcbReturn);
156__END_DECLS
157
158#endif
159
160int vbglDriverOpen (VBGLDRIVER *pDriver)
161{
162#ifdef RT_OS_WINDOWS
163 UNICODE_STRING uszDeviceName;
164 RtlInitUnicodeString (&uszDeviceName, L"\\Device\\VBoxGuest");
165
166 PDEVICE_OBJECT pDeviceObject = NULL;
167 PFILE_OBJECT pFileObject = NULL;
168
169 NTSTATUS rc = IoGetDeviceObjectPointer (&uszDeviceName, FILE_ALL_ACCESS,
170 &pFileObject, &pDeviceObject);
171
172 if (NT_SUCCESS (rc))
173 {
174 Log(("vbglDriverOpen VBoxGuest successful pDeviceObject=%x\n", pDeviceObject));
175 pDriver->pDeviceObject = pDeviceObject;
176 pDriver->pFileObject = pFileObject;
177 return VINF_SUCCESS;
178 }
179 /** @todo return RTErrConvertFromNtStatus(rc)! */
180 Log(("vbglDriverOpen VBoxGuest failed with ntstatus=%x\n", rc));
181 return rc;
182
183#elif defined (RT_OS_LINUX)
184 void *opaque;
185
186 opaque = (void *) vboxadd_cmc_open ();
187 if (!opaque)
188 {
189 return VERR_NOT_IMPLEMENTED;
190 }
191 pDriver->opaque = opaque;
192 return VINF_SUCCESS;
193
194#elif defined (RT_OS_OS2)
195 /*
196 * Just check whether the connection was made or not.
197 */
198 if ( g_VBoxGuestIDC.u32Version == VMMDEV_VERSION
199 && VALID_PTR(g_VBoxGuestIDC.u32Session)
200 && VALID_PTR(g_VBoxGuestIDC.pfnServiceEP))
201 {
202 pDriver->u32Session = g_VBoxGuestIDC.u32Session;
203 return VINF_SUCCESS;
204 }
205 pDriver->u32Session = UINT32_MAX;
206 Log(("vbglDriverOpen: failed\n"));
207 return VERR_FILE_NOT_FOUND;
208
209#elif defined (RT_OS_SOLARIS)
210 uint32_t u32VMMDevVersion;
211 pDriver->pvOpaque = VBoxGuestSolarisServiceOpen(&u32VMMDevVersion);
212 if ( pDriver->pvOpaque
213 && u32VMMDevVersion == VMMDEV_VERSION)
214 return VINF_SUCCESS;
215
216 Log(("vbglDriverOpen: failed\n"));
217 return VERR_FILE_NOT_FOUND;
218
219#elif defined (RT_OS_FREEBSD)
220 uint32_t u32VMMDevVersion;
221 pDriver->pvOpaque = VBoxGuestFreeBSDServiceOpen(&u32VMMDevVersion);
222 if (pDriver->pvOpaque && (u32VMMDevVersion == VMMDEV_VERSION))
223 return VINF_SUCCESS;
224
225 Log(("vbglDriverOpen: failed\n"));
226 return VERR_FILE_NOT_FOUND;
227
228#else
229# error "Port me"
230#endif
231}
232
233#ifdef RT_OS_WINDOWS
234static NTSTATUS vbglDriverIOCtlCompletion (IN PDEVICE_OBJECT DeviceObject,
235 IN PIRP Irp,
236 IN PVOID Context)
237{
238 Log(("VBGL completion %x\n", Irp));
239
240 KEVENT *pEvent = (KEVENT *)Context;
241 KeSetEvent (pEvent, IO_NO_INCREMENT, FALSE);
242
243 return STATUS_MORE_PROCESSING_REQUIRED;
244}
245#endif
246
247int vbglDriverIOCtl (VBGLDRIVER *pDriver, uint32_t u32Function, void *pvData, uint32_t cbData)
248{
249 Log(("vbglDriverIOCtl: pDriver: %p, Func: %x, pvData: %p, cbData: %d\n", pDriver, u32Function, pvData, cbData));
250
251#ifdef RT_OS_WINDOWS
252 KEVENT Event;
253
254 KeInitializeEvent (&Event, NotificationEvent, FALSE);
255
256 /* Have to use the IoAllocateIRP method because this code is generic and
257 * must work in any thread context.
258 * The IoBuildDeviceIoControlRequest, which was used here, does not work
259 * when APCs are disabled, for example.
260 */
261 PIRP irp = IoAllocateIrp (pDriver->pDeviceObject->StackSize, FALSE);
262
263 Log(("vbglDriverIOCtl: irp %p, IRQL = %d\n", irp, KeGetCurrentIrql()));
264
265 if (irp == NULL)
266 {
267 Log(("vbglDriverIOCtl: IRP allocation failed!\n"));
268 return VERR_NO_MEMORY;
269 }
270
271 /*
272 * Setup the IRP_MJ_DEVICE_CONTROL IRP.
273 */
274
275 PIO_STACK_LOCATION nextStack = IoGetNextIrpStackLocation (irp);
276
277 nextStack->MajorFunction = IRP_MJ_DEVICE_CONTROL;
278 nextStack->MinorFunction = 0;
279 nextStack->DeviceObject = pDriver->pDeviceObject;
280 nextStack->Parameters.DeviceIoControl.OutputBufferLength = cbData;
281 nextStack->Parameters.DeviceIoControl.InputBufferLength = cbData;
282 nextStack->Parameters.DeviceIoControl.IoControlCode = u32Function;
283 nextStack->Parameters.DeviceIoControl.Type3InputBuffer = pvData;
284
285 irp->AssociatedIrp.SystemBuffer = pvData; /* Output buffer. */
286 irp->MdlAddress = NULL;
287
288 /* A completion routine is required to signal the Event. */
289 IoSetCompletionRoutine (irp, vbglDriverIOCtlCompletion, &Event, TRUE, TRUE, TRUE);
290
291 NTSTATUS rc = IoCallDriver (pDriver->pDeviceObject, irp);
292
293 if (NT_SUCCESS (rc))
294 {
295 /* Wait the event to be signalled by the completion routine. */
296 KeWaitForSingleObject (&Event,
297 Executive,
298 KernelMode,
299 FALSE,
300 NULL);
301
302 rc = irp->IoStatus.Status;
303
304 Log(("vbglDriverIOCtl: wait completed IRQL = %d\n", KeGetCurrentIrql()));
305 }
306
307 IoFreeIrp (irp);
308
309 if (rc != STATUS_SUCCESS)
310 Log(("vbglDriverIOCtl: ntstatus=%x\n", rc));
311
312 return NT_SUCCESS(rc)? VINF_SUCCESS: VERR_VBGL_IOCTL_FAILED;
313
314#elif defined (RT_OS_LINUX)
315 return vboxadd_cmc_call (pDriver->opaque, u32Function, pvData);
316
317#elif defined (RT_OS_OS2)
318 if ( pDriver->u32Session
319 && pDriver->u32Session == g_VBoxGuestIDC.u32Session)
320 return g_VBoxGuestIDC.pfnServiceEP(pDriver->u32Session, u32Function, pvData, cbData, NULL);
321
322 Log(("vbglDriverIOCtl: No connection\n"));
323 return VERR_WRONG_ORDER;
324
325#elif defined (RT_OS_SOLARIS)
326 return VBoxGuestSolarisServiceCall(pDriver->pvOpaque, u32Function, pvData, cbData, NULL);
327
328#elif defined (RT_OS_FREEBSD)
329 return VBoxGuestFreeBSDServiceCall(pDriver->pvOpaque, u32Function, pvData, cbData, NULL);
330
331#else
332# error "Port me"
333#endif
334}
335
336void vbglDriverClose (VBGLDRIVER *pDriver)
337{
338#ifdef RT_OS_WINDOWS
339 Log(("vbglDriverClose pDeviceObject=%x\n", pDriver->pDeviceObject));
340 ObDereferenceObject (pDriver->pFileObject);
341
342#elif defined (RT_OS_LINUX)
343 vboxadd_cmc_close (pDriver->opaque);
344
345#elif defined (RT_OS_OS2)
346 pDriver->u32Session = 0;
347
348#elif defined (RT_OS_SOLARIS)
349 VBoxGuestSolarisServiceClose (pDriver->pvOpaque);
350
351#elif defined (RT_OS_FREEBSD)
352 VBoxGuestFreeBSDServiceClose(pDriver->pvOpaque);
353
354#else
355# error "Port me"
356#endif
357}
358
359#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