VirtualBox

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

Last change on this file since 92667 was 86876, checked in by vboxsync, 4 years ago

Guest Additions/VbglR3: Condensed / removed duplicate guest property code by adding VbglR3GuestPropExist() + VbglR3GuestPropReadEx().

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