]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
vbox: Add glue layer for MSCOM on Windows
authorMatthias Bolte <matthias.bolte@googlemail.com>
Tue, 14 Dec 2010 22:07:57 +0000 (23:07 +0100)
committerMatthias Bolte <matthias.bolte@googlemail.com>
Fri, 17 Dec 2010 21:51:33 +0000 (22:51 +0100)
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
po/POTFILES.in
src/Makefile.am
src/vbox/vbox_MSCOMGlue.c [new file with mode: 0644]
src/vbox/vbox_MSCOMGlue.h [new file with mode: 0644]
src/vbox/vbox_XPCOMCGlue.c
src/vbox/vbox_XPCOMCGlue.h
src/vbox/vbox_driver.c
src/vbox/vbox_glue.c [new file with mode: 0644]
src/vbox/vbox_glue.h [new file with mode: 0644]
src/vbox/vbox_tmpl.c

index 7a53c7d78c35bddce7ac110bf94376f41e42581c..558bb7757bf9a7a1eb436f9246eea661c3eeb404 100644 (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([])
index 090de3b936967214d0e541bef2f4199779a97032..3b851f1e91ae971dbb3a6063b479c19a1cad5a12 100644 (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
index 0f28f46290bfb9d3b405a9e32b79dafe2954c514..6749786d599d120677f3c57b34734e6f4a0aa98e 100644 (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)
diff --git a/src/vbox/vbox_MSCOMGlue.c b/src/vbox/vbox_MSCOMGlue.c
new file mode 100644 (file)
index 0000000..b1663b1
--- /dev/null
@@ -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)
+{
+}
diff --git a/src/vbox/vbox_MSCOMGlue.h b/src/vbox/vbox_MSCOMGlue.h
new file mode 100644 (file)
index 0000000..1d91f09
--- /dev/null
@@ -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__ */
index d73e799c7be59ff1c9898f414d25f59d71dcb8c3..03e66bc2e7fe4e7141789e3d34df020216be82d1 100644 (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;
 }
index 6c4403087e8daddb40a583b4ccdbc03b70944db2..1fa873a26aea976e611b2cccd26ac27ac0a1e934 100644 (file)
 /* 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
index 3704f8cea6ebad39799191466dc735ed5270e689..b39a63b3ab22782fbfa67082289c5ed2632a6087 100644 (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,
diff --git a/src/vbox/vbox_glue.c b/src/vbox/vbox_glue.c
new file mode 100644 (file)
index 0000000..5fca843
--- /dev/null
@@ -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
diff --git a/src/vbox/vbox_glue.h b/src/vbox/vbox_glue.h
new file mode 100644 (file)
index 0000000..bbc244b
--- /dev/null
@@ -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__ */
index 5ae611ac99651fac48946077a231a9e8e0a9aa16..6a4589c87d45dd11bdfad317955decf6a35b0802 100644 (file)
 
 #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)