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