[libvirt] [PATCH 3/6] vbox: Add glue layer for MSCOM on Windows

Matthias Bolte matthias.bolte at googlemail.com
Fri Dec 17 18:56:26 UTC 2010


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.
---
 configure.ac               |   15 +-
 po/POTFILES.in             |    1 +
 src/Makefile.am            |    9 +-
 src/vbox/vbox_MSCOMGlue.c  |  649 ++++++++++++++++++++++++++++++++++++++++++++
 src/vbox/vbox_MSCOMGlue.h  |   33 +++
 src/vbox/vbox_XPCOMCGlue.c |   46 ++--
 src/vbox/vbox_XPCOMCGlue.h |    4 +-
 src/vbox/vbox_driver.c     |    6 +-
 src/vbox/vbox_glue.c       |   29 ++
 src/vbox/vbox_glue.h       |   32 +++
 src/vbox/vbox_tmpl.c       |   12 +-
 11 files changed, 798 insertions(+), 38 deletions(-)
 create mode 100644 src/vbox/vbox_MSCOMGlue.c
 create mode 100644 src/vbox/vbox_MSCOMGlue.h
 create mode 100644 src/vbox/vbox_glue.c
 create mode 100644 src/vbox/vbox_glue.h

diff --git a/configure.ac b/configure.ac
index 64e76dc..cedd50f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -352,12 +352,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"])
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 355df0b..0f4cf70 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -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
diff --git a/src/Makefile.am b/src/Makefile.am
index 64e890f..d72a929 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -257,14 +257,17 @@ OPENVZ_DRIVER_SOURCES =						\
 		openvz/openvz_driver.c openvz/openvz_driver.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\
@@ -617,7 +620,7 @@ libvirt_la_BUILT_LIBADD += libvirt_driver_vbox.la
 endif
 libvirt_driver_vbox_la_CFLAGS = \
 		-I at 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)
diff --git a/src/vbox/vbox_MSCOMGlue.c b/src/vbox/vbox_MSCOMGlue.c
new file mode 100644
index 0000000..81a2c99
--- /dev/null
+++ b/src/vbox/vbox_MSCOMGlue.c
@@ -0,0 +1,648 @@
+
+/*
+ * vbox_MSCOMGlue.c: glue to the MSCOM based VirtualBox API
+ *
+ * Copyright (C) 2010 Matthias Bolte <matthias.bolte at 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 = NULL;
+static ISession *vboxSession = NULL;
+
+
+
+/*
+ * 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)
+{
+}
diff --git a/src/vbox/vbox_MSCOMGlue.h b/src/vbox/vbox_MSCOMGlue.h
new file mode 100644
index 0000000..1d91f09
--- /dev/null
+++ b/src/vbox/vbox_MSCOMGlue.h
@@ -0,0 +1,33 @@
+
+/*
+ * vbox_MSCOMGlue.h: glue to the MSCOM based VirtualBox API
+ *
+ * Copyright (C) 2010 Matthias Bolte <matthias.bolte at 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__ */
diff --git a/src/vbox/vbox_XPCOMCGlue.c b/src/vbox/vbox_XPCOMCGlue.c
index d73e799..03e66bc 100644
--- a/src/vbox/vbox_XPCOMCGlue.c
+++ b/src/vbox/vbox_XPCOMCGlue.c
@@ -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;
 }
diff --git a/src/vbox/vbox_XPCOMCGlue.h b/src/vbox/vbox_XPCOMCGlue.h
index 6c44030..1fa873a 100644
--- a/src/vbox/vbox_XPCOMCGlue.h
+++ b/src/vbox/vbox_XPCOMCGlue.h
@@ -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
diff --git a/src/vbox/vbox_driver.c b/src/vbox/vbox_driver.c
index 3704f8c..b39a63b 100644
--- a/src/vbox/vbox_driver.c
+++ b/src/vbox/vbox_driver.c
@@ -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,
diff --git a/src/vbox/vbox_glue.c b/src/vbox/vbox_glue.c
new file mode 100644
index 0000000..5fca843
--- /dev/null
+++ b/src/vbox/vbox_glue.c
@@ -0,0 +1,29 @@
+
+/*
+ * vbox_glue.c: glue to the VirtualBox API
+ *
+ * Copyright (C) 2010 Matthias Bolte <matthias.bolte at 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
diff --git a/src/vbox/vbox_glue.h b/src/vbox/vbox_glue.h
new file mode 100644
index 0000000..bbc244b
--- /dev/null
+++ b/src/vbox/vbox_glue.h
@@ -0,0 +1,32 @@
+
+/*
+ * vbox_glue.h: glue to the VirtualBox API
+ *
+ * Copyright (C) 2010 Matthias Bolte <matthias.bolte at 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__ */
diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index 5ae611a..6a4589c 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -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)
-- 
1.7.0.4




More information about the libvir-list mailing list