/** @todo Move this part in VbglR3 and just provide a callback for the platform-specific
          notification stuff, since this is very similar to the VBoxClient code. */
int VBoxCheckHostVersion(void)
{
    int rc;
    uint32_t uGuestPropSvcClientID;

    rc = VbglR3GuestPropConnect(&uGuestPropSvcClientID);
    if (RT_SUCCESS(rc))
    {
        char *pszHostVersion;
        char *pszGuestVersion;
        bool bUpdate;
        rc = VbglR3HostVersionCheckForUpdate(uGuestPropSvcClientID, &bUpdate, &pszHostVersion, &pszGuestVersion);
        if (RT_SUCCESS(rc))
        {
            if (bUpdate)
            {
                char szMsg[256]; /* Sizes according to MSDN. */
                char szTitle[64];

                /** @todo Add some translation macros here. */
                _snprintf(szTitle, sizeof(szTitle), "VirtualBox Guest Additions update available!");
                _snprintf(szMsg, sizeof(szMsg), "Your guest is currently running the Guest Additions version %s. "
                                                "We recommend updating to the latest version (%s) by choosing the "
                                                "install option from the Devices menu.", pszGuestVersion, pszHostVersion);

                rc = hlpShowBalloonTip(g_hInstance, g_hwndToolWindow, ID_TRAYICON,
                                       szMsg, szTitle,
                                       5000 /* Time to display in msec */, NIIF_INFO);
                if (RT_FAILURE(rc))
                    LogFlowFunc(("Guest Additions update found; however: could not show version notifier balloon tooltip, rc=%Rrc\n", rc));
            }

            /* Store host version to not notify again. */
            rc = VbglR3HostVersionLastCheckedStore(uGuestPropSvcClientID, pszHostVersion);

            VbglR3GuestPropReadValueFree(pszHostVersion);
            VbglR3GuestPropReadValueFree(pszGuestVersion);
        }
        VbglR3GuestPropDisconnect(uGuestPropSvcClientID);
    }
    return rc;
}
/**
 * Checks for a Guest Additions update by comparing the installed version on the
 * guest and the reported host version.
 *
 * @returns VBox status code
 *
 * @param   u32ClientId         The client id returned by
 *                              VbglR3InfoSvcConnect().
 * @param   pfUpdate            Receives pointer to boolean flag indicating
 *                              whether an update was found or not.
 * @param   ppszHostVersion     Receives pointer of allocated version string.
 *                              The returned pointer must be freed using
 *                              VbglR3GuestPropReadValueFree().  Always set to
 *                              NULL.
 * @param   ppszGuestVersion    Receives pointer of allocated revision string.
 *                              The returned pointer must be freed using
 *                              VbglR3GuestPropReadValueFree().  Always set to
 *                              NULL.
 */
VBGLR3DECL(int) VbglR3HostVersionCheckForUpdate(uint32_t u32ClientId, bool *pfUpdate, char **ppszHostVersion, char **ppszGuestVersion)
{
    Assert(u32ClientId > 0);
    AssertPtr(pfUpdate);
    AssertPtr(ppszHostVersion);
    AssertPtr(ppszGuestVersion);

    *ppszHostVersion = NULL;
    *ppszGuestVersion = NULL;

    /* We assume we have an update initially.
       Every block down below is allowed to veto */
    *pfUpdate = true;

    /* Do we need to do all this stuff? */
    char *pszCheckHostVersion;
    int rc = VbglR3GuestPropReadValueAlloc(u32ClientId, "/VirtualBox/GuestAdd/CheckHostVersion", &pszCheckHostVersion);
    if (RT_FAILURE(rc))
    {
        if (rc == VERR_NOT_FOUND)
            rc = VINF_SUCCESS; /* If we don't find the value above we do the check by default */
        else
            LogFlow(("Could not read check host version flag! rc = %Rrc\n", rc));
    }
    else
    {
        /* Only don't do the check if we have a valid "0" in it */
        if (!strcmp(pszCheckHostVersion, "0"))
        {
            LogRel(("No host version update check performed (disabled).\n"));
            *pfUpdate = false;
        }
        VbglR3GuestPropReadValueFree(pszCheckHostVersion);
    }

    /* Collect all needed information */
    /* Make sure we only notify the user once by comparing the host version with
     * the last checked host version (if any) */
    if (RT_SUCCESS(rc) && *pfUpdate)
    {
        /* Look up host version */
        rc = VbglR3GuestPropReadValueAlloc(u32ClientId, "/VirtualBox/HostInfo/VBoxVer", ppszHostVersion);
        if (RT_FAILURE(rc))
        {
            LogFlow(("Could not read VBox host version! rc = %Rrc\n", rc));
        }
        else
        {
            LogFlow(("Host version: %s\n", *ppszHostVersion));

            /* Get last checked host version */
            char *pszLastCheckedHostVersion;
            rc = VbglR3HostVersionLastCheckedLoad(u32ClientId, &pszLastCheckedHostVersion);
            if (RT_SUCCESS(rc))
            {
                LogFlow(("Last checked host version: %s\n", pszLastCheckedHostVersion));
                if (strcmp(*ppszHostVersion, pszLastCheckedHostVersion) == 0)
                    *pfUpdate = false; /* We already notified this version, skip */
                VbglR3GuestPropReadValueFree(pszLastCheckedHostVersion);
            }
            else if (rc == VERR_NOT_FOUND) /* Never wrote a last checked host version before */
            {
                LogFlow(("Never checked a host version before.\n"));
                rc = VINF_SUCCESS;
            }
        }

        /* Look up guest version */
        if (RT_SUCCESS(rc))
        {
            rc = VbglR3GetAdditionsVersion(ppszGuestVersion, NULL /* Extended version not needed here */,
                                           NULL /* Revision not needed here */);
            if (RT_FAILURE(rc))
                LogFlow(("Could not read VBox guest version! rc = %Rrc\n", rc));
        }
    }

    /* Do the actual version comparison (if needed, see block(s) above) */
    if (RT_SUCCESS(rc) && *pfUpdate)
    {
        if (RTStrVersionCompare(*ppszHostVersion, *ppszGuestVersion) > 0) /* Is host version greater than guest add version? */
        {
            /* Yay, we have an update! */
            LogRel(("Guest Additions update found! Please upgrade this machine to the latest Guest Additions.\n"));
        }
        else
        {
            /* How sad ... */
            *pfUpdate = false;
        }
    }

    /* Cleanup on failure */
    if (RT_FAILURE(rc))
    {
        if (*ppszHostVersion)
        {
            VbglR3GuestPropReadValueFree(*ppszHostVersion);
            *ppszHostVersion = NULL;
        }
        if (*ppszGuestVersion)
        {
            VbglR3GuestPropReadValueFree(*ppszGuestVersion);
            *ppszGuestVersion = NULL;
        }
    }
    return rc;
}
Exemple #3
0
/** @todo Move this part in VbglR3 and just provide a callback for the platform-specific
          notification stuff, since this is very similar to the VBoxTray code. */
static int run(struct VBCLSERVICE **ppInterface, bool fDaemonised)
{
    int rc;
    LogFlowFunc(("\n"));

    NOREF(ppInterface);
    /* Initialise the guest library. */
    rc = VbglR3InitUser();
    if (RT_FAILURE(rc))
        VBClFatalError(("Failed to connect to the VirtualBox kernel service, rc=%Rrc\n", rc));
    /* Because we need desktop notifications to be displayed, wait
     * some time to make the desktop environment load (as a work around). */
    if (fDaemonised)
        RTThreadSleep(30 * 1000 /* Wait 30 seconds */);

# ifdef VBOX_WITH_DBUS
    rc = RTDBusLoadLib();
    if (RT_FAILURE(rc))
        LogRel(("VBoxClient: D-Bus seems not to be installed; no host version check/notification done.\n"));
# else
    rc = VERR_NOT_IMPLEMENTED;
# endif /* VBOX_WITH_DBUS */

# ifdef VBOX_WITH_GUEST_PROPS
    uint32_t uGuestPropSvcClientID;
    if (RT_SUCCESS(rc))
    {
        rc = VbglR3GuestPropConnect(&uGuestPropSvcClientID);
        if (RT_FAILURE(rc))
            LogRel(("VBoxClient: Cannot connect to guest property service while chcking for host version! rc = %Rrc\n", rc));
    }

    if (RT_SUCCESS(rc))
    {
        char *pszHostVersion;
        char *pszGuestVersion;
        bool bUpdate;

        rc = VbglR3HostVersionCheckForUpdate(uGuestPropSvcClientID, &bUpdate, &pszHostVersion, &pszGuestVersion);
        if (RT_SUCCESS(rc))
        {
            if (bUpdate)
            {
                char szMsg[1024];
                char szTitle[64];

                /** @todo add some translation macros here */
                RTStrPrintf(szTitle, sizeof(szTitle), "VirtualBox Guest Additions update available!");
#ifndef VBOX_OSE
                RTStrPrintf(szMsg, sizeof(szMsg), "Your guest is currently running the Guest Additions version %s. "
                                                  "We recommend updating to the latest version (%s) by choosing the "
                                                  "install option from the Devices menu.", pszGuestVersion, pszHostVersion);
#else
/* This is the message which appears for non-Oracle builds of the
* Guest Additions.  Distributors are encouraged to customise this. */
                RTStrPrintf(szMsg, sizeof(szMsg), "Your virtual machine is currently running the Guest Additions version %s. Since you are running a version of the Guest Additions provided by the operating system you installed in the virtual machine we recommend that you update it to at least version %s using that system's update features, or alternatively that you remove this version and then install the " VBOX_VENDOR_SHORT " Guest Additions package using the install option from the Devices menu. Please consult the documentation for the operating system you are running to find out how to update or remove the current Guest Additions package.", pszGuestVersion, pszHostVersion);
#endif
                rc = showNotify(szTitle, szMsg);
                LogRel(("VBoxClient: VirtualBox Guest Additions update available!"));
                if (RT_FAILURE(rc))
                    LogRel(("VBoxClient: Could not show version notifier tooltip! rc = %d\n", rc));
            }

            /* Store host version to not notify again */
            rc = VbglR3HostVersionLastCheckedStore(uGuestPropSvcClientID, pszHostVersion);

            VbglR3GuestPropReadValueFree(pszHostVersion);
            VbglR3GuestPropReadValueFree(pszGuestVersion);
        }
        VbglR3GuestPropDisconnect(uGuestPropSvcClientID);
    }
# endif /* VBOX_WITH_GUEST_PROPS */
    VbglR3Term();
    LogFlowFunc(("returning %Rrc\n", rc));
    return rc;
}