e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync/** @file
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync * X11 guest client - host version check.
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync */
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync/*
c7814cf6e1240a519cbec0441e033d0e2470ed00vboxsync * Copyright (C) 2011-2012 Oracle Corporation
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync *
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync * available from http://www.virtualbox.org. This file is free software;
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync * you can redistribute it and/or modify it under the terms of the GNU
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync * General Public License (GPL) as published by the Free Software
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync */
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync#include <stdio.h>
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync#include <iprt/assert.h>
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync#include <iprt/err.h>
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync#include <iprt/mem.h>
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync#include <iprt/ldr.h>
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync#include <iprt/string.h>
01a633cf9bd9b8c3430065dd1e96ccfb3a9ea92avboxsync#include <iprt/thread.h>
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync#ifdef VBOX_WITH_DBUS
9baac1fd5699f1c9b16bb500a1b1785f47a895a6vboxsync# include <VBox/dbus.h>
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync#endif
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync#include <VBox/log.h>
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync#include <VBox/VBoxGuestLib.h>
9baac1fd5699f1c9b16bb500a1b1785f47a895a6vboxsync#ifdef VBOX_OSE
9baac1fd5699f1c9b16bb500a1b1785f47a895a6vboxsync# include <VBox/version.h>
9baac1fd5699f1c9b16bb500a1b1785f47a895a6vboxsync#endif
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync#include "VBoxClient.h"
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsyncstatic const char *getPidFilePath()
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync{
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync return ".vboxclient-hostversion.pid";
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync}
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsyncstatic int showNotify(const char *pcHeader, const char *pcBody)
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync{
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync int rc;
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync# ifdef VBOX_WITH_DBUS
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync DBusConnection *conn;
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync DBusMessage* msg = NULL;
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync conn = dbus_bus_get (DBUS_BUS_SESSON, NULL);
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync if (conn == NULL)
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync {
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync LogRelFlowFunc(("Could not retrieve D-BUS session bus!\n"));
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync rc = VERR_INVALID_HANDLE;
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync }
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync else
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync {
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync msg = dbus_message_new_method_call("org.freedesktop.Notifications",
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync "/org/freedesktop/Notifications",
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync "org.freedesktop.Notifications",
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync "Notify");
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync if (msg == NULL)
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync {
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync LogRel(("Could not create D-BUS message!\n"));
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync rc = VERR_INVALID_HANDLE;
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync }
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync else
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync rc = VINF_SUCCESS;
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync }
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync if (RT_SUCCESS(rc))
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync {
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync uint32_t msg_replace_id = 0;
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync const char *msg_app = "VBoxClient";
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync const char *msg_icon = "";
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync const char *msg_summary = pcHeader;
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync const char *msg_body = pcBody;
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync int32_t msg_timeout = -1; /* Let the notification server decide */
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync DBusMessageIter iter;
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync DBusMessageIter array;
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync DBusMessageIter dict;
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync DBusMessageIter value;
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync DBusMessageIter variant;
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync DBusMessageIter data;
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync /* Format: UINT32 org.freedesktop.Notifications.Notify
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync * (STRING app_name, UINT32 replaces_id, STRING app_icon, STRING summary, STRING body,
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync * ARRAY actions, DICT hints, INT32 expire_timeout)
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync */
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync dbus_message_iter_init_append(msg,&iter);
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync dbus_message_iter_append_basic(&iter,DBUS_TYPE_STRING,&msg_app);
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync dbus_message_iter_append_basic(&iter,DBUS_TYPE_UINT32,&msg_replace_id);
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync dbus_message_iter_append_basic(&iter,DBUS_TYPE_STRING,&msg_icon);
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync dbus_message_iter_append_basic(&iter,DBUS_TYPE_STRING,&msg_summary);
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync dbus_message_iter_append_basic(&iter,DBUS_TYPE_STRING,&msg_body);
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync dbus_message_iter_open_container(&iter,DBUS_TYPE_ARRAY,DBUS_TYPE_STRING_AS_STRING,&array);
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync dbus_message_iter_close_container(&iter,&array);
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync dbus_message_iter_open_container(&iter,DBUS_TYPE_ARRAY,"{sv}",&array);
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync dbus_message_iter_close_container(&iter,&array);
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync dbus_message_iter_append_basic(&iter,DBUS_TYPE_INT32,&msg_timeout);
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync DBusError err;
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync dbus_error_init(&err);
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync DBusMessage *reply;
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync reply = dbus_connection_send_with_reply_and_block(conn, msg,
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync 30 * 1000 /* 30 seconds timeout */, &err);
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync if (dbus_error_is_set(&err))
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync {
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync LogRel(("D-BUS returned an error while sending the notification: %s", err.message));
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync }
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync else if (reply)
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync {
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync dbus_connection_flush(conn);
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync dbus_message_unref(reply);
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync }
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync if (dbus_error_is_set(&err))
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync dbus_error_free(&err);
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync }
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync if (msg != NULL)
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync dbus_message_unref(msg);
917e3202179bd9460c46d8c1c4b2e34efaae1f41vboxsync# else
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync /* TODO: Implement me */
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync rc = VINF_SUCCESS;
917e3202179bd9460c46d8c1c4b2e34efaae1f41vboxsync# endif /* VBOX_WITH_DBUS */
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync return rc;
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync}
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync/** @todo Move this part in VbglR3 and just provide a callback for the platform-specific
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync notification stuff, since this is very similar to the VBoxTray code. */
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsyncstatic int run(struct VBCLSERVICE **ppInterface, bool fDaemonised)
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync{
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync int rc;
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync LogFlowFunc(("\n"));
01a633cf9bd9b8c3430065dd1e96ccfb3a9ea92avboxsync
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync NOREF(ppInterface);
77652a49779a180359203eedb2fcfab79b598939vboxsync /* Initialise the guest library. */
77652a49779a180359203eedb2fcfab79b598939vboxsync rc = VbglR3InitUser();
77652a49779a180359203eedb2fcfab79b598939vboxsync if (RT_FAILURE(rc))
77652a49779a180359203eedb2fcfab79b598939vboxsync VBClFatalError(("Failed to connect to the VirtualBox kernel service, rc=%Rrc\n", rc));
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync /* Because we need desktop notifications to be displayed, wait
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync * some time to make the desktop environment load (as a work around). */
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync if (fDaemonised)
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync RTThreadSleep(30 * 1000 /* Wait 30 seconds */);
01a633cf9bd9b8c3430065dd1e96ccfb3a9ea92avboxsync
917e3202179bd9460c46d8c1c4b2e34efaae1f41vboxsync# ifdef VBOX_WITH_DBUS
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync rc = RTDBusLoadLib();
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync if (RT_FAILURE(rc))
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync LogRel(("VBoxClient: D-Bus seems not to be installed; no host version check/notification done.\n"));
917e3202179bd9460c46d8c1c4b2e34efaae1f41vboxsync# else
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync rc = VERR_NOT_IMPLEMENTED;
917e3202179bd9460c46d8c1c4b2e34efaae1f41vboxsync# endif /* VBOX_WITH_DBUS */
917e3202179bd9460c46d8c1c4b2e34efaae1f41vboxsync
917e3202179bd9460c46d8c1c4b2e34efaae1f41vboxsync# ifdef VBOX_WITH_GUEST_PROPS
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync uint32_t uGuestPropSvcClientID;
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync if (RT_SUCCESS(rc))
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync {
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync rc = VbglR3GuestPropConnect(&uGuestPropSvcClientID);
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync if (RT_FAILURE(rc))
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync LogRel(("VBoxClient: Cannot connect to guest property service while chcking for host version! rc = %Rrc\n", rc));
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync }
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync if (RT_SUCCESS(rc))
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync {
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync char *pszHostVersion;
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync char *pszGuestVersion;
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync bool bUpdate;
917e3202179bd9460c46d8c1c4b2e34efaae1f41vboxsync
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync rc = VbglR3HostVersionCheckForUpdate(uGuestPropSvcClientID, &bUpdate, &pszHostVersion, &pszGuestVersion);
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync if (RT_SUCCESS(rc))
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync {
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync if (bUpdate)
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync {
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync char szMsg[1024];
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync char szTitle[64];
8dc8b396dcb8081d15604a6d021ead9bfb8f4438vboxsync
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync /** @todo add some translation macros here */
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync RTStrPrintf(szTitle, sizeof(szTitle), "VirtualBox Guest Additions update available!");
786cbe9c98b3640b2e3b9d71c0110ce659a4ff8evboxsync#ifndef VBOX_OSE
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync RTStrPrintf(szMsg, sizeof(szMsg), "Your guest is currently running the Guest Additions version %s. "
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync "We recommend updating to the latest version (%s) by choosing the "
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync "install option from the Devices menu.", pszGuestVersion, pszHostVersion);
786cbe9c98b3640b2e3b9d71c0110ce659a4ff8evboxsync#else
786cbe9c98b3640b2e3b9d71c0110ce659a4ff8evboxsync/* This is the message which appears for non-Oracle builds of the
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync* Guest Additions. Distributors are encouraged to customise this. */
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync 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);
786cbe9c98b3640b2e3b9d71c0110ce659a4ff8evboxsync#endif
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync rc = showNotify(szTitle, szMsg);
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync LogRel(("VBoxClient: VirtualBox Guest Additions update available!"));
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync if (RT_FAILURE(rc))
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync LogRel(("VBoxClient: Could not show version notifier tooltip! rc = %d\n", rc));
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync }
8dc8b396dcb8081d15604a6d021ead9bfb8f4438vboxsync
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync /* Store host version to not notify again */
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync rc = VbglR3HostVersionLastCheckedStore(uGuestPropSvcClientID, pszHostVersion);
8dc8b396dcb8081d15604a6d021ead9bfb8f4438vboxsync
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync VbglR3GuestPropReadValueFree(pszHostVersion);
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync VbglR3GuestPropReadValueFree(pszGuestVersion);
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync }
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync VbglR3GuestPropDisconnect(uGuestPropSvcClientID);
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync }
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync# endif /* VBOX_WITH_GUEST_PROPS */
77652a49779a180359203eedb2fcfab79b598939vboxsync VbglR3Term();
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync LogFlowFunc(("returning %Rrc\n", rc));
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync return rc;
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync}
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsyncstruct VBCLSERVICE vbclHostVersionInterface =
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync{
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync getPidFilePath,
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync VBClServiceDefaultHandler, /* init */
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync run,
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync VBClServiceDefaultHandler, /* pause */
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync VBClServiceDefaultHandler, /* resume */
2b114c590cf5a19f8047cd7bde9c7e5ae00aa22bvboxsync VBClServiceDefaultCleanup
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync};
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsyncstruct HOSTVERSIONSERVICE
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync{
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync struct VBCLSERVICE *pInterface;
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync};
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync/* Static factory */
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsyncstruct VBCLSERVICE **VBClGetHostVersionService()
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync{
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync struct HOSTVERSIONSERVICE *pService =
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync (struct HOSTVERSIONSERVICE *)RTMemAlloc(sizeof(*pService));
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync if (!pService)
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync VBClFatalError(("Out of memory\n"));
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync pService->pInterface = &vbclHostVersionInterface;
3f69769f2d22bf0277c2d17c8e7d10b147f5823fvboxsync return &pService->pInterface;
e3559ff9101568144a45ace0534bf0283d7a91bdvboxsync}
d2efe9ae01d62c0434adafe7a2b6b783d013b96dvboxsync