VirtualBox

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

Last change on this file since 28501 was 26425, checked in by vboxsync, 15 years ago

alternative license for VBoxGuestLib is CDDL

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.0 KB
Line 
1/* $Revision: 26425 $ */
2/** @file
3 * VBoxGuestLibR0 - IDC with VBoxGuest and HGCM helpers.
4 */
5
6/*
7 * Copyright (C) 2006-2009 Sun Microsystems, Inc.
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 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 *
26 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
27 * Clara, CA 95054 USA or visit http://www.sun.com if you need
28 * additional information or have any questions.
29 */
30
31#define LOG_GROUP LOG_GROUP_HGCM
32#include <VBox/log.h>
33
34#include <VBox/VBoxGuestLib.h>
35#include "SysHlp.h"
36
37#include <iprt/assert.h>
38
39#ifdef VBGL_VBOXGUEST
40
41#if !defined (RT_OS_WINDOWS)
42# include <iprt/memobj.h>
43# include <iprt/mem.h>
44#endif
45
46
47/**
48 * Internal worker for locking a range of linear addresses.
49 *
50 * @returns VBox status code.
51 * @param ppvCtx Where to store context data.
52 * @param pv The start of the range.
53 * @param u32Size The size of the range.
54 * @param fWriteAccess Lock for read-write (true) or readonly (false).
55 * @param fFlags HGCM call flags, VBGLR0_HGCM_F_XXX.
56 */
57int vbglLockLinear (void **ppvCtx, void *pv, uint32_t u32Size, bool fWriteAccess, uint32_t fFlags)
58{
59 int rc = VINF_SUCCESS;
60
61 /* Zero size buffers shouldn't be locked. */
62 if (u32Size == 0)
63 {
64 Assert(pv == NULL);
65#ifdef RT_OS_WINDOWS
66 *ppvCtx = NULL;
67#else
68 *ppvCtx = NIL_RTR0MEMOBJ;
69#endif
70 return VINF_SUCCESS;
71 }
72
73 /** @todo just use IPRT here. the extra allocation shouldn't matter much...
74 * Then we can most all this up one level even. */
75#ifdef RT_OS_WINDOWS
76 PMDL pMdl = IoAllocateMdl (pv, u32Size, FALSE, FALSE, NULL);
77
78 if (pMdl == NULL)
79 {
80 rc = VERR_NOT_SUPPORTED;
81 AssertMsgFailed(("IoAllocateMdl %p %x failed!!\n", pv, u32Size));
82 }
83 else
84 {
85 __try {
86 /* Calls to MmProbeAndLockPages must be enclosed in a try/except block. */
87 MmProbeAndLockPages (pMdl,
88 /** @todo (fFlags & VBGLR0_HGCMCALL_F_MODE_MASK) == VBGLR0_HGCMCALL_F_USER? UserMode: KernelMode */
89 KernelMode,
90 (fWriteAccess) ? IoModifyAccess : IoReadAccess);
91
92 *ppvCtx = pMdl;
93
94 } __except(EXCEPTION_EXECUTE_HANDLER) {
95
96 IoFreeMdl (pMdl);
97 /** @todo */
98 rc = VERR_INVALID_PARAMETER;
99 AssertMsgFailed(("MmProbeAndLockPages %p %x failed!!\n", pv, u32Size));
100 }
101 }
102
103#else
104 /*
105 * Lock depending on context.
106 *
107 * Note: We will later use the memory object here to convert the HGCM
108 * linear buffer paramter into a physical page list. This is why
109 * we lock both kernel pages on all systems, even those where we
110 * know they aren't pagable.
111 */
112 RTR0MEMOBJ MemObj = NIL_RTR0MEMOBJ;
113 uint32_t fAccess = RTMEM_PROT_READ | (fWriteAccess ? RTMEM_PROT_WRITE : 0);
114 if ((fFlags & VBGLR0_HGCMCALL_F_MODE_MASK) == VBGLR0_HGCMCALL_F_USER)
115 rc = RTR0MemObjLockUser(&MemObj, (RTR3PTR)pv, u32Size, fAccess, NIL_RTR0PROCESS);
116 else
117 rc = RTR0MemObjLockKernel(&MemObj, pv, u32Size, fAccess);
118 if (RT_SUCCESS(rc))
119 *ppvCtx = MemObj;
120 else
121 *ppvCtx = NIL_RTR0MEMOBJ;
122
123#endif
124
125 return rc;
126}
127
128void vbglUnlockLinear (void *pvCtx, void *pv, uint32_t u32Size)
129{
130 NOREF(pv);
131 NOREF(u32Size);
132
133#ifdef RT_OS_WINDOWS
134 PMDL pMdl = (PMDL)pvCtx;
135
136 Assert(pMdl);
137 if (pMdl != NULL)
138 {
139 MmUnlockPages (pMdl);
140 IoFreeMdl (pMdl);
141 }
142
143#else
144 RTR0MEMOBJ MemObj = (RTR0MEMOBJ)pvCtx;
145 int rc = RTR0MemObjFree(MemObj, false);
146 AssertRC(rc);
147
148#endif
149}
150
151#else /* !VBGL_VBOXGUEST */
152
153# ifdef RT_OS_OS2
154# include <VBox/VBoxGuest.h> /* for VBOXGUESTOS2IDCCONNECT */
155RT_C_DECLS_BEGIN
156/*
157 * On OS/2 we'll do the connecting in the assembly code of the
158 * client driver, exporting a g_VBoxGuestIDC symbol containing
159 * the connection information obtained from the 16-bit IDC.
160 */
161extern VBOXGUESTOS2IDCCONNECT g_VBoxGuestIDC;
162RT_C_DECLS_END
163# endif
164
165# if !defined(RT_OS_OS2) \
166 && !defined(RT_OS_WINDOWS)
167RT_C_DECLS_BEGIN
168extern DECLVBGL(void *) VBoxGuestIDCOpen (uint32_t *pu32Version);
169extern DECLVBGL(void) VBoxGuestIDCClose (void *pvOpaque);
170extern DECLVBGL(int) VBoxGuestIDCCall (void *pvOpaque, unsigned int iCmd, void *pvData, size_t cbSize, size_t *pcbReturn);
171RT_C_DECLS_END
172# endif
173
174int vbglDriverOpen (VBGLDRIVER *pDriver)
175{
176# ifdef RT_OS_WINDOWS
177 UNICODE_STRING uszDeviceName;
178 RtlInitUnicodeString (&uszDeviceName, L"\\Device\\VBoxGuest");
179
180 PDEVICE_OBJECT pDeviceObject = NULL;
181 PFILE_OBJECT pFileObject = NULL;
182
183 NTSTATUS rc = IoGetDeviceObjectPointer (&uszDeviceName, FILE_ALL_ACCESS,
184 &pFileObject, &pDeviceObject);
185
186 if (NT_SUCCESS (rc))
187 {
188 Log(("vbglDriverOpen VBoxGuest successful pDeviceObject=%x\n", pDeviceObject));
189 pDriver->pDeviceObject = pDeviceObject;
190 pDriver->pFileObject = pFileObject;
191 return VINF_SUCCESS;
192 }
193 /** @todo return RTErrConvertFromNtStatus(rc)! */
194 Log(("vbglDriverOpen VBoxGuest failed with ntstatus=%x\n", rc));
195 return rc;
196
197# elif defined (RT_OS_OS2)
198 /*
199 * Just check whether the connection was made or not.
200 */
201 if ( g_VBoxGuestIDC.u32Version == VMMDEV_VERSION
202 && VALID_PTR(g_VBoxGuestIDC.u32Session)
203 && VALID_PTR(g_VBoxGuestIDC.pfnServiceEP))
204 {
205 pDriver->u32Session = g_VBoxGuestIDC.u32Session;
206 return VINF_SUCCESS;
207 }
208 pDriver->u32Session = UINT32_MAX;
209 Log(("vbglDriverOpen: failed\n"));
210 return VERR_FILE_NOT_FOUND;
211
212# else
213 uint32_t u32VMMDevVersion;
214 pDriver->pvOpaque = VBoxGuestIDCOpen (&u32VMMDevVersion);
215 if ( pDriver->pvOpaque
216 && u32VMMDevVersion == VMMDEV_VERSION)
217 return VINF_SUCCESS;
218
219 Log(("vbglDriverOpen: failed\n"));
220 return VERR_FILE_NOT_FOUND;
221# endif
222}
223
224# ifdef RT_OS_WINDOWS
225static NTSTATUS vbglDriverIOCtlCompletion (IN PDEVICE_OBJECT DeviceObject,
226 IN PIRP Irp,
227 IN PVOID Context)
228{
229 Log(("VBGL completion %x\n", Irp));
230
231 KEVENT *pEvent = (KEVENT *)Context;
232 KeSetEvent (pEvent, IO_NO_INCREMENT, FALSE);
233
234 return STATUS_MORE_PROCESSING_REQUIRED;
235}
236# endif
237
238int vbglDriverIOCtl (VBGLDRIVER *pDriver, uint32_t u32Function, void *pvData, uint32_t cbData)
239{
240 Log(("vbglDriverIOCtl: pDriver: %p, Func: %x, pvData: %p, cbData: %d\n", pDriver, u32Function, pvData, cbData));
241
242# ifdef RT_OS_WINDOWS
243 KEVENT Event;
244
245 KeInitializeEvent (&Event, NotificationEvent, FALSE);
246
247 /* Have to use the IoAllocateIRP method because this code is generic and
248 * must work in any thread context.
249 * The IoBuildDeviceIoControlRequest, which was used here, does not work
250 * when APCs are disabled, for example.
251 */
252 PIRP irp = IoAllocateIrp (pDriver->pDeviceObject->StackSize, FALSE);
253
254 Log(("vbglDriverIOCtl: irp %p, IRQL = %d\n", irp, KeGetCurrentIrql()));
255
256 if (irp == NULL)
257 {
258 Log(("vbglDriverIOCtl: IRP allocation failed!\n"));
259 return VERR_NO_MEMORY;
260 }
261
262 /*
263 * Setup the IRP_MJ_DEVICE_CONTROL IRP.
264 */
265
266 PIO_STACK_LOCATION nextStack = IoGetNextIrpStackLocation (irp);
267
268 nextStack->MajorFunction = IRP_MJ_DEVICE_CONTROL;
269 nextStack->MinorFunction = 0;
270 nextStack->DeviceObject = pDriver->pDeviceObject;
271 nextStack->Parameters.DeviceIoControl.OutputBufferLength = cbData;
272 nextStack->Parameters.DeviceIoControl.InputBufferLength = cbData;
273 nextStack->Parameters.DeviceIoControl.IoControlCode = u32Function;
274 nextStack->Parameters.DeviceIoControl.Type3InputBuffer = pvData;
275
276 irp->AssociatedIrp.SystemBuffer = pvData; /* Output buffer. */
277 irp->MdlAddress = NULL;
278
279 /* A completion routine is required to signal the Event. */
280 IoSetCompletionRoutine (irp, vbglDriverIOCtlCompletion, &Event, TRUE, TRUE, TRUE);
281
282 NTSTATUS rc = IoCallDriver (pDriver->pDeviceObject, irp);
283
284 if (NT_SUCCESS (rc))
285 {
286 /* Wait the event to be signalled by the completion routine. */
287 KeWaitForSingleObject (&Event,
288 Executive,
289 KernelMode,
290 FALSE,
291 NULL);
292
293 rc = irp->IoStatus.Status;
294
295 Log(("vbglDriverIOCtl: wait completed IRQL = %d\n", KeGetCurrentIrql()));
296 }
297
298 IoFreeIrp (irp);
299
300 if (rc != STATUS_SUCCESS)
301 Log(("vbglDriverIOCtl: ntstatus=%x\n", rc));
302
303 return NT_SUCCESS(rc)? VINF_SUCCESS: VERR_VBGL_IOCTL_FAILED;
304
305# elif defined (RT_OS_OS2)
306 if ( pDriver->u32Session
307 && pDriver->u32Session == g_VBoxGuestIDC.u32Session)
308 return g_VBoxGuestIDC.pfnServiceEP(pDriver->u32Session, u32Function, pvData, cbData, NULL);
309
310 Log(("vbglDriverIOCtl: No connection\n"));
311 return VERR_WRONG_ORDER;
312
313# else
314 return VBoxGuestIDCCall(pDriver->pvOpaque, u32Function, pvData, cbData, NULL);
315# endif
316}
317
318void vbglDriverClose (VBGLDRIVER *pDriver)
319{
320# ifdef RT_OS_WINDOWS
321 Log(("vbglDriverClose pDeviceObject=%x\n", pDriver->pDeviceObject));
322 ObDereferenceObject (pDriver->pFileObject);
323
324# elif defined (RT_OS_OS2)
325 pDriver->u32Session = 0;
326
327# else
328 VBoxGuestIDCClose (pDriver->pvOpaque);
329# endif
330}
331
332#endif /* !VBGL_VBOXGUEST */
333
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