VirtualBox

source: vbox/trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibAdditions.cpp

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keyword set to Id
  • Property svn:keywords set to Id Revision
File size: 10.9 KB
Line 
1/* $Id: VBoxGuestR3LibAdditions.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * VBoxGuestR3Lib - Ring-3 Support Library for VirtualBox guest additions, Additions Info.
4 */
5
6/*
7 * Copyright (C) 2007-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#include <iprt/err.h>
42#include <iprt/mem.h>
43#include <iprt/path.h>
44#include <iprt/string.h>
45#ifdef RT_OS_WINDOWS
46# include <iprt/utf16.h>
47#endif
48#include <VBox/log.h>
49#include <VBox/version.h>
50#include "VBoxGuestR3LibInternal.h"
51
52
53
54#ifdef RT_OS_WINDOWS
55
56/**
57 * Opens the "VirtualBox Guest Additions" registry key.
58 *
59 * @returns IPRT status code
60 * @param phKey Receives key handle on success. The returned handle must
61 * be closed by calling vbglR3WinCloseRegKey.
62 */
63static int vbglR3WinOpenAdditionRegisterKey(PHKEY phKey)
64{
65 /*
66 * Current vendor first. We keep the older ones just for the case that
67 * the caller isn't actually installed yet (no real use case AFAIK).
68 */
69 static PCRTUTF16 s_apwszKeys[] =
70 {
71 L"SOFTWARE\\" RT_LSTR(VBOX_VENDOR_SHORT) L"\\VirtualBox Guest Additions",
72#ifdef RT_ARCH_AMD64
73 L"SOFTWARE\\Wow6432Node\\" RT_LSTR(VBOX_VENDOR_SHORT) L"\\VirtualBox Guest Additions",
74#endif
75 L"SOFTWARE\\Sun\\VirtualBox Guest Additions",
76#ifdef RT_ARCH_AMD64
77 L"SOFTWARE\\Wow6432Node\\Sun\\VirtualBox Guest Additions",
78#endif
79 L"SOFTWARE\\Sun\\xVM VirtualBox Guest Additions",
80#ifdef RT_ARCH_AMD64
81 L"SOFTWARE\\Wow6432Node\\Sun\\xVM VirtualBox Guest Additions",
82#endif
83 };
84 int rc = VERR_NOT_FOUND;
85 for (uint32_t i = 0; i < RT_ELEMENTS(s_apwszKeys); i++)
86 {
87 LSTATUS lrc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, s_apwszKeys[i], 0 /* ulOptions*/, KEY_READ, phKey);
88 if (lrc == ERROR_SUCCESS)
89 return VINF_SUCCESS;
90 if (i == 0)
91 rc = RTErrConvertFromWin32(lrc);
92 }
93 return rc;
94}
95
96
97/**
98 * Closes the registry handle returned by vbglR3WinOpenAdditionRegisterKey().
99 *
100 * @returns @a rc or IPRT failure status.
101 * @param hKey Handle to close.
102 * @param rc The current IPRT status of the operation. Error
103 * condition takes precedence over errors from this call.
104 */
105static int vbglR3WinCloseRegKey(HKEY hKey, int rc)
106{
107 LSTATUS lrc = RegCloseKey(hKey);
108 if ( lrc == ERROR_SUCCESS
109 || RT_FAILURE(rc))
110 return rc;
111 return RTErrConvertFromWin32(lrc);
112}
113
114
115/**
116 * Queries a string value from a specified registry key.
117 *
118 * @return IPRT status code.
119 * @param hKey Handle of registry key to use.
120 * @param pwszValueName The name of the value to query.
121 * @param cbHint Size hint.
122 * @param ppszValue Where to return value string on success. Free
123 * with RTStrFree.
124 */
125static int vbglR3QueryRegistryString(HKEY hKey, PCRTUTF16 pwszValueName, uint32_t cbHint, char **ppszValue)
126{
127 AssertPtr(pwszValueName);
128 AssertPtrReturn(ppszValue, VERR_INVALID_POINTER);
129
130 /*
131 * First try.
132 */
133 int rc;
134 DWORD dwType;
135 DWORD cbTmp = cbHint;
136 PRTUTF16 pwszTmp = (PRTUTF16)RTMemTmpAllocZ(cbTmp + sizeof(RTUTF16));
137 if (pwszTmp)
138 {
139 LSTATUS lrc = RegQueryValueExW(hKey, pwszValueName, NULL, &dwType, (BYTE *)pwszTmp, &cbTmp);
140 if (lrc == ERROR_MORE_DATA)
141 {
142 /*
143 * Allocate larger buffer and try again.
144 */
145 RTMemTmpFree(pwszTmp);
146 cbTmp += 16;
147 pwszTmp = (PRTUTF16)RTMemTmpAllocZ(cbTmp + sizeof(RTUTF16));
148 if (!pwszTmp)
149 {
150 *ppszValue = NULL;
151 return VERR_NO_TMP_MEMORY;
152 }
153 lrc = RegQueryValueExW(hKey, pwszValueName, NULL, &dwType, (BYTE *)pwszTmp, &cbTmp);
154 }
155 if (lrc == ERROR_SUCCESS)
156 {
157 /*
158 * Check the type and convert to UTF-8.
159 */
160 if (dwType == REG_SZ)
161 rc = RTUtf16ToUtf8(pwszTmp, ppszValue);
162 else
163 rc = VERR_WRONG_TYPE;
164 }
165 else
166 rc = RTErrConvertFromWin32(lrc);
167 RTMemTmpFree(pwszTmp);
168 }
169 else
170 rc = VERR_NO_TMP_MEMORY;
171 if (RT_SUCCESS(rc))
172 return rc;
173 *ppszValue = NULL;
174 return rc;
175}
176
177#endif /* RT_OS_WINDOWS */
178
179
180/**
181 * Fallback for VbglR3GetAdditionsVersion.
182 *
183 * @copydoc VbglR3GetAdditionsVersion
184 */
185static int vbglR3GetAdditionsCompileTimeVersion(char **ppszVer, char **ppszVerExt, char **ppszRev)
186{
187 int rc = VINF_SUCCESS;
188 if (ppszVer)
189 rc = RTStrDupEx(ppszVer, VBOX_VERSION_STRING_RAW);
190 if (RT_SUCCESS(rc))
191 {
192 if (ppszVerExt)
193 rc = RTStrDupEx(ppszVerExt, VBOX_VERSION_STRING);
194 if (RT_SUCCESS(rc))
195 {
196 if (ppszRev)
197 rc = RTStrDupEx(ppszRev, RT_XSTR(VBOX_SVN_REV));
198 if (RT_SUCCESS(rc))
199 return VINF_SUCCESS;
200
201 /* bail out: */
202 }
203 if (ppszVerExt)
204 {
205 RTStrFree(*ppszVerExt);
206 *ppszVerExt = NULL;
207 }
208 }
209 if (ppszVer)
210 {
211 RTStrFree(*ppszVer);
212 *ppszVer = NULL;
213 }
214 return rc;
215}
216
217
218/**
219 * Retrieves the installed Guest Additions version and/or revision.
220 *
221 * @returns IPRT status code
222 * @param ppszVer Receives pointer of allocated raw version string
223 * (major.minor.build). NULL is accepted. The returned
224 * pointer must be freed using RTStrFree().
225 * @param ppszVerExt Receives pointer of allocated full version string
226 * (raw version + vendor suffix(es)). NULL is
227 * accepted. The returned pointer must be freed using
228 * RTStrFree().
229 * @param ppszRev Receives pointer of allocated revision string. NULL is
230 * accepted. The returned pointer must be freed using
231 * RTStrFree().
232 */
233VBGLR3DECL(int) VbglR3GetAdditionsVersion(char **ppszVer, char **ppszVerExt, char **ppszRev)
234{
235 /*
236 * Zap the return value up front.
237 */
238 if (ppszVer)
239 *ppszVer = NULL;
240 if (ppszVerExt)
241 *ppszVerExt = NULL;
242 if (ppszRev)
243 *ppszRev = NULL;
244
245#ifdef RT_OS_WINDOWS
246 HKEY hKey;
247 int rc = vbglR3WinOpenAdditionRegisterKey(&hKey);
248 if (RT_SUCCESS(rc))
249 {
250 /*
251 * Version.
252 */
253 if (ppszVer)
254 rc = vbglR3QueryRegistryString(hKey, L"Version", 64, ppszVer);
255
256 if ( RT_SUCCESS(rc)
257 && ppszVerExt)
258 rc = vbglR3QueryRegistryString(hKey, L"VersionExt", 128, ppszVerExt);
259
260 /*
261 * Revision.
262 */
263 if ( RT_SUCCESS(rc)
264 && ppszRev)
265 rc = vbglR3QueryRegistryString(hKey, L"Revision", 64, ppszRev);
266
267 rc = vbglR3WinCloseRegKey(hKey, rc);
268
269 /* Clean up allocated strings on error. */
270 if (RT_FAILURE(rc))
271 {
272 if (ppszVer)
273 {
274 RTStrFree(*ppszVer);
275 *ppszVer = NULL;
276 }
277 if (ppszVerExt)
278 {
279 RTStrFree(*ppszVerExt);
280 *ppszVerExt = NULL;
281 }
282 if (ppszRev)
283 {
284 RTStrFree(*ppszRev);
285 *ppszRev = NULL;
286 }
287 }
288 }
289 /*
290 * No registry entries found, return the version string compiled into this binary.
291 */
292 else
293 rc = vbglR3GetAdditionsCompileTimeVersion(ppszVer, ppszVerExt, ppszRev);
294 return rc;
295
296#else /* !RT_OS_WINDOWS */
297 /*
298 * On non-Windows platforms just return the compile-time version string.
299 */
300 return vbglR3GetAdditionsCompileTimeVersion(ppszVer, ppszVerExt, ppszRev);
301#endif /* !RT_OS_WINDOWS */
302}
303
304
305/**
306 * Retrieves the installation path of Guest Additions.
307 *
308 * @returns IPRT status code
309 * @param ppszPath Receives pointer of allocated installation path string.
310 * The returned pointer must be freed using
311 * RTStrFree().
312 */
313VBGLR3DECL(int) VbglR3GetAdditionsInstallationPath(char **ppszPath)
314{
315 int rc;
316
317#ifdef RT_OS_WINDOWS
318 /*
319 * Get it from the registry.
320 */
321 HKEY hKey;
322 rc = vbglR3WinOpenAdditionRegisterKey(&hKey);
323 if (RT_SUCCESS(rc))
324 {
325 rc = vbglR3QueryRegistryString(hKey, L"InstallDir", MAX_PATH * sizeof(RTUTF16), ppszPath);
326 if (RT_SUCCESS(rc))
327 RTPathChangeToUnixSlashes(*ppszPath, true /*fForce*/);
328 rc = vbglR3WinCloseRegKey(hKey, rc);
329 }
330#else
331 /** @todo implement me */
332 rc = VERR_NOT_IMPLEMENTED;
333 RT_NOREF1(ppszPath);
334#endif
335 return rc;
336}
337
338
339/**
340 * Reports the Guest Additions status of a certain facility to the host.
341 *
342 * @returns IPRT status code
343 * @param enmFacility The facility to report the status on.
344 * @param enmStatus The new status of the facility.
345 * @param fReserved Flags reserved for future hacks.
346 */
347VBGLR3DECL(int) VbglR3ReportAdditionsStatus(VBoxGuestFacilityType enmFacility, VBoxGuestFacilityStatus enmStatus,
348 uint32_t fReserved)
349{
350 VMMDevReportGuestStatus Report;
351 RT_ZERO(Report);
352 int rc = vmmdevInitRequest(&Report.header, VMMDevReq_ReportGuestStatus);
353 if (RT_SUCCESS(rc))
354 {
355 Report.guestStatus.facility = enmFacility;
356 Report.guestStatus.status = enmStatus;
357 Report.guestStatus.flags = fReserved;
358
359 rc = vbglR3GRPerform(&Report.header);
360 }
361 return rc;
362}
363
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use