VirtualBox

source: vbox/trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibMisc.cpp@ 26131

Last change on this file since 26131 was 26054, checked in by vboxsync, 15 years ago

Additions/x11/vboxvideo: use vboxvideo_70 for the XFree86 driver too

  • Property svn:eol-style set to native
  • Property svn:keyword set to Id
  • Property svn:keywords set to Id
File size: 13.1 KB
Line 
1/* $Id: VBoxGuestR3LibMisc.cpp 26054 2010-01-26 20:46:38Z vboxsync $ */
2/** @file
3 * VBoxGuestR3Lib - Ring-3 Support Library for VirtualBox guest additions, Misc.
4 */
5
6/*
7 * Copyright (C) 2007 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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22
23/*******************************************************************************
24* Header Files *
25*******************************************************************************/
26#include <iprt/mem.h>
27#include <iprt/string.h>
28#include <VBox/log.h>
29#include <VBox/version.h>
30#include "VBGLR3Internal.h"
31
32
33/**
34 * Wait for the host to signal one or more events and return which.
35 *
36 * The events will only be delivered by the host if they have been enabled
37 * previously using @a VbglR3CtlFilterMask. If one or several of the events
38 * have already been signalled but not yet waited for, this function will return
39 * immediately and return those events.
40 *
41 * @returns IPRT status code
42 *
43 * @param fMask The events we want to wait for, or-ed together.
44 * @param cMillies How long to wait before giving up and returning
45 * (VERR_TIMEOUT). Use RT_INDEFINITE_WAIT to wait until we
46 * are interrupted or one of the events is signalled.
47 * @param pfEvents Where to store the events signalled. Optional.
48 */
49VBGLR3DECL(int) VbglR3WaitEvent(uint32_t fMask, uint32_t cMillies, uint32_t *pfEvents)
50{
51#ifndef VBOX_VBGLR3_XFREE86
52 LogFlow(("VbglR3WaitEvent: fMask=0x%x, cMillies=%u, pfEvents=%p\n",
53 fMask, cMillies, pfEvents));
54 AssertReturn((fMask & ~VMMDEV_EVENT_VALID_EVENT_MASK) == 0, VERR_INVALID_PARAMETER);
55 AssertPtrNullReturn(pfEvents, VERR_INVALID_POINTER);
56#endif
57
58 VBoxGuestWaitEventInfo waitEvent;
59 waitEvent.u32TimeoutIn = cMillies;
60 waitEvent.u32EventMaskIn = fMask;
61 waitEvent.u32Result = VBOXGUEST_WAITEVENT_ERROR;
62 waitEvent.u32EventFlagsOut = 0;
63 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_WAITEVENT, &waitEvent, sizeof(waitEvent));
64 if (RT_SUCCESS(rc))
65 {
66#ifndef VBOX_VBGLR3_XFREE86
67 AssertMsg(waitEvent.u32Result == VBOXGUEST_WAITEVENT_OK, ("%d\n", waitEvent.u32Result));
68#endif
69 if (pfEvents)
70 *pfEvents = waitEvent.u32EventFlagsOut;
71 }
72
73#ifndef VBOX_VBGLR3_XFREE86
74 LogFlow(("VbglR3WaitEvent: rc=%Rrc, u32EventFlagsOut=0x%x. u32Result=%d\n",
75 rc, waitEvent.u32EventFlagsOut, waitEvent.u32Result));
76#endif
77 return rc;
78}
79
80
81/**
82 * Cause any pending WaitEvent calls (VBOXGUEST_IOCTL_WAITEVENT) to return
83 * with a VERR_INTERRUPTED status.
84 *
85 * Can be used in combination with a termination flag variable for interrupting
86 * event loops. Avoiding race conditions is the responsibility of the caller.
87 *
88 * @returns IPRT status code
89 */
90VBGLR3DECL(int) VbglR3InterruptEventWaits(void)
91{
92 return vbglR3DoIOCtl(VBOXGUEST_IOCTL_CANCEL_ALL_WAITEVENTS, 0, 0);
93}
94
95
96/**
97 * Write to the backdoor logger from ring 3 guest code.
98 *
99 * @returns IPRT status code
100 *
101 * @remarks This currently does not accept more than 255 bytes of data at
102 * one time. It should probably be rewritten to use pass a pointer
103 * in the IOCtl.
104 */
105VBGLR3DECL(int) VbglR3WriteLog(const char *pch, size_t cb)
106{
107 /*
108 * Quietly skip NULL strings.
109 * (Happens in the RTLogBackdoorPrintf case.)
110 */
111 if (!cb)
112 return VINF_SUCCESS;
113 if (!VALID_PTR(pch))
114 return VERR_INVALID_POINTER;
115
116#ifdef RT_OS_WINDOWS
117 /*
118 * Duplicate the string as it may be read only (a C string).
119 */
120 void *pvTmp = RTMemDup(pch, cb);
121 if (!pvTmp)
122 return VERR_NO_MEMORY;
123 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_LOG(cb), pvTmp, cb);
124 RTMemFree(pvTmp);
125 return rc;
126
127#elif 0 /** @todo Several OSes could take this route (solaris and freebsd for instance). */
128 /*
129 * Handle the entire request in one go.
130 */
131 return vbglR3DoIOCtl(VBOXGUEST_IOCTL_LOG(cb), pvTmp, cb);
132
133#else
134 /*
135 * *BSD does not accept more than 4KB per ioctl request, while
136 * Linux can't express sizes above 8KB, so, split it up into 2KB chunks.
137 */
138# define STEP 2048
139 int rc = VINF_SUCCESS;
140 for (size_t off = 0; off < cb && RT_SUCCESS(rc); off += STEP)
141 {
142 size_t cbStep = RT_MIN(cb - off, STEP);
143 rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_LOG(cbStep), (char *)pch + off, cbStep);
144 }
145# undef STEP
146 return rc;
147#endif
148}
149
150
151/**
152 * Change the IRQ filter mask.
153 *
154 * @returns IPRT status code
155 * @param fOr The OR mask.
156 * @param fNo The NOT mask.
157 */
158VBGLR3DECL(int) VbglR3CtlFilterMask(uint32_t fOr, uint32_t fNot)
159{
160#if defined(RT_OS_WINDOWS)
161 /** @todo Not yet implemented. */
162 return VERR_NOT_SUPPORTED;
163
164#else
165
166 VBoxGuestFilterMaskInfo Info;
167 Info.u32OrMask = fOr;
168 Info.u32NotMask = fNot;
169 return vbglR3DoIOCtl(VBOXGUEST_IOCTL_CTL_FILTER_MASK, &Info, sizeof(Info));
170#endif
171}
172
173
174/**
175 * Report a change in the capabilities that we support to the host.
176 *
177 * @returns IPRT status value
178 * @param fOr Capabilities which have been added.
179 * @param fNot Capabilities which have been removed.
180 *
181 * @todo Move to a different file.
182 */
183VBGLR3DECL(int) VbglR3SetGuestCaps(uint32_t fOr, uint32_t fNot)
184{
185 VMMDevReqGuestCapabilities2 Req;
186
187 vmmdevInitRequest(&Req.header, VMMDevReq_SetGuestCapabilities);
188 Req.u32OrMask = fOr;
189 Req.u32NotMask = fNot;
190 int rc = vbglR3GRPerform(&Req.header);
191#if defined(DEBUG) && !defined(VBOX_VBGLR3_XFREE86)
192 if (RT_SUCCESS(rc))
193 LogRel(("Successfully changed guest capabilities: or mask 0x%x, not mask 0x%x.\n", fOr, fNot));
194 else
195 LogRel(("Failed to change guest capabilities: or mask 0x%x, not mask 0x%x. rc=%Rrc.\n", fOr, fNot, rc));
196#endif
197 return rc;
198}
199
200
201#ifndef VBOX_VBGLR3_XFREE86
202/**
203 * Fallback for vbglR3GetAdditionsVersion.
204 */
205static int vbglR3GetAdditionsCompileTimeVersion(char **ppszVer, char **ppszRev)
206{
207 if (ppszVer)
208 {
209 *ppszVer = RTStrDup(VBOX_VERSION_STRING);
210 if (!*ppszVer)
211 return VERR_NO_STR_MEMORY;
212 }
213
214 if (ppszRev)
215 {
216 char szRev[64];
217 RTStrPrintf(szRev, sizeof(szRev), "%d", VBOX_SVN_REV);
218 *ppszRev = RTStrDup(szRev);
219 if (!*ppszRev)
220 {
221 if (ppszVer)
222 {
223 RTStrFree(*ppszVer);
224 *ppszVer = NULL;
225 }
226 return VERR_NO_STR_MEMORY;
227 }
228 }
229
230 return VINF_SUCCESS;
231}
232#endif
233
234
235#ifdef RT_OS_WINDOWS
236/**
237 * Looks up the storage path handle (registry).
238 *
239 * @returns IPRT status value
240 * @param hKey Receives pointer of allocated version string. NULL is
241 * accepted. The returned pointer must be closed by
242 * vbglR3CloseAdditionsWinStoragePath().
243 */
244static int vbglR3GetAdditionsWinStoragePath(PHKEY phKey)
245{
246 /*
247 * Try get the *installed* version first.
248 */
249 LONG r;
250
251 /* Check the new path first. */
252 r = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Sun\\VirtualBox Guest Additions", 0, KEY_READ, phKey);
253# ifdef RT_ARCH_AMD64
254 if (r != ERROR_SUCCESS)
255 {
256 /* Check Wow6432Node (for new entries). */
257 r = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wow6432Node\\Sun\\VirtualBox Guest Additions", 0, KEY_READ, phKey);
258 }
259# endif
260
261 /* Still no luck? Then try the old xVM paths ... */
262 if (r != ERROR_SUCCESS)
263 {
264 r = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Sun\\xVM VirtualBox Guest Additions", 0, KEY_READ, phKey);
265# ifdef RT_ARCH_AMD64
266 if (r != ERROR_SUCCESS)
267 {
268 /* Check Wow6432Node (for new entries). */
269 r = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wow6432Node\\Sun\\xVM VirtualBox Guest Additions", 0, KEY_READ, phKey);
270 }
271# endif
272 }
273 return RTErrConvertFromWin32(r);
274}
275
276
277/**
278 * Closes the storage path handle (registry).
279 *
280 * @returns IPRT status value
281 * @param hKey Handle to close, retrieved by
282 * vbglR3GetAdditionsWinStoragePath().
283 */
284static int vbglR3CloseAdditionsWinStoragePath(HKEY hKey)
285{
286 return RTErrConvertFromWin32(RegCloseKey(hKey));
287}
288#endif /* RT_OS_WINDOWS */
289
290
291#ifndef VBOX_VBGLR3_XFREE86
292/**
293 * Retrieves the installed Guest Additions version and/or revision.
294 *
295 * @returns IPRT status value
296 * @param ppszVer Receives pointer of allocated version string. NULL is
297 * accepted. The returned pointer must be freed using
298 * RTStrFree().
299 * @param ppszRev Receives pointer of allocated revision string. NULL is
300 * accepted. The returned pointer must be freed using
301 * RTStrFree().
302 */
303VBGLR3DECL(int) VbglR3GetAdditionsVersion(char **ppszVer, char **ppszRev)
304{
305#ifdef RT_OS_WINDOWS
306 HKEY hKey;
307 int rc = vbglR3GetAdditionsWinStoragePath(&hKey);
308 if (RT_SUCCESS(rc))
309 {
310 /* Version. */
311 LONG l;
312 DWORD dwType;
313 DWORD dwSize = 32;
314 char *pszTmp;
315 if (ppszVer)
316 {
317 pszTmp = (char*)RTMemAlloc(dwSize);
318 if (pszTmp)
319 {
320 l = RegQueryValueEx(hKey, "Version", NULL, &dwType, (BYTE*)(LPCTSTR)pszTmp, &dwSize);
321 if (l == ERROR_SUCCESS)
322 {
323 if (dwType == REG_SZ)
324 rc = RTStrDupEx(ppszVer, pszTmp);
325 else
326 rc = VERR_INVALID_PARAMETER;
327 }
328 else
329 {
330 rc = RTErrConvertFromWin32(l);
331 }
332 RTMemFree(pszTmp);
333 }
334 else
335 rc = VERR_NO_MEMORY;
336 }
337 /* Revision. */
338 if (ppszRev)
339 {
340 dwSize = 32; /* Reset */
341 pszTmp = (char*)RTMemAlloc(dwSize);
342 if (pszTmp)
343 {
344 l = RegQueryValueEx(hKey, "Revision", NULL, &dwType, (BYTE*)(LPCTSTR)pszTmp, &dwSize);
345 if (l == ERROR_SUCCESS)
346 {
347 if (dwType == REG_SZ)
348 rc = RTStrDupEx(ppszRev, pszTmp);
349 else
350 rc = VERR_INVALID_PARAMETER;
351 }
352 else
353 {
354 rc = RTErrConvertFromWin32(l);
355 }
356 RTMemFree(pszTmp);
357 }
358 else
359 rc = VERR_NO_MEMORY;
360
361 if (RT_FAILURE(rc) && ppszVer)
362 {
363 RTStrFree(*ppszVer);
364 *ppszVer = NULL;
365 }
366 }
367 rc = vbglR3CloseAdditionsWinStoragePath(hKey);
368 }
369 else
370 {
371 /*
372 * No registry entries found, return the version string compiled
373 * into this binary.
374 */
375 rc = vbglR3GetAdditionsCompileTimeVersion(ppszVer, ppszRev);
376 }
377 return rc;
378
379#else /* !RT_OS_WINDOWS */
380 /*
381 * On non-Windows platforms just return the compile-time version string.
382 */
383 return vbglR3GetAdditionsCompileTimeVersion(ppszVer, ppszRev);
384#endif /* !RT_OS_WINDOWS */
385}
386#endif /* !VBOX_VBGLR3_XFREE86 */
387
388/**
389 * Retrieves the installation path of Guest Additions.
390 *
391 * @returns IPRT status value
392 * @param ppszPath Receives pointer of allocated installation path string.
393 * The returned pointer must be freed using
394 * RTStrFree().
395 */
396VBGLR3DECL(int) VbglR3GetAdditionsInstallationPath(char **ppszPath)
397{
398 int rc;
399#ifdef RT_OS_WINDOWS
400 HKEY hKey;
401 rc = vbglR3GetAdditionsWinStoragePath(&hKey);
402 if (RT_SUCCESS(rc))
403 {
404 /* Installation directory. */
405 DWORD dwType;
406 DWORD dwSize = _MAX_PATH * sizeof(char);
407 char *pszTmp = (char*)RTMemAlloc(dwSize + 1);
408 if (pszTmp)
409 {
410 LONG l = RegQueryValueEx(hKey, "InstallDir", NULL, &dwType, (BYTE*)(LPCTSTR)pszTmp, &dwSize);
411 if ((l != ERROR_SUCCESS) && (l != ERROR_FILE_NOT_FOUND))
412 {
413 rc = RTErrConvertFromNtStatus(l);
414 }
415 else
416 {
417 if (dwType == REG_SZ)
418 rc = RTStrDupEx(ppszPath, pszTmp);
419 else
420 rc = VERR_INVALID_PARAMETER;
421 if (RT_SUCCESS(rc))
422 {
423 /* Flip slashes. */
424 for (char *pszTmp2 = ppszPath[0]; *pszTmp2; ++pszTmp2)
425 if (*pszTmp2 == '\\')
426 *pszTmp2 = '/';
427 }
428 }
429 RTMemFree(pszTmp);
430 }
431 else
432 rc = VERR_NO_MEMORY;
433 rc = vbglR3CloseAdditionsWinStoragePath(hKey);
434 }
435#else
436 /** @todo implement me */
437 rc = VERR_NOT_IMPLEMENTED;
438#endif
439 return rc;
440}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette