5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync/* $Id: */
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync/** @file
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync * VBoxGuestR3Lib - Ring-3 Support Library for VirtualBox guest additions, host version check.
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync */
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync/*
c7814cf6e1240a519cbec0441e033d0e2470ed00vboxsync * Copyright (C) 2009-2011 Oracle Corporation
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync *
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync * available from http://www.virtualbox.org. This file is free software;
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync * you can redistribute it and/or modify it under the terms of the GNU
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync * General Public License (GPL) as published by the Free Software
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync *
aba0e602e244ae7c4f11b50fc6d2440f5a762038vboxsync * The contents of this file may alternatively be used under the terms
aba0e602e244ae7c4f11b50fc6d2440f5a762038vboxsync * of the Common Development and Distribution License Version 1.0
aba0e602e244ae7c4f11b50fc6d2440f5a762038vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
aba0e602e244ae7c4f11b50fc6d2440f5a762038vboxsync * VirtualBox OSE distribution, in which case the provisions of the
aba0e602e244ae7c4f11b50fc6d2440f5a762038vboxsync * CDDL are applicable instead of those of the GPL.
aba0e602e244ae7c4f11b50fc6d2440f5a762038vboxsync *
aba0e602e244ae7c4f11b50fc6d2440f5a762038vboxsync * You may elect to license modified versions of this file under the
aba0e602e244ae7c4f11b50fc6d2440f5a762038vboxsync * terms and conditions of either the GPL or the CDDL or both.
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync */
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync/*******************************************************************************
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync* Header Files *
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync*******************************************************************************/
f9ee1d165e7b88ce9bb2efc9f5e77fd877ac6f65vboxsync#include <stdio.h> /* Required for sscanf */
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync#include <iprt/string.h>
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync#include <VBox/log.h>
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync#ifdef RT_OS_WINDOWS
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync #define WIN32_LEAN_AND_MEAN
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync #include <windows.h>
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync#endif
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync#include "VBGLR3Internal.h"
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync
6c25b9cd17e54772e285ccac4feea9aa92608918vboxsync/**
6c25b9cd17e54772e285ccac4feea9aa92608918vboxsync * Checks for a Guest Additions update by comparing the installed version on the
6c25b9cd17e54772e285ccac4feea9aa92608918vboxsync * guest and the reported host version.
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync *
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync * @returns VBox status code
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync *
6c25b9cd17e54772e285ccac4feea9aa92608918vboxsync * @param u32ClientId The client id returned by
6c25b9cd17e54772e285ccac4feea9aa92608918vboxsync * VbglR3InfoSvcConnect().
6c25b9cd17e54772e285ccac4feea9aa92608918vboxsync * @param pfUpdate Receives pointer to boolean flag indicating
6c25b9cd17e54772e285ccac4feea9aa92608918vboxsync * whether an update was found or not.
6c25b9cd17e54772e285ccac4feea9aa92608918vboxsync * @param ppszHostVersion Receives pointer of allocated version string.
6c25b9cd17e54772e285ccac4feea9aa92608918vboxsync * The returned pointer must be freed using
a66445f2d6971e23a9bccef243bc6000b41c05eevboxsync * VbglR3GuestPropReadValueFree(). Always set to
a66445f2d6971e23a9bccef243bc6000b41c05eevboxsync * NULL.
6c25b9cd17e54772e285ccac4feea9aa92608918vboxsync * @param ppszGuestVersion Receives pointer of allocated revision string.
6c25b9cd17e54772e285ccac4feea9aa92608918vboxsync * The returned pointer must be freed using
a66445f2d6971e23a9bccef243bc6000b41c05eevboxsync * VbglR3GuestPropReadValueFree(). Always set to
a66445f2d6971e23a9bccef243bc6000b41c05eevboxsync * NULL.
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync */
6c25b9cd17e54772e285ccac4feea9aa92608918vboxsyncVBGLR3DECL(int) VbglR3HostVersionCheckForUpdate(uint32_t u32ClientId, bool *pfUpdate, char **ppszHostVersion, char **ppszGuestVersion)
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync{
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync Assert(u32ClientId > 0);
4190631fd4f93d43354b83b613a080cba19cd45avboxsync AssertPtr(pfUpdate);
4190631fd4f93d43354b83b613a080cba19cd45avboxsync AssertPtr(ppszHostVersion);
4190631fd4f93d43354b83b613a080cba19cd45avboxsync AssertPtr(ppszGuestVersion);
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync
9f087cebed8dd0e223d1e98503ef98d8f7469fbdvboxsync *ppszHostVersion = NULL;
9f087cebed8dd0e223d1e98503ef98d8f7469fbdvboxsync *ppszGuestVersion = NULL;
9f087cebed8dd0e223d1e98503ef98d8f7469fbdvboxsync
d3cb1728da9e60397e81daace4e82d69fb5ff784vboxsync /* We assume we have an update initially.
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync Every block down below is allowed to veto */
6c25b9cd17e54772e285ccac4feea9aa92608918vboxsync *pfUpdate = true;
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync /* Do we need to do all this stuff? */
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync char *pszCheckHostVersion;
6c25b9cd17e54772e285ccac4feea9aa92608918vboxsync int rc = VbglR3GuestPropReadValueAlloc(u32ClientId, "/VirtualBox/GuestAdd/CheckHostVersion", &pszCheckHostVersion);
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync if (RT_FAILURE(rc))
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync {
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync if (rc == VERR_NOT_FOUND)
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync rc = VINF_SUCCESS; /* If we don't find the value above we do the check by default */
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync else
6c25b9cd17e54772e285ccac4feea9aa92608918vboxsync LogFlow(("Could not read check host version flag! rc = %Rrc\n", rc));
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync }
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync else
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync {
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync /* Only don't do the check if we have a valid "0" in it */
a70114bc30e757afa26f4a66475f54836a80497cvboxsync if (!strcmp(pszCheckHostVersion, "0"))
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync {
a66445f2d6971e23a9bccef243bc6000b41c05eevboxsync LogRel(("No host version update check performed (disabled).\n"));
6c25b9cd17e54772e285ccac4feea9aa92608918vboxsync *pfUpdate = false;
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync }
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync VbglR3GuestPropReadValueFree(pszCheckHostVersion);
d3cb1728da9e60397e81daace4e82d69fb5ff784vboxsync }
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync
d3cb1728da9e60397e81daace4e82d69fb5ff784vboxsync /* Collect all needed information */
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync /* Make sure we only notify the user once by comparing the host version with
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync * the last checked host version (if any) */
6c25b9cd17e54772e285ccac4feea9aa92608918vboxsync if (RT_SUCCESS(rc) && *pfUpdate)
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync {
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync /* Look up host version */
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync rc = VbglR3GuestPropReadValueAlloc(u32ClientId, "/VirtualBox/HostInfo/VBoxVer", ppszHostVersion);
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync if (RT_FAILURE(rc))
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync {
6c25b9cd17e54772e285ccac4feea9aa92608918vboxsync LogFlow(("Could not read VBox host version! rc = %Rrc\n", rc));
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync }
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync else
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync {
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync LogFlow(("Host version: %s\n", *ppszHostVersion));
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync /* Get last checked host version */
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync char *pszLastCheckedHostVersion;
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync rc = VbglR3HostVersionLastCheckedLoad(u32ClientId, &pszLastCheckedHostVersion);
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync if (RT_SUCCESS(rc))
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync {
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync LogFlow(("Last checked host version: %s\n", pszLastCheckedHostVersion));
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync if (strcmp(*ppszHostVersion, pszLastCheckedHostVersion) == 0)
6c25b9cd17e54772e285ccac4feea9aa92608918vboxsync *pfUpdate = false; /* We already notified this version, skip */
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync VbglR3GuestPropReadValueFree(pszLastCheckedHostVersion);
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync }
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync else if (rc == VERR_NOT_FOUND) /* Never wrote a last checked host version before */
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync {
a66445f2d6971e23a9bccef243bc6000b41c05eevboxsync LogFlow(("Never checked a host version before.\n"));
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync rc = VINF_SUCCESS;
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync }
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync }
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync
d3cb1728da9e60397e81daace4e82d69fb5ff784vboxsync /* Look up guest version */
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync if (RT_SUCCESS(rc))
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync {
8df35be0631db6b3ca2d388aa7f3e17f1782d093vboxsync rc = VbglR3GetAdditionsVersion(ppszGuestVersion, NULL /* Extended version not needed here */,
8df35be0631db6b3ca2d388aa7f3e17f1782d093vboxsync NULL /* Revision not needed here */);
d3cb1728da9e60397e81daace4e82d69fb5ff784vboxsync if (RT_FAILURE(rc))
6c25b9cd17e54772e285ccac4feea9aa92608918vboxsync LogFlow(("Could not read VBox guest version! rc = %Rrc\n", rc));
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync }
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync }
d3cb1728da9e60397e81daace4e82d69fb5ff784vboxsync
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync /* Do the actual version comparison (if needed, see block(s) above) */
6c25b9cd17e54772e285ccac4feea9aa92608918vboxsync if (RT_SUCCESS(rc) && *pfUpdate)
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync {
467aa5ec73ac24ab34a04b46ea812955566910dcvboxsync if (RTStrVersionCompare(*ppszHostVersion, *ppszGuestVersion) > 0) /* Is host version greater than guest add version? */
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync {
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync /* Yay, we have an update! */
a66445f2d6971e23a9bccef243bc6000b41c05eevboxsync LogRel(("Guest Additions update found! Please upgrade this machine to the latest Guest Additions.\n"));
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync }
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync else
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync {
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync /* How sad ... */
6c25b9cd17e54772e285ccac4feea9aa92608918vboxsync *pfUpdate = false;
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync }
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync }
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync /* Cleanup on failure */
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync if (RT_FAILURE(rc))
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync {
9f087cebed8dd0e223d1e98503ef98d8f7469fbdvboxsync if (*ppszHostVersion)
6c25b9cd17e54772e285ccac4feea9aa92608918vboxsync {
9f087cebed8dd0e223d1e98503ef98d8f7469fbdvboxsync VbglR3GuestPropReadValueFree(*ppszHostVersion);
6c25b9cd17e54772e285ccac4feea9aa92608918vboxsync *ppszHostVersion = NULL;
6c25b9cd17e54772e285ccac4feea9aa92608918vboxsync }
9f087cebed8dd0e223d1e98503ef98d8f7469fbdvboxsync if (*ppszGuestVersion)
6c25b9cd17e54772e285ccac4feea9aa92608918vboxsync {
9f087cebed8dd0e223d1e98503ef98d8f7469fbdvboxsync VbglR3GuestPropReadValueFree(*ppszGuestVersion);
6c25b9cd17e54772e285ccac4feea9aa92608918vboxsync *ppszGuestVersion = NULL;
6c25b9cd17e54772e285ccac4feea9aa92608918vboxsync }
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync }
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync return rc;
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync}
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync/** Retrieves the last checked host version.
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync *
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync * @returns VBox status code.
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync *
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync * @param u32ClientId The client id returned by VbglR3InfoSvcConnect().
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync * @param ppszVer Receives pointer of allocated version string.
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync * The returned pointer must be freed using RTStrFree() on VINF_SUCCESS.
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync */
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsyncVBGLR3DECL(int) VbglR3HostVersionLastCheckedLoad(uint32_t u32ClientId, char **ppszVer)
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync{
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync Assert(u32ClientId > 0);
8e6aed82b0eb0b6bed6ed2cc870921a3e6ba946cvboxsync AssertPtr(ppszVer);
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync return VbglR3GuestPropReadValueAlloc(u32ClientId, "/VirtualBox/GuestAdd/HostVerLastChecked", ppszVer);
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync}
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync/** Stores the last checked host version for later lookup.
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync * Requires strings in form of "majorVer.minorVer.build".
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync *
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync * @returns VBox status code.
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync *
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync * @param u32ClientId The client id returned by VbglR3InfoSvcConnect().
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync * @param pszVer Pointer to version string to store.
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync */
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsyncVBGLR3DECL(int) VbglR3HostVersionLastCheckedStore(uint32_t u32ClientId, const char *pszVer)
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync{
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync Assert(u32ClientId > 0);
8e6aed82b0eb0b6bed6ed2cc870921a3e6ba946cvboxsync AssertPtr(pszVer);
892354a49bac7f96155923cf8d2aa68a91c4dbd5vboxsync return VbglR3GuestPropWriteValue(u32ClientId, "/VirtualBox/GuestAdd/HostVerLastChecked", pszVer);
5bb7b06e9e2186e1f51700e01cfd58f2b5f70937vboxsync}