VirtualBox

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

Last change on this file since 29743 was 28800, checked in by vboxsync, 15 years ago

Automated rebranding to Oracle copyright/license strings via filemuncher

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