vbox: Add glue layer for MSCOM on Windows

Don't require dlopen, but link to ole32 and oleaut32 on Windows.

Don't expose g_pVBoxFuncs anymore. It was only used to get the
version of the API. Make VBoxCGlueInit return the version instead.
This simplifies the implementation of the MSCOM glue layer.

Get the VirtualBox version from the registry.

Add a dummy implementation of the nsIEventQueue to the MSCOM glue
as there seems to be no direct equivalent with MSCOM. It might be
implemented using the normal window message loop. This requires
additional investigation.
This commit is contained in:
Matthias Bolte 2010-12-14 23:07:57 +01:00
parent abd0e1dce7
commit 448347f8b0
11 changed files with 802 additions and 38 deletions

View File

@ -358,12 +358,23 @@ AC_DEFINE_UNQUOTED([VBOX_XPCOMC_DIR], ["$vbox_xpcomc_dir"],
[Location of directory containing VirtualBox XPCOMC library])
if test "x$with_vbox" = "xyes"; then
AC_SEARCH_LIBS([dlopen], [dl], [], [AC_MSG_ERROR([Unable to find dlopen()])])
AC_SEARCH_LIBS([dlopen], [dl],,)
case $ac_cv_search_dlopen in
no*) DLOPEN_LIBS= ;;
no*) DLOPEN_LIBS=
case "$host" in
*-*-mingw* | *-*-msvc*) ;;
*) AC_MSG_ERROR([Unable to find dlopen()]) ;;
esac ;;
*) DLOPEN_LIBS=$ac_cv_search_dlopen ;;
esac
AC_SUBST([DLOPEN_LIBS])
case "$host" in
*-*-mingw* | *-*-msvc*) MSCOM_LIBS="-lole32 -loleaut32" ;;
*) MSCOM_LIBS= ;;
esac
AC_SUBST([MSCOM_LIBS])
AC_DEFINE_UNQUOTED([WITH_VBOX], 1, [whether VirtualBox driver is enabled])
fi
AM_CONDITIONAL([WITH_VBOX], [test "$with_vbox" = "yes"])
@ -2419,6 +2430,11 @@ AC_MSG_NOTICE([ nl: $LIBNL_CFLAGS $LIBNL_LIBS])
else
AC_MSG_NOTICE([ nl: no])
fi
if test "$with_vbox" = "yes" && test -n "$MSCOM_LIBS" ; then
AC_MSG_NOTICE([ mscom: $MSCOM_LIBS])
else
AC_MSG_NOTICE([ mscom: no])
fi
AC_MSG_NOTICE([])
AC_MSG_NOTICE([Test suite])
AC_MSG_NOTICE([])

View File

@ -103,6 +103,7 @@ src/util/util.c
src/util/virtaudit.c
src/util/virterror.c
src/util/xml.c
src/vbox/vbox_MSCOMGlue.c
src/vbox/vbox_XPCOMCGlue.c
src/vbox/vbox_driver.c
src/vbox/vbox_tmpl.c

View File

@ -259,14 +259,17 @@ VMWARE_DRIVER_SOURCES = \
vmware/vmware_conf.c vmware/vmware_conf.h
VBOX_DRIVER_SOURCES = \
vbox/vbox_XPCOMCGlue.c vbox/vbox_XPCOMCGlue.h \
vbox/vbox_glue.c vbox/vbox_glue.h \
vbox/vbox_driver.c vbox/vbox_driver.h \
vbox/vbox_V2_2.c vbox/vbox_CAPI_v2_2.h \
vbox/vbox_V3_0.c vbox/vbox_CAPI_v3_0.h \
vbox/vbox_V3_1.c vbox/vbox_CAPI_v3_1.h \
vbox/vbox_V3_2.c vbox/vbox_CAPI_v3_2.h
VBOX_DRIVER_EXTRA_DIST = vbox/vbox_tmpl.c vbox/README
VBOX_DRIVER_EXTRA_DIST = \
vbox/vbox_tmpl.c vbox/README \
vbox/vbox_MSCOMGlue.c vbox/vbox_MSCOMGlue.h \
vbox/vbox_XPCOMCGlue.c vbox/vbox_XPCOMCGlue.h
QEMU_DRIVER_SOURCES = \
qemu/qemu_capabilities.c qemu/qemu_capabilities.h\
@ -634,7 +637,7 @@ libvirt_la_BUILT_LIBADD += libvirt_driver_vbox.la
endif
libvirt_driver_vbox_la_CFLAGS = \
-I@top_srcdir@/src/conf $(AM_CFLAGS)
libvirt_driver_vbox_la_LIBADD = $(DLOPEN_LIBS)
libvirt_driver_vbox_la_LIBADD = $(DLOPEN_LIBS) $(MSCOM_LIBS)
if WITH_DRIVER_MODULES
libvirt_driver_vbox_la_LIBADD += ../gnulib/lib/libgnu.la
libvirt_driver_vbox_la_LDFLAGS = -module -avoid-version $(AM_LDFLAGS)

648
src/vbox/vbox_MSCOMGlue.c Normal file
View File

@ -0,0 +1,648 @@
/*
* vbox_MSCOMGlue.c: glue to the MSCOM based VirtualBox API
*
* Copyright (C) 2010 Matthias Bolte <matthias.bolte@googlemail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <config.h>
#include <windows.h>
#define nsCID CLSID
#include "internal.h"
#include "memory.h"
#include "util.h"
#include "logging.h"
#include "virterror_internal.h"
#include "vbox_MSCOMGlue.h"
#define VIR_FROM_THIS VIR_FROM_VBOX
#define VBOX_REGKEY_ORACLE "Software\\Oracle\\VirtualBox"
#define VBOX_REGKEY_SUN "Software\\Sun\\xVM VirtualBox"
#define IVIRTUALBOX_IID_STR_v2_2 "779264f4-65ed-48ed-be39-518ca549e296"
#define ISESSION_IID_STR_v2_2 "12F4DCDB-12B2-4ec1-B7CD-DDD9F6C5BF4D"
typedef struct _VBOXXPCOMC_v1 VBOXXPCOMC_v1;
typedef struct _VBOXXPCOMC_v2 VBOXXPCOMC_v2;
struct _VBOXXPCOMC_v1 {
unsigned cb;
unsigned uVersion;
unsigned int (*pfnGetVersion)(void);
void (*pfnComInitialize)(IVirtualBox **virtualBox, ISession **session);
void (*pfnComUninitialize)(void);
void (*pfnComUnallocMem)(void *pv);
void (*pfnUtf16Free)(PRUnichar *pwszString);
void (*pfnUtf8Free)(char *pszString);
int (*pfnUtf16ToUtf8)(const PRUnichar *pwszString, char **ppszString);
int (*pfnUtf8ToUtf16)(const char *pszString, PRUnichar **ppwszString);
unsigned uEndVersion;
};
struct _VBOXXPCOMC_v2 {
unsigned cb;
unsigned uVersion;
unsigned int (*pfnGetVersion)(void);
void (*pfnComInitialize)(const char *pszVirtualBoxIID,
IVirtualBox **ppVirtualBox,
const char *pszSessionIID,
ISession **ppSession);
void (*pfnComUninitialize)(void);
void (*pfnComUnallocMem)(void *pv);
void (*pfnUtf16Free)(PRUnichar *pwszString);
void (*pfnUtf8Free)(char *pszString);
int (*pfnUtf16ToUtf8)(const PRUnichar *pwszString, char **ppszString);
int (*pfnUtf8ToUtf16)(const char *pszString, PRUnichar **ppwszString);
void (*pfnGetEventQueue)(nsIEventQueue **eventQueue);
unsigned uEndVersion;
};
PFNVBOXGETXPCOMCFUNCTIONS g_pfnGetFunctions = NULL;
static unsigned long vboxVersion;
static IVirtualBox *vboxVirtualBox;
static ISession *vboxSession;
/*
* nsISupports dummy implementation
*/
static nsresult __stdcall
vboxSupports_QueryInterface(nsISupports *pThis ATTRIBUTE_UNUSED,
const nsID *iid ATTRIBUTE_UNUSED,
void **resultp ATTRIBUTE_UNUSED)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
static nsresult __stdcall
vboxSupports_AddRef(nsISupports *pThis ATTRIBUTE_UNUSED)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
static nsresult __stdcall
vboxSupports_Release(nsISupports *pThis ATTRIBUTE_UNUSED)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
static nsresult __stdcall
vboxSupports_GetTypeInfoCount(nsISupports *pThis ATTRIBUTE_UNUSED)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
static nsresult __stdcall
vboxSupports_GetTypeInfo(nsISupports *pThis ATTRIBUTE_UNUSED)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
static nsresult __stdcall
vboxSupports_GetIDsOfNames(nsISupports *pThis ATTRIBUTE_UNUSED)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
static nsresult __stdcall
vboxSupports_Invoke(nsISupports *pThis ATTRIBUTE_UNUSED)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/*
* nsIEventTarget dummy implementation
*/
static nsresult __stdcall
vboxEventTarget_PostEvent(nsIEventTarget *pThis ATTRIBUTE_UNUSED,
PLEvent *aEvent ATTRIBUTE_UNUSED)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
static nsresult __stdcall
vboxEventTarget_IsOnCurrentThread(nsIEventTarget *pThis ATTRIBUTE_UNUSED,
PRBool *_retval ATTRIBUTE_UNUSED)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/*
* nsIEventQueue dummy implementation
*/
static nsresult __stdcall
vboxEventQueue_InitEvent(nsIEventQueue *pThis ATTRIBUTE_UNUSED,
PLEvent *aEvent ATTRIBUTE_UNUSED,
void *owner ATTRIBUTE_UNUSED,
PLHandleEventProc handler ATTRIBUTE_UNUSED,
PLDestroyEventProc destructor ATTRIBUTE_UNUSED)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
static nsresult __stdcall
vboxEventQueue_PostSynchronousEvent(nsIEventQueue *pThis ATTRIBUTE_UNUSED,
PLEvent *aEvent ATTRIBUTE_UNUSED,
void **aResult ATTRIBUTE_UNUSED)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
static nsresult __stdcall
vboxEventQueue_PendingEvents(nsIEventQueue *pThis ATTRIBUTE_UNUSED,
PRBool *_retval ATTRIBUTE_UNUSED)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
static nsresult __stdcall
vboxEventQueue_ProcessPendingEvents(nsIEventQueue *pThis ATTRIBUTE_UNUSED)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
static nsresult __stdcall
vboxEventQueue_EventLoop(nsIEventQueue *pThis ATTRIBUTE_UNUSED)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
static nsresult __stdcall
vboxEventQueue_EventAvailable(nsIEventQueue *pThis ATTRIBUTE_UNUSED,
PRBool *aResult ATTRIBUTE_UNUSED)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
static nsresult __stdcall
vboxEventQueue_GetEvent(nsIEventQueue *pThis ATTRIBUTE_UNUSED,
PLEvent **_retval ATTRIBUTE_UNUSED)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
static nsresult __stdcall
vboxEventQueue_HandleEvent(nsIEventQueue *pThis ATTRIBUTE_UNUSED,
PLEvent *aEvent ATTRIBUTE_UNUSED)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
static nsresult __stdcall
vboxEventQueue_WaitForEvent(nsIEventQueue *pThis ATTRIBUTE_UNUSED,
PLEvent **_retval ATTRIBUTE_UNUSED)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
static PRInt32 __stdcall
vboxEventQueue_GetEventQueueSelectFD(nsIEventQueue *pThis ATTRIBUTE_UNUSED)
{
return -1;
}
static nsresult __stdcall
vboxEventQueue_Init(nsIEventQueue *pThis ATTRIBUTE_UNUSED,
PRBool aNative ATTRIBUTE_UNUSED)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
static nsresult __stdcall
vboxEventQueue_InitFromPRThread(nsIEventQueue *pThis ATTRIBUTE_UNUSED,
PRThread *thread ATTRIBUTE_UNUSED,
PRBool aNative ATTRIBUTE_UNUSED)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
static nsresult __stdcall
vboxEventQueue_InitFromPLQueue(nsIEventQueue *pThis ATTRIBUTE_UNUSED,
PLEventQueue *aQueue ATTRIBUTE_UNUSED)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
static nsresult __stdcall
vboxEventQueue_EnterMonitor(nsIEventQueue *pThis ATTRIBUTE_UNUSED)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
static nsresult __stdcall
vboxEventQueue_ExitMonitor(nsIEventQueue *pThis ATTRIBUTE_UNUSED)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
static nsresult __stdcall
vboxEventQueue_RevokeEvents(nsIEventQueue *pThis ATTRIBUTE_UNUSED,
void *owner ATTRIBUTE_UNUSED)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
static nsresult __stdcall
vboxEventQueue_GetPLEventQueue(nsIEventQueue *pThis ATTRIBUTE_UNUSED,
PLEventQueue **_retval ATTRIBUTE_UNUSED)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
static nsresult __stdcall
vboxEventQueue_IsQueueNative(nsIEventQueue *pThis ATTRIBUTE_UNUSED,
PRBool *_retval ATTRIBUTE_UNUSED)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
static nsresult __stdcall
vboxEventQueue_StopAcceptingEvents(nsIEventQueue *pThis ATTRIBUTE_UNUSED)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
static struct nsIEventQueue_vtbl vboxEventQueueVtbl = {
{
{
vboxSupports_QueryInterface,
vboxSupports_AddRef,
vboxSupports_Release,
vboxSupports_GetTypeInfoCount,
vboxSupports_GetTypeInfo,
vboxSupports_GetIDsOfNames,
vboxSupports_Invoke
},
vboxEventTarget_PostEvent,
vboxEventTarget_IsOnCurrentThread
},
vboxEventQueue_InitEvent,
vboxEventQueue_PostSynchronousEvent,
vboxEventQueue_PendingEvents,
vboxEventQueue_ProcessPendingEvents,
vboxEventQueue_EventLoop,
vboxEventQueue_EventAvailable,
vboxEventQueue_GetEvent,
vboxEventQueue_HandleEvent,
vboxEventQueue_WaitForEvent,
vboxEventQueue_GetEventQueueSelectFD,
vboxEventQueue_Init,
vboxEventQueue_InitFromPRThread,
vboxEventQueue_InitFromPLQueue,
vboxEventQueue_EnterMonitor,
vboxEventQueue_ExitMonitor,
vboxEventQueue_RevokeEvents,
vboxEventQueue_GetPLEventQueue,
vboxEventQueue_IsQueueNative,
vboxEventQueue_StopAcceptingEvents,
};
static nsIEventQueue vboxEventQueue = {
&vboxEventQueueVtbl
};
static int
vboxLookupVersionInRegistry(void)
{
int result = -1;
const char *keyName = VBOX_REGKEY_ORACLE;
LONG status;
HKEY key;
DWORD type;
DWORD length;
char *value = NULL;
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyName, 0, KEY_READ, &key);
if (status != ERROR_SUCCESS) {
keyName = VBOX_REGKEY_SUN;
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyName, 0, KEY_READ, &key);
if (status != ERROR_SUCCESS) {
VIR_ERROR(_("Could not open registry key '%s' nor '%s'"),
VBOX_REGKEY_ORACLE, VBOX_REGKEY_SUN);
return -1;
}
}
status = RegQueryValueEx(key, "Version", NULL, &type, NULL, &length);
if (status != ERROR_SUCCESS) {
VIR_ERROR(_("Could not query registry value '%s\\Version'"), keyName);
goto cleanup;
}
if (type != REG_SZ) {
VIR_ERROR(_("Registry value '%s\\Version' has unexpected type"), keyName);
goto cleanup;
}
if (length < 2) {
VIR_ERROR(_("Registry value '%s\\Version' is too short"), keyName);
goto cleanup;
}
/* +1 for the null-terminator if it's missing */
if (VIR_ALLOC_N(value, length + 1) < 0) {
virReportOOMError();
goto cleanup;
}
status = RegQueryValueEx(key, "Version", NULL, NULL, (LPBYTE)value, &length);
if (status != ERROR_SUCCESS) {
VIR_ERROR(_("Could not query registry value '%s\\Version'"), keyName);
goto cleanup;
}
if (value[length - 1] != '\0') {
value[length] = '\0';
}
if (virParseVersionString(value, &vboxVersion)) {
VIR_ERROR(_("Could not parse version number from '%s'"), value);
goto cleanup;
}
result = 0;
cleanup:
VIR_FREE(value);
RegCloseKey(key);
return result;
}
static unsigned int
vboxGetVersion(void)
{
return vboxVersion;
}
static void
vboxComUnallocMem(void *pv)
{
SysFreeString(pv);
}
static void
vboxUtf16Free(PRUnichar *pwszString)
{
SysFreeString(pwszString);
}
static void
vboxUtf8Free(char *pszString)
{
VIR_FREE(pszString);
}
static int
vboxUtf16ToUtf8(const PRUnichar *pwszString, char **ppszString)
{
int length = WideCharToMultiByte(CP_UTF8, 0, pwszString, -1, NULL, 0,
NULL, NULL);
if (length < 1) {
return -1;
}
if (VIR_ALLOC_N(*ppszString, length) < 0) {
return -1;
}
return WideCharToMultiByte(CP_UTF8, 0, pwszString, -1, *ppszString,
length, NULL, NULL);
}
static int
vboxUtf8ToUtf16(const char *pszString, PRUnichar **ppwszString)
{
int length = MultiByteToWideChar(CP_UTF8, 0, pszString, -1, NULL, 0);
if (length < 1) {
return -1;
}
*ppwszString = SysAllocStringLen(NULL, length);
if (*ppwszString == NULL) {
return -1;
}
return MultiByteToWideChar(CP_UTF8, 0, pszString, -1, *ppwszString, length);
}
static void
vboxGetEventQueue(nsIEventQueue **eventQueue)
{
*eventQueue = &vboxEventQueue;
}
static void
vboxComInitialize_v2(const char *pszVirtualBoxIID, IVirtualBox **ppVirtualBox,
const char *pszSessionIID, ISession **ppSession)
{
int result = -1;
HRESULT hrc;
IID virtualBoxIID;
IID sessionIID;
char *mbsVirtualBoxIID = NULL;
char *mbsSessionIID = NULL;
PRUnichar *wcsVirtualBoxIID = NULL;
PRUnichar *wcsSessionIID = NULL;
*ppVirtualBox = NULL;
*ppSession = NULL;
CoInitialize(NULL);
if (virAsprintf(&mbsVirtualBoxIID, "{%s}", pszVirtualBoxIID) < 0 ||
virAsprintf(&mbsSessionIID, "{%s}", pszSessionIID) < 0) {
virReportOOMError();
goto cleanup;
}
if (vboxUtf8ToUtf16(mbsVirtualBoxIID, &wcsVirtualBoxIID) < 0 ||
vboxUtf8ToUtf16(mbsSessionIID, &wcsSessionIID) < 0) {
goto cleanup;
}
hrc = IIDFromString(wcsVirtualBoxIID, &virtualBoxIID);
if (FAILED(hrc)) {
VIR_ERROR(_("Could not parse IID from '%s', rc = 0x%08x"),
pszVirtualBoxIID, (unsigned int)hrc);
goto cleanup;
}
hrc = IIDFromString(wcsSessionIID, &sessionIID);
if (FAILED(hrc)) {
VIR_ERROR(_("Could not parse IID from '%s', rc = 0x%08x"),
pszVirtualBoxIID, (unsigned int)hrc);
goto cleanup;
}
hrc = CoCreateInstance(&CLSID_VirtualBox, NULL, CLSCTX_LOCAL_SERVER,
&virtualBoxIID, (void**)&vboxVirtualBox);
if (FAILED(hrc)) {
VIR_ERROR(_("Could not create VirtualBox instance, rc = 0x%08x"),
(unsigned int)hrc);
goto cleanup;
}
hrc = CoCreateInstance(&CLSID_Session, NULL, CLSCTX_INPROC_SERVER,
&sessionIID, (void**)&vboxSession);
if (FAILED(hrc)) {
VIR_ERROR(_("Could not create Session instance, rc = 0x%08x"),
(unsigned int)hrc);
goto cleanup;
}
*ppVirtualBox = vboxVirtualBox;
*ppSession = vboxSession;
result = 0;
cleanup:
if (result < 0) {
if (vboxVirtualBox != NULL) {
vboxVirtualBox->vtbl->nsisupports.Release((nsISupports *)vboxVirtualBox);
vboxVirtualBox = NULL;
}
if (vboxSession != NULL) {
vboxSession->vtbl->nsisupports.Release((nsISupports *)vboxSession);
vboxSession = NULL;
}
}
vboxUtf16Free(wcsVirtualBoxIID);
vboxUtf16Free(wcsSessionIID);
}
static void
vboxComInitialize_v1(IVirtualBox **ppVirtualBox, ISession **ppSession)
{
vboxComInitialize_v2(IVIRTUALBOX_IID_STR_v2_2, ppVirtualBox,
ISESSION_IID_STR_v2_2, ppSession);
}
static void
vboxComUninitialize(void)
{
if (vboxVirtualBox != NULL) {
vboxVirtualBox->vtbl->nsisupports.Release((nsISupports *)vboxVirtualBox);
vboxVirtualBox = NULL;
}
if (vboxSession != NULL) {
vboxSession->vtbl->nsisupports.Release((nsISupports *)vboxSession);
vboxSession = NULL;
}
CoUninitialize();
}
static VBOXXPCOMC_v1 vboxXPCOMC_v1 = {
sizeof (VBOXXPCOMC_v1), /* cb */
0x00010000U, /* uVersion */
vboxGetVersion, /* pfnGetVersion */
vboxComInitialize_v1, /* pfnComInitialize */
vboxComUninitialize, /* pfnComUninitialize */
vboxComUnallocMem, /* pfnComUnallocMem */
vboxUtf16Free, /* pfnUtf16Free */
vboxUtf8Free, /* pfnUtf8Free */
vboxUtf16ToUtf8, /* pfnUtf16ToUtf8 */
vboxUtf8ToUtf16, /* pfnUtf8ToUtf16 */
0x00010000U /* uEndVersion */
};
static VBOXXPCOMC_v2 vboxXPCOMC_v2 = {
sizeof (VBOXXPCOMC_v2), /* cb */
0x00020000U, /* uVersion */
vboxGetVersion, /* pfnGetVersion */
vboxComInitialize_v2, /* pfnComInitialize */
vboxComUninitialize, /* pfnComUninitialize */
vboxComUnallocMem, /* pfnComUnallocMem */
vboxUtf16Free, /* pfnUtf16Free */
vboxUtf8Free, /* pfnUtf8Free */
vboxUtf16ToUtf8, /* pfnUtf16ToUtf8 */
vboxUtf8ToUtf16, /* pfnUtf8ToUtf16 */
vboxGetEventQueue, /* pfnGetEventQueue */
0x00020000U /* uEndVersion */
};
static PCVBOXXPCOM
vboxGetFunctions(unsigned int version)
{
if (version == 0x00010000U) {
return (PCVBOXXPCOM)&vboxXPCOMC_v1;
} else if (version == 0x00020000U) {
return (PCVBOXXPCOM)&vboxXPCOMC_v2;
} else {
return NULL;
}
}
int
VBoxCGlueInit(unsigned int *version)
{
if (vboxLookupVersionInRegistry() < 0) {
return -1;
}
*version = vboxGetVersion();
g_pfnGetFunctions = vboxGetFunctions;
return 0;
}
void
VBoxCGlueTerm(void)
{
}

33
src/vbox/vbox_MSCOMGlue.h Normal file
View File

@ -0,0 +1,33 @@
/*
* vbox_MSCOMGlue.h: glue to the MSCOM based VirtualBox API
*
* Copyright (C) 2010 Matthias Bolte <matthias.bolte@googlemail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef __VBOX_MSCOMGLUE_H__
# define __VBOX_MSCOMGLUE_H__
# include "vbox_CAPI_v3_2.h"
extern PFNVBOXGETXPCOMCFUNCTIONS g_pfnGetFunctions;
int VBoxCGlueInit(unsigned int *version);
void VBoxCGlueTerm(void);
#endif /* __VBOX_MSCOMGLUE_H__ */

View File

@ -64,9 +64,9 @@
* Global Variables *
*******************************************************************************/
/** The dlopen handle for VBoxXPCOMC. */
void *g_hVBoxXPCOMC = NULL;
static void *hVBoxXPCOMC = NULL;
/** Pointer to the VBoxXPCOMC function table. */
PCVBOXXPCOM g_pVBoxFuncs = NULL;
static PCVBOXXPCOM pVBoxFuncs_v2_2 = NULL;
/** Pointer to VBoxGetXPCOMCFunctions for the loaded VBoxXPCOMC so/dylib/dll. */
PFNVBOXGETXPCOMCFUNCTIONS g_pfnGetFunctions = NULL;
@ -80,8 +80,11 @@ PFNVBOXGETXPCOMCFUNCTIONS g_pfnGetFunctions = NULL;
* be NULL.
* @param setAppHome Whether to set the VBOX_APP_HOME env.var. or not.
* @param ignoreMissing Whether to ignore missing library or not.
* @param version Version number of the loaded API.
*/
static int tryLoadOne(const char *dir, bool setAppHome, bool ignoreMissing)
static int
tryLoadOne(const char *dir, bool setAppHome, bool ignoreMissing,
unsigned int *version)
{
int result = -1;
char *name = NULL;
@ -122,9 +125,9 @@ static int tryLoadOne(const char *dir, bool setAppHome, bool ignoreMissing)
}
}
g_hVBoxXPCOMC = dlopen(name, RTLD_NOW | RTLD_LOCAL);
hVBoxXPCOMC = dlopen(name, RTLD_NOW | RTLD_LOCAL);
if (g_hVBoxXPCOMC == NULL) {
if (hVBoxXPCOMC == NULL) {
/*
* FIXME: Don't warn in this case as it currently breaks make check
* on systems without VirtualBox.
@ -137,7 +140,7 @@ static int tryLoadOne(const char *dir, bool setAppHome, bool ignoreMissing)
}
pfnGetFunctions = (PFNVBOXGETXPCOMCFUNCTIONS)
dlsym(g_hVBoxXPCOMC, VBOX_GET_XPCOMC_FUNCTIONS_SYMBOL_NAME);
dlsym(hVBoxXPCOMC, VBOX_GET_XPCOMC_FUNCTIONS_SYMBOL_NAME);
if (pfnGetFunctions == NULL) {
VIR_ERROR(_("Could not dlsym %s from '%s': %s"),
@ -145,14 +148,15 @@ static int tryLoadOne(const char *dir, bool setAppHome, bool ignoreMissing)
goto cleanup;
}
g_pVBoxFuncs = pfnGetFunctions(VBOX_XPCOMC_VERSION);
pVBoxFuncs_v2_2 = pfnGetFunctions(VBOX_XPCOMC_VERSION);
if (g_pVBoxFuncs == NULL) {
if (pVBoxFuncs_v2_2 == NULL) {
VIR_ERROR(_("Calling %s from '%s' failed"),
VBOX_GET_XPCOMC_FUNCTIONS_SYMBOL_NAME, name);
goto cleanup;
}
*version = pVBoxFuncs_v2_2->pfnGetVersion();
g_pfnGetFunctions = pfnGetFunctions;
result = 0;
@ -163,9 +167,9 @@ static int tryLoadOne(const char *dir, bool setAppHome, bool ignoreMissing)
}
cleanup:
if (g_hVBoxXPCOMC != NULL && result < 0) {
dlclose(g_hVBoxXPCOMC);
g_hVBoxXPCOMC = NULL;
if (hVBoxXPCOMC != NULL && result < 0) {
dlclose(hVBoxXPCOMC);
hVBoxXPCOMC = NULL;
}
VIR_FREE(name);
@ -180,7 +184,8 @@ cleanup:
*
* @returns 0 on success, -1 on failure.
*/
int VBoxCGlueInit(void)
int
VBoxCGlueInit(unsigned int *version)
{
int i;
static const char *knownDirs[] = {
@ -203,27 +208,27 @@ int VBoxCGlueInit(void)
/* If the user specifies the location, try only that. */
if (home != NULL) {
if (tryLoadOne(home, false, false) < 0) {
if (tryLoadOne(home, false, false, version) < 0) {
return -1;
}
}
/* Try the additionally configured location. */
if (VBOX_XPCOMC_DIR[0] != '\0') {
if (tryLoadOne(VBOX_XPCOMC_DIR, true, true) >= 0) {
if (tryLoadOne(VBOX_XPCOMC_DIR, true, true, version) >= 0) {
return 0;
}
}
/* Try the known locations. */
for (i = 0; i < ARRAY_CARDINALITY(knownDirs); ++i) {
if (tryLoadOne(knownDirs[i], true, true) >= 0) {
if (tryLoadOne(knownDirs[i], true, true, version) >= 0) {
return 0;
}
}
/* Finally try the dynamic linker search path. */
if (tryLoadOne(NULL, false, true) >= 0) {
if (tryLoadOne(NULL, false, true, version) >= 0) {
return 0;
}
@ -235,15 +240,16 @@ int VBoxCGlueInit(void)
/**
* Terminate the C glue library.
*/
void VBoxCGlueTerm(void)
void
VBoxCGlueTerm(void)
{
if (g_hVBoxXPCOMC != NULL) {
if (hVBoxXPCOMC != NULL) {
#if 0 /* VBoxRT.so doesn't like being reloaded. See @bugref{3725}. */
dlclose(g_hVBoxXPCOMC);
#endif
g_hVBoxXPCOMC = NULL;
hVBoxXPCOMC = NULL;
}
g_pVBoxFuncs = NULL;
pVBoxFuncs_v2_2 = NULL;
g_pfnGetFunctions = NULL;
}

View File

@ -32,12 +32,10 @@
/* This has to be the oldest version we support. */
# include "vbox_CAPI_v2_2.h"
/** Pointer to the VBoxXPCOMC function table. */
extern PCVBOXXPCOM g_pVBoxFuncs;
/** Pointer to VBoxGetXPCOMCFunctions for the loaded VBoxXPCOMC so/dylib/dll. */
extern PFNVBOXGETXPCOMCFUNCTIONS g_pfnGetFunctions;
int VBoxCGlueInit(void);
int VBoxCGlueInit(unsigned int *version);
void VBoxCGlueTerm(void);
#endif

View File

@ -38,8 +38,9 @@
#include "datatypes.h"
#include "logging.h"
#include "vbox_driver.h"
#include "vbox_XPCOMCGlue.h"
#include "vbox_glue.h"
#include "virterror_internal.h"
#include "util.h"
#define VIR_FROM_THIS VIR_FROM_VBOX
@ -82,8 +83,7 @@ int vboxRegister(void) {
storageDriver = &vbox22StorageDriver;
/* Init the glue and get the API version. */
if (VBoxCGlueInit() == 0) {
uVersion = g_pVBoxFuncs->pfnGetVersion();
if (VBoxCGlueInit(&uVersion) == 0) {
DEBUG("VBoxCGlueInit found API version: %d.%d.%d (%u)",
uVersion / 1000000,
uVersion % 1000000 / 1000,

29
src/vbox/vbox_glue.c Normal file
View File

@ -0,0 +1,29 @@
/*
* vbox_glue.c: glue to the VirtualBox API
*
* Copyright (C) 2010 Matthias Bolte <matthias.bolte@googlemail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <config.h>
#ifdef WIN32
# include "vbox_MSCOMGlue.c"
#else
# include "vbox_XPCOMCGlue.c"
#endif

32
src/vbox/vbox_glue.h Normal file
View File

@ -0,0 +1,32 @@
/*
* vbox_glue.h: glue to the VirtualBox API
*
* Copyright (C) 2010 Matthias Bolte <matthias.bolte@googlemail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef __VBOX_GLUE_H__
# define __VBOX_GLUE_H__
# ifdef WIN32
# include "vbox_MSCOMGlue.h"
# else
# include "vbox_XPCOMCGlue.h"
# endif
#endif /* __VBOX_GLUE_H__ */

View File

@ -34,12 +34,11 @@
#include <config.h>
#include <dlfcn.h>
#include <sys/utsname.h>
#include <stdbool.h>
#include <unistd.h>
#include "internal.h"
#include "datatypes.h"
#include "domain_conf.h"
#include "network_conf.h"
@ -68,7 +67,7 @@
#endif
/* Include this *last* or we'll get the wrong vbox_CAPI_*.h. */
#include "vbox_XPCOMCGlue.h"
#include "vbox_glue.h"
#define VIR_FROM_THIS VIR_FROM_VBOX
@ -705,10 +704,9 @@ no_memory:
return NULL;
}
static int vboxInitialize(vboxGlobalData *data) {
/* Get the API table for out version, g_pVBoxFuncs is for the oldest
version of the API that we support so we cannot use that. */
static int
vboxInitialize(vboxGlobalData *data)
{
data->pFuncs = g_pfnGetFunctions(VBOX_XPCOMC_VERSION);
if (data->pFuncs == NULL)