VirtualBox

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

Last change on this file since 27014 was 26999, checked in by vboxsync, 15 years ago

Guest Additions: memory ballooning for guests without support for RTR0MemObjAllocPhysNC() (does not work yet)

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