VBoxServiceUtils.cpp revision 4893c4e3513fece2ef56f559aa2370c25f12a745
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync/* $Id$ */
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync/** @file
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync * VBoxServiceUtils - Some utility functions.
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync */
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync/*
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync * Copyright (C) 2009 Sun Microsystems, Inc.
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync *
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync * available from http://www.virtualbox.org. This file is free software;
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync * you can redistribute it and/or modify it under the terms of the GNU
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync * General Public License (GPL) as published by the Free Software
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync *
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync * additional information or have any questions.
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync */
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync/*******************************************************************************
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync* Header Files *
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync*******************************************************************************/
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync#ifdef RT_OS_WINDOWS
682a27d94b9116c719038882487b99053985f91avboxsync# include <Windows.h>
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync#endif
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync#include <iprt/assert.h>
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync#include <iprt/mem.h>
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync#include <iprt/string.h>
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync
682a27d94b9116c719038882487b99053985f91avboxsync#include <VBox/VBoxGuestLib.h>
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync#include "VBoxServiceInternal.h"
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync
b0b8c85eb454e2a7ad926bbefda6d908932291e3vboxsync#ifdef VBOX_WITH_GUEST_PROPS
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync/**
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync * Reads a guest property.
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync *
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync * @returns VBox status code, fully bitched.
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync *
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync * @param u32ClientId The HGCM client ID for the guest property session.
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync * @param pszPropName The property name.
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync * @param ppszValue Where to return the value. This is always set
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync * to NULL. Free it using RTStrFree().
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync * @param ppszFlags Where to return the value flags. Free it
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync * using RTStrFree(). Optional.
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync * @param puTimestamp Where to return the timestamp. This is only set
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync * on success. Optional.
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync */
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsyncint VBoxServiceReadProp(uint32_t u32ClientId, const char *pszPropName, char **ppszValue, char **ppszFlags, uint64_t *puTimestamp)
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync{
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync size_t cbBuf = _1K;
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync void *pvBuf = NULL;
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync int rc;
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync *ppszValue = NULL;
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync for (unsigned cTries = 0; cTries < 10; cTries++)
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync {
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync /*
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync * (Re-)Allocate the buffer and try read the property.
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync */
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync RTMemFree(pvBuf);
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync pvBuf = RTMemAlloc(cbBuf);
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync if (!pvBuf)
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync {
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync VBoxServiceError("Guest Property: Failed to allocate %zu bytes\n", cbBuf);
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync rc = VERR_NO_MEMORY;
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync break;
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync }
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync char *pszValue;
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync char *pszFlags;
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync uint64_t uTimestamp;
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync rc = VbglR3GuestPropRead(u32ClientId, pszPropName,
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync pvBuf, cbBuf,
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync &pszValue, &uTimestamp, &pszFlags, NULL);
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync if (RT_FAILURE(rc))
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync {
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync if (rc == VERR_BUFFER_OVERFLOW)
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync {
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync /* try again with a bigger buffer. */
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync cbBuf *= 2;
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync continue;
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync }
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync if (rc == VERR_NOT_FOUND)
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync VBoxServiceVerbose(2, "Guest Property: %s not found\n", pszPropName);
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync else
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync VBoxServiceError("Guest Property: Failed to query \"%s\": %Rrc\n", pszPropName, rc);
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync break;
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync }
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync VBoxServiceVerbose(2, "Guest Property: Read \"%s\" = \"%s\", timestamp %RU64n\n",
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync pszPropName, pszValue, uTimestamp);
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync *ppszValue = RTStrDup(pszValue);
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync if (!*ppszValue)
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync {
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync VBoxServiceError("Guest Property: RTStrDup failed for \"%s\"\n", pszValue);
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync rc = VERR_NO_MEMORY;
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync break;
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync }
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync if (puTimestamp)
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync *puTimestamp = uTimestamp;
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync if (ppszFlags)
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync *ppszFlags = RTStrDup(pszFlags);
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync break; /* done */
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync }
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync RTMemFree(pvBuf);
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync return rc;
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync}
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync/**
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync * Reads a guest property as a 32-bit value.
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync *
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync * @returns VBox status code, fully bitched.
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync *
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync * @param u32ClientId The HGCM client ID for the guest property session.
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync * @param pszPropName The property name.
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync * @param pu32 Where to store the 32-bit value.
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync *
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync */
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsyncint VBoxServiceReadPropUInt32(uint32_t u32ClientId, const char *pszPropName, uint32_t *pu32, uint32_t u32Min, uint32_t u32Max)
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync{
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync char *pszValue;
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync int rc = VBoxServiceReadProp(u32ClientId, pszPropName, &pszValue,
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync NULL /* ppszFlags */, NULL /* puTimestamp */);
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync if (RT_SUCCESS(rc))
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync {
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync AssertPtr(pu32);
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync char *pszNext;
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync rc = RTStrToUInt32Ex(pszValue, &pszNext, 0, pu32);
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync if ( RT_SUCCESS(rc)
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync && (*pu32 < u32Min || *pu32 > u32Max))
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync {
4893c4e3513fece2ef56f559aa2370c25f12a745vboxsync rc = VBoxServiceError("The guest property value %s = %RU32 is out of range [%RU32..%RU32].\n",
4893c4e3513fece2ef56f559aa2370c25f12a745vboxsync pszPropName, *pu32, u32Min, u32Max);
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync }
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync RTStrFree(pszValue);
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync }
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync return rc;
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync}
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync
bc6df168670cfc0df5ae3be50ccbf098ba2cebc7vboxsync
019f39cc548f50d58cfdf91965f58eab1ded841bvboxsync/**
019f39cc548f50d58cfdf91965f58eab1ded841bvboxsync * Wrapper around VbglR3GuestPropWriteValue that does value formatting and
019f39cc548f50d58cfdf91965f58eab1ded841bvboxsync * logging.
019f39cc548f50d58cfdf91965f58eab1ded841bvboxsync *
019f39cc548f50d58cfdf91965f58eab1ded841bvboxsync * @returns VBox status code. Errors will be logged.
019f39cc548f50d58cfdf91965f58eab1ded841bvboxsync *
019f39cc548f50d58cfdf91965f58eab1ded841bvboxsync * @param u32ClientId The HGCM client ID for the guest property session.
019f39cc548f50d58cfdf91965f58eab1ded841bvboxsync * @param pszName The property name.
019f39cc548f50d58cfdf91965f58eab1ded841bvboxsync * @param pszValueFormat The property format string. If this is NULL then
019f39cc548f50d58cfdf91965f58eab1ded841bvboxsync * the property will be removed.
019f39cc548f50d58cfdf91965f58eab1ded841bvboxsync * @param ... Format arguments.
019f39cc548f50d58cfdf91965f58eab1ded841bvboxsync */
324b7b7cb0e3e95595f5fb069043ff3643891ba2vboxsyncint VBoxServiceWritePropF(uint32_t u32ClientId, const char *pszName, const char *pszValueFormat, ...)
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync{
23776fb44216ff7aa3b47916ef4975748de89de1vboxsync int rc;
23776fb44216ff7aa3b47916ef4975748de89de1vboxsync if (pszValueFormat != NULL)
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync {
019f39cc548f50d58cfdf91965f58eab1ded841bvboxsync /** @todo Log the value as well? just copy the guts of
019f39cc548f50d58cfdf91965f58eab1ded841bvboxsync * VbglR3GuestPropWriteValueV. */
23776fb44216ff7aa3b47916ef4975748de89de1vboxsync VBoxServiceVerbose(3, "Writing guest property \"%s\"\n", pszName);
23776fb44216ff7aa3b47916ef4975748de89de1vboxsync va_list va;
23776fb44216ff7aa3b47916ef4975748de89de1vboxsync va_start(va, pszValueFormat);
23776fb44216ff7aa3b47916ef4975748de89de1vboxsync rc = VbglR3GuestPropWriteValueV(u32ClientId, pszName, pszValueFormat, va);
23776fb44216ff7aa3b47916ef4975748de89de1vboxsync va_end(va);
23776fb44216ff7aa3b47916ef4975748de89de1vboxsync if (RT_FAILURE(rc))
23776fb44216ff7aa3b47916ef4975748de89de1vboxsync VBoxServiceError("Error writing guest property \"%s\" (rc=%Rrc)\n", pszName, rc);
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync }
23776fb44216ff7aa3b47916ef4975748de89de1vboxsync else
019f39cc548f50d58cfdf91965f58eab1ded841bvboxsync {
23776fb44216ff7aa3b47916ef4975748de89de1vboxsync rc = VbglR3GuestPropWriteValue(u32ClientId, pszName, NULL);
019f39cc548f50d58cfdf91965f58eab1ded841bvboxsync if (RT_FAILURE(rc))
019f39cc548f50d58cfdf91965f58eab1ded841bvboxsync VBoxServiceError("Error removing guest property \"%s\" (rc=%Rrc)\n", pszName, rc);
019f39cc548f50d58cfdf91965f58eab1ded841bvboxsync }
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync return rc;
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync}
b0b8c85eb454e2a7ad926bbefda6d908932291e3vboxsync#endif /* VBOX_WITH_GUEST_PROPS */
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync#ifdef RT_OS_WINDOWS
7da4d6056248b76ff6c265010bc3b8ceb06be93fvboxsync/** @todo return an iprt status code instead of BOOL */
324b7b7cb0e3e95595f5fb069043ff3643891ba2vboxsyncBOOL VBoxServiceGetFileString(const char* pszFileName,
f65e6cba3e74ffd3dc9e6053828dcc82b367e8devboxsync char* pszBlock,
f65e6cba3e74ffd3dc9e6053828dcc82b367e8devboxsync char* pszString,
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync PUINT puiSize)
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync{
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync DWORD dwHandle, dwLen = 0;
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync UINT uiDataLen = 0;
f65e6cba3e74ffd3dc9e6053828dcc82b367e8devboxsync char* lpData = NULL;
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync UINT uiValueLen = 0;
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync LPTSTR lpValue = NULL;
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync BOOL bRet = FALSE;
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync Assert(pszFileName);
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync Assert(pszBlock);
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync Assert(pszString);
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync Assert(puiSize > 0);
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync /* The VS_FIXEDFILEINFO structure contains version information about a file.
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync This information is language and code page independent. */
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync VS_FIXEDFILEINFO *pFileInfo = NULL;
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync dwLen = GetFileVersionInfoSize(pszFileName, &dwHandle);
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync if (!dwLen)
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync {
7da4d6056248b76ff6c265010bc3b8ceb06be93fvboxsync /* Don't print this to release log -- this confuses people if a file
7da4d6056248b76ff6c265010bc3b8ceb06be93fvboxsync * isn't present because it's optional / was not installed intentionally. */
7da4d6056248b76ff6c265010bc3b8ceb06be93fvboxsync VBoxServiceVerbose(3, "No file information found! File = %s, Error: %Rrc\n",
7da4d6056248b76ff6c265010bc3b8ceb06be93fvboxsync pszFileName, RTErrConvertFromWin32(GetLastError()));
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync return FALSE;
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync }
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync lpData = (LPTSTR) RTMemTmpAlloc(dwLen);
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync if (!lpData)
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync {
7da4d6056248b76ff6c265010bc3b8ceb06be93fvboxsync VBoxServiceError("Could not allocate temp buffer for file string lookup!\n");
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync return FALSE;
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync }
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync if (GetFileVersionInfo(pszFileName, dwHandle, dwLen, lpData))
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync {
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync if((bRet = VerQueryValue(lpData, pszBlock, (LPVOID*)&lpValue, (PUINT)&uiValueLen)))
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync {
f65e6cba3e74ffd3dc9e6053828dcc82b367e8devboxsync UINT uiSize = uiValueLen * sizeof(char);
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync if(uiSize > *puiSize)
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync uiSize = *puiSize;
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync ZeroMemory(pszString, *puiSize);
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync memcpy(pszString, lpValue, uiSize);
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync }
7da4d6056248b76ff6c265010bc3b8ceb06be93fvboxsync else VBoxServiceVerbose(3, "No file string value for \"%s\" in file \"%s\" available!\n", pszBlock, pszFileName);
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync }
7da4d6056248b76ff6c265010bc3b8ceb06be93fvboxsync else VBoxServiceVerbose(3, "No file version table for file \"%s\" available!\n", pszFileName);
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync RTMemFree(lpData);
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync return bRet;
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync}
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync
7da4d6056248b76ff6c265010bc3b8ceb06be93fvboxsync/** @todo return an iprt status code instead of BOOL */
324b7b7cb0e3e95595f5fb069043ff3643891ba2vboxsyncBOOL VBoxServiceGetFileVersion(const char* pszFileName,
682a27d94b9116c719038882487b99053985f91avboxsync DWORD* pdwMajor,
682a27d94b9116c719038882487b99053985f91avboxsync DWORD* pdwMinor,
682a27d94b9116c719038882487b99053985f91avboxsync DWORD* pdwBuildNumber,
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync DWORD* pdwRevisionNumber)
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync{
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync DWORD dwHandle, dwLen = 0;
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync UINT BufLen = 0;
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync LPTSTR lpData = NULL;
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync BOOL bRet = FALSE;
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync Assert(pszFileName);
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync Assert(pdwMajor);
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync Assert(pdwMinor);
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync Assert(pdwBuildNumber);
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync Assert(pdwRevisionNumber);
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync /* The VS_FIXEDFILEINFO structure contains version information about a file.
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync This information is language and code page independent. */
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync VS_FIXEDFILEINFO *pFileInfo = NULL;
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync dwLen = GetFileVersionInfoSize(pszFileName, &dwHandle);
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync /* Try own fields defined in block "\\StringFileInfo\\040904b0\\FileVersion". */
f65e6cba3e74ffd3dc9e6053828dcc82b367e8devboxsync char szValue[_MAX_PATH] = {0};
f65e6cba3e74ffd3dc9e6053828dcc82b367e8devboxsync char *pszValue = szValue;
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync UINT uiSize = _MAX_PATH;
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync int r = 0;
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync
324b7b7cb0e3e95595f5fb069043ff3643891ba2vboxsync bRet = VBoxServiceGetFileString(pszFileName, "\\StringFileInfo\\040904b0\\FileVersion", szValue, &uiSize);
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync if (bRet)
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync {
f65e6cba3e74ffd3dc9e6053828dcc82b367e8devboxsync sscanf(pszValue, "%ld.%ld.%ld.%ld", pdwMajor, pdwMinor, pdwBuildNumber, pdwRevisionNumber);
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync }
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync else if (dwLen > 0)
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync {
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync /* Try regular fields - this maybe is not file provided by VBox! */
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync lpData = (LPTSTR) RTMemTmpAlloc(dwLen);
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync if (!lpData)
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync {
7da4d6056248b76ff6c265010bc3b8ceb06be93fvboxsync VBoxServiceError("Could not allocate temp buffer for file version string!\n");
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync return FALSE;
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync }
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync if (GetFileVersionInfo(pszFileName, dwHandle, dwLen, lpData))
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync {
f65e6cba3e74ffd3dc9e6053828dcc82b367e8devboxsync if((bRet = VerQueryValue(lpData, "\\", (LPVOID*)&pFileInfo, (PUINT)&BufLen)))
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync {
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync *pdwMajor = HIWORD(pFileInfo->dwFileVersionMS);
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync *pdwMinor = LOWORD(pFileInfo->dwFileVersionMS);
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync *pdwBuildNumber = HIWORD(pFileInfo->dwFileVersionLS);
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync *pdwRevisionNumber = LOWORD(pFileInfo->dwFileVersionLS);
7da4d6056248b76ff6c265010bc3b8ceb06be93fvboxsync bRet = TRUE;
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync }
7da4d6056248b76ff6c265010bc3b8ceb06be93fvboxsync else VBoxServiceVerbose(3, "No file version value for file \"%s\" available!\n", pszFileName);
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync }
7da4d6056248b76ff6c265010bc3b8ceb06be93fvboxsync else VBoxServiceVerbose(3, "No file version struct for file \"%s\" available!\n", pszFileName);
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync RTMemFree(lpData);
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync }
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync return bRet;
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync}
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync
324b7b7cb0e3e95595f5fb069043ff3643891ba2vboxsyncBOOL VBoxServiceGetFileVersionString(const char* pszPath, const char* pszFileName, char* pszVersion, UINT uiSize)
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync{
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync BOOL bRet = FALSE;
f65e6cba3e74ffd3dc9e6053828dcc82b367e8devboxsync char szFullPath[_MAX_PATH] = {0};
f65e6cba3e74ffd3dc9e6053828dcc82b367e8devboxsync char szValue[_MAX_PATH] = {0};
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync int r = 0;
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync
f65e6cba3e74ffd3dc9e6053828dcc82b367e8devboxsync RTStrPrintf(szFullPath, 4096, "%s\\%s", pszPath, pszFileName);
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync DWORD dwMajor, dwMinor, dwBuild, dwRev;
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync
324b7b7cb0e3e95595f5fb069043ff3643891ba2vboxsync bRet = VBoxServiceGetFileVersion(szFullPath, &dwMajor, &dwMinor, &dwBuild, &dwRev);
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync if (bRet)
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync RTStrPrintf(pszVersion, uiSize, "%ld.%ld.%ldr%ld", dwMajor, dwMinor, dwBuild, dwRev);
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync else
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync RTStrPrintf(pszVersion, uiSize, "-");
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync return bRet;
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync}
7a61a5714b9a39ac3bd59e52b0843ef498350a35vboxsync#endif /* !RT_OS_WINDOWS */
682a27d94b9116c719038882487b99053985f91avboxsync