VirtualBox

source: vbox/trunk/src/VBox/Additions/common/VBoxService/VBoxServiceUtils.cpp@ 98103

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

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.4 KB
Line 
1/* $Id: VBoxServiceUtils.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * VBoxServiceUtils - Some utility functions.
4 */
5
6/*
7 * Copyright (C) 2009-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 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#ifdef RT_OS_WINDOWS
33# include <iprt/win/windows.h>
34# include <iprt/param.h>
35# include <iprt/path.h>
36#endif
37#include <iprt/assert.h>
38#include <iprt/mem.h>
39#include <iprt/string.h>
40
41#include <VBox/VBoxGuestLib.h>
42#include "VBoxServiceInternal.h"
43
44
45#ifdef VBOX_WITH_GUEST_PROPS
46/**
47 * Reads a guest property as a 32-bit value.
48 *
49 * @returns VBox status code, fully bitched.
50 *
51 * @param u32ClientId The HGCM client ID for the guest property session.
52 * @param pszPropName The property name.
53 * @param pu32 Where to store the 32-bit value.
54 *
55 */
56int VGSvcReadPropUInt32(uint32_t u32ClientId, const char *pszPropName, uint32_t *pu32, uint32_t u32Min, uint32_t u32Max)
57{
58 char *pszValue;
59 int rc = VbglR3GuestPropReadEx(u32ClientId, pszPropName, &pszValue, NULL /* ppszFlags */, NULL /* puTimestamp */);
60 if (RT_SUCCESS(rc))
61 {
62 char *pszNext;
63 rc = RTStrToUInt32Ex(pszValue, &pszNext, 0, pu32);
64 if ( RT_SUCCESS(rc)
65 && (*pu32 < u32Min || *pu32 > u32Max))
66 rc = VGSvcError("The guest property value %s = %RU32 is out of range [%RU32..%RU32].\n",
67 pszPropName, *pu32, u32Min, u32Max);
68 RTStrFree(pszValue);
69 }
70 return rc;
71}
72
73/**
74 * Reads a guest property from the host side.
75 *
76 * @returns IPRT status code, fully bitched.
77 * @param u32ClientId The HGCM client ID for the guest property session.
78 * @param pszPropName The property name.
79 * @param fReadOnly Whether or not this property needs to be read only
80 * by the guest side. Otherwise VERR_ACCESS_DENIED will
81 * be returned.
82 * @param ppszValue Where to return the value. This is always set
83 * to NULL. Free it using RTStrFree().
84 * @param ppszFlags Where to return the value flags. Free it
85 * using RTStrFree(). Optional.
86 * @param puTimestamp Where to return the timestamp. This is only set
87 * on success. Optional.
88 */
89int VGSvcReadHostProp(uint32_t u32ClientId, const char *pszPropName, bool fReadOnly,
90 char **ppszValue, char **ppszFlags, uint64_t *puTimestamp)
91{
92 AssertPtrReturn(ppszValue, VERR_INVALID_PARAMETER);
93
94 char *pszValue = NULL;
95 char *pszFlags = NULL;
96 int rc = VbglR3GuestPropReadEx(u32ClientId, pszPropName, &pszValue, &pszFlags, puTimestamp);
97 if (RT_SUCCESS(rc))
98 {
99 /* Check security bits. */
100 if ( fReadOnly /* Do we except a guest read-only property */
101 && !RTStrStr(pszFlags, "RDONLYGUEST"))
102 {
103 /* If we want a property which is read-only on the guest
104 * and it is *not* marked as such, deny access! */
105 rc = VERR_ACCESS_DENIED;
106 }
107
108 if (RT_SUCCESS(rc))
109 {
110 *ppszValue = pszValue;
111
112 if (ppszFlags)
113 *ppszFlags = pszFlags;
114 else if (pszFlags)
115 RTStrFree(pszFlags);
116 }
117 else
118 {
119 if (pszValue)
120 RTStrFree(pszValue);
121 if (pszFlags)
122 RTStrFree(pszFlags);
123 }
124 }
125
126 return rc;
127}
128
129
130/**
131 * Wrapper around VbglR3GuestPropWriteValue that does value formatting and
132 * logging.
133 *
134 * @returns VBox status code. Errors will be logged.
135 *
136 * @param u32ClientId The HGCM client ID for the guest property session.
137 * @param pszName The property name.
138 * @param pszValueFormat The property format string. If this is NULL then
139 * the property will be deleted (if possible).
140 * @param ... Format arguments.
141 */
142int VGSvcWritePropF(uint32_t u32ClientId, const char *pszName, const char *pszValueFormat, ...)
143{
144 AssertPtr(pszName);
145 int rc;
146 if (pszValueFormat != NULL)
147 {
148 va_list va;
149 va_start(va, pszValueFormat);
150 VGSvcVerbose(3, "Writing guest property '%s' = '%N'\n", pszName, pszValueFormat, &va);
151 va_end(va);
152
153 va_start(va, pszValueFormat);
154 rc = VbglR3GuestPropWriteValueV(u32ClientId, pszName, pszValueFormat, va);
155 va_end(va);
156
157 if (RT_FAILURE(rc))
158 VGSvcError("Error writing guest property '%s' (rc=%Rrc)\n", pszName, rc);
159 }
160 else
161 {
162 VGSvcVerbose(3, "Deleting guest property '%s'\n", pszName);
163 rc = VbglR3GuestPropWriteValue(u32ClientId, pszName, NULL);
164 if (RT_FAILURE(rc))
165 VGSvcError("Error deleting guest property '%s' (rc=%Rrc)\n", pszName, rc);
166 }
167 return rc;
168}
169
170#endif /* VBOX_WITH_GUEST_PROPS */
171#ifdef RT_OS_WINDOWS
172
173/**
174 * Helper for vgsvcUtilGetFileVersion and attempts to read and parse
175 * FileVersion.
176 *
177 * @returns Success indicator.
178 */
179static bool vgsvcUtilGetFileVersionOwn(LPSTR pVerData, uint32_t *puMajor, uint32_t *puMinor,
180 uint32_t *puBuildNumber, uint32_t *puRevisionNumber)
181{
182 UINT cchStrValue = 0;
183 LPTSTR pStrValue = NULL;
184 if (!VerQueryValueA(pVerData, "\\StringFileInfo\\040904b0\\FileVersion", (LPVOID *)&pStrValue, &cchStrValue))
185 return false;
186
187 char *pszNext = pStrValue;
188 int rc = RTStrToUInt32Ex(pszNext, &pszNext, 0, puMajor);
189 AssertReturn(rc == VWRN_TRAILING_CHARS, false);
190 AssertReturn(*pszNext == '.', false);
191
192 rc = RTStrToUInt32Ex(pszNext + 1, &pszNext, 0, puMinor);
193 AssertReturn(rc == VWRN_TRAILING_CHARS, false);
194 AssertReturn(*pszNext == '.', false);
195
196 rc = RTStrToUInt32Ex(pszNext + 1, &pszNext, 0, puBuildNumber);
197 AssertReturn(rc == VWRN_TRAILING_CHARS, false);
198 AssertReturn(*pszNext == '.', false);
199
200 rc = RTStrToUInt32Ex(pszNext + 1, &pszNext, 0, puRevisionNumber);
201 AssertReturn(rc == VINF_SUCCESS || rc == VWRN_TRAILING_CHARS /*??*/, false);
202
203 return true;
204}
205
206
207/**
208 * Worker for VGSvcUtilWinGetFileVersionString.
209 *
210 * @returns VBox status code.
211 * @param pszFilename ASCII & ANSI & UTF-8 compliant name.
212 * @param puMajor Where to return the major version number.
213 * @param puMinor Where to return the minor version number.
214 * @param puBuildNumber Where to return the build number.
215 * @param puRevisionNumber Where to return the revision number.
216 */
217static int vgsvcUtilGetFileVersion(const char *pszFilename, uint32_t *puMajor, uint32_t *puMinor, uint32_t *puBuildNumber,
218 uint32_t *puRevisionNumber)
219{
220 int rc;
221
222 *puMajor = *puMinor = *puBuildNumber = *puRevisionNumber = 0;
223
224 /*
225 * Get the file version info.
226 */
227 DWORD dwHandleIgnored;
228 DWORD cbVerData = GetFileVersionInfoSizeA(pszFilename, &dwHandleIgnored);
229 if (cbVerData)
230 {
231 LPTSTR pVerData = (LPTSTR)RTMemTmpAllocZ(cbVerData);
232 if (pVerData)
233 {
234 if (GetFileVersionInfoA(pszFilename, dwHandleIgnored, cbVerData, pVerData))
235 {
236 /*
237 * Try query and parse the FileVersion string our selves first
238 * since this will give us the correct revision number when
239 * it goes beyond the range of an uint16_t / WORD.
240 */
241 if (vgsvcUtilGetFileVersionOwn(pVerData, puMajor, puMinor, puBuildNumber, puRevisionNumber))
242 rc = VINF_SUCCESS;
243 else
244 {
245 /* Fall back on VS_FIXEDFILEINFO */
246 UINT cbFileInfoIgnored = 0;
247 VS_FIXEDFILEINFO *pFileInfo = NULL;
248 if (VerQueryValue(pVerData, "\\", (LPVOID *)&pFileInfo, &cbFileInfoIgnored))
249 {
250 *puMajor = HIWORD(pFileInfo->dwFileVersionMS);
251 *puMinor = LOWORD(pFileInfo->dwFileVersionMS);
252 *puBuildNumber = HIWORD(pFileInfo->dwFileVersionLS);
253 *puRevisionNumber = LOWORD(pFileInfo->dwFileVersionLS);
254 rc = VINF_SUCCESS;
255 }
256 else
257 {
258 rc = RTErrConvertFromWin32(GetLastError());
259 VGSvcVerbose(3, "No file version value for file '%s' available! (%d / rc=%Rrc)\n",
260 pszFilename, GetLastError(), rc);
261 }
262 }
263 }
264 else
265 {
266 rc = RTErrConvertFromWin32(GetLastError());
267 VGSvcVerbose(0, "GetFileVersionInfo(%s) -> %u / %Rrc\n", pszFilename, GetLastError(), rc);
268 }
269
270 RTMemTmpFree(pVerData);
271 }
272 else
273 {
274 VGSvcVerbose(0, "Failed to allocate %u byte for file version info for '%s'\n", cbVerData, pszFilename);
275 rc = VERR_NO_TMP_MEMORY;
276 }
277 }
278 else
279 {
280 rc = RTErrConvertFromWin32(GetLastError());
281 VGSvcVerbose(3, "GetFileVersionInfoSize(%s) -> %u / %Rrc\n", pszFilename, GetLastError(), rc);
282 }
283 return rc;
284}
285
286
287/**
288 * Gets a re-formatted version string from the VS_FIXEDFILEINFO table.
289 *
290 * @returns VBox status code. The output buffer is always valid and the status
291 * code can safely be ignored.
292 *
293 * @param pszPath The base path.
294 * @param pszFilename The filename.
295 * @param pszVersion Where to return the version string.
296 * @param cbVersion The size of the version string buffer. This MUST be
297 * at least 2 bytes!
298 */
299int VGSvcUtilWinGetFileVersionString(const char *pszPath, const char *pszFilename, char *pszVersion, size_t cbVersion)
300{
301 /*
302 * We will ALWAYS return with a valid output buffer.
303 */
304 AssertReturn(cbVersion >= 2, VERR_BUFFER_OVERFLOW);
305 pszVersion[0] = '-';
306 pszVersion[1] = '\0';
307
308 /*
309 * Create the path and query the bits.
310 */
311 char szFullPath[RTPATH_MAX];
312 int rc = RTPathJoin(szFullPath, sizeof(szFullPath), pszPath, pszFilename);
313 if (RT_SUCCESS(rc))
314 {
315 uint32_t uMajor, uMinor, uBuild, uRev;
316 rc = vgsvcUtilGetFileVersion(szFullPath, &uMajor, &uMinor, &uBuild, &uRev);
317 if (RT_SUCCESS(rc))
318 RTStrPrintf(pszVersion, cbVersion, "%u.%u.%ur%u", uMajor, uMinor, uBuild, uRev);
319 }
320 return rc;
321}
322
323#endif /* RT_OS_WINDOWS */
324
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use