summaryrefslogtreecommitdiffstats
path: root/src/VBox/Main/cbinding
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-11 08:17:27 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-11 08:17:27 +0000
commitf215e02bf85f68d3a6106c2a1f4f7f063f819064 (patch)
tree6bb5b92c046312c4e95ac2620b10ddf482d3fa8b /src/VBox/Main/cbinding
parentInitial commit. (diff)
downloadvirtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.tar.xz
virtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.zip
Adding upstream version 7.0.14-dfsg.upstream/7.0.14-dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/Main/cbinding')
-rw-r--r--src/VBox/Main/cbinding/Makefile.kmk158
-rw-r--r--src/VBox/Main/cbinding/VBoxCAPI.cpp1023
-rw-r--r--src/VBox/Main/cbinding/VBoxCAPI.rc61
-rw-r--r--src/VBox/Main/cbinding/VBoxCAPIGlue.c345
-rw-r--r--src/VBox/Main/cbinding/VBoxCAPIGlue.h.in68
-rw-r--r--src/VBox/Main/cbinding/capiidl.xsl2736
-rw-r--r--src/VBox/Main/cbinding/makefile.tstCAPIGlue63
-rw-r--r--src/VBox/Main/cbinding/tstCAPIGlue.c1145
8 files changed, 5599 insertions, 0 deletions
diff --git a/src/VBox/Main/cbinding/Makefile.kmk b/src/VBox/Main/cbinding/Makefile.kmk
new file mode 100644
index 00000000..7f45b28c
--- /dev/null
+++ b/src/VBox/Main/cbinding/Makefile.kmk
@@ -0,0 +1,158 @@
+# $Id: Makefile.kmk $
+## @file
+# Sub-Makefile for the VBox C Binding.
+#
+
+#
+# Copyright (C) 2009-2023 Oracle and/or its affiliates.
+#
+# This file is part of VirtualBox base platform packages, as
+# available from https://www.virtualbox.org.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation, in version 3 of the
+# License.
+#
+# This program 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
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses>.
+#
+# SPDX-License-Identifier: GPL-3.0-only
+#
+
+SUB_DEPTH = ../../../..
+include $(KBUILD_PATH)/subheader.kmk
+
+
+#
+# The samples
+#
+INSTALLS += CAPISamples
+CAPISamples_MODE = a+r,u+rw
+CAPISamples_INST = \
+ $(INST_SDK)bindings/c/samples/
+CAPISamples_SOURCES = \
+ tstCAPIGlue.c \
+ makefile.tstCAPIGlue=>Makefile
+
+#
+# The ???.
+#
+INSTALLS += CAPIGlue
+CAPIGlue_MODE = a+r,u+rw
+CAPIGlue_INST = \
+ $(INST_SDK)bindings/c/glue/
+CAPIGlue_SOURCES = \
+ VBoxCAPIGlue.c \
+ $(CAPIHeaders_0_OUTDIR)/VBoxCAPIGlue.h
+CAPIGlue_CLEAN = \
+ $(CAPIHeaders_0_OUTDIR)/VBoxCAPIGlue.h
+
+$$(CAPIHeaders_0_OUTDIR)/VBoxCAPIGlue.h: \
+ $(PATH_SUB_CURRENT)/VBoxCAPIGlue.h.in \
+ $(MAKEFILE_CURRENT) \
+ | $$(dir $$@)
+ $(call MSG_GENERATE,,$@)
+ $(QUIET)$(SED) \
+ -e 's/@VBOX_API_VERSION@/$(VBOX_API_VERSION)/' \
+ < $< > $@
+
+#
+# The ???.
+#
+INSTALLS += CAPIHeaders
+CAPIHeaders_MODE = a+r,u+rw
+CAPIHeaders_INST = $(INST_SDK)bindings/c/include/
+CAPIHeaders_SOURCES = \
+ $(CAPIHeaders_0_OUTDIR)/VBoxCAPI.h=>VBoxCAPI_v$(VBOX_API_VERSION).h
+CAPIHeaders_CLEAN = \
+ $(CAPIHeaders_0_OUTDIR)/VBoxCAPI.h
+
+$$(CAPIHeaders_0_OUTDIR)/VBoxCAPI.h: \
+ $(PATH_SUB_CURRENT)/capiidl.xsl \
+ $(PATH_SUB_CURRENT)/../idl/typemap-shared.inc.xsl \
+ $(VBOX_XIDL_FILE) \
+ | $$(dir $$@)
+ $(call MSG_TOOL,xsltproc,CAPIHeaders,$<,$@)
+ $(QUIET)$(VBOX_XSLTPROC) -o $@ $^
+
+ifndef VBOX_ONLY_SDK
+
+ #
+ # The C API binding utility DLL
+ #
+ DLLS += VBoxCAPI
+ VBoxCAPI_TEMPLATE = VBoxMainClientDll
+ ifdef VBOX_WITH_XPCOM
+ # Keep old name on XPCOM so that legacy code is happy.
+ VBoxCAPI_INST = $(INST_BIN)VBoxXPCOMC$(VBOX_SUFF_DLL)
+ endif
+ VBoxCAPI_DEFS = IN_VBOXCAPI
+ VBoxCAPI_SOURCES = \
+ VBoxCAPI.cpp
+ VBoxCAPI_SOURCES.win = \
+ VBoxCAPI.rc
+ VBoxCAPI_INCS = \
+ $(CAPIHeaders_0_OUTDIR)
+ VBoxCAPI_INTERMEDIATES = \
+ $(CAPIHeaders_0_OUTDIR)/VBoxCAPI.h
+
+ #
+ # The C glue library.
+ #
+ LIBRARIES += VBoxCAPIGlue
+ VBoxCAPIGlue_TEMPLATE = VBoxMainExe
+ VBoxCAPIGlue_DEFS = IN_VBOXCAPI
+ VBoxCAPIGlue_SOURCES = \
+ VBoxCAPIGlue.c
+ ifdef VBOX_WITH_XPCOM
+ VBoxCAPIGlue_SOURCES += \
+ $(VBOX_PATH_SDK)/bindings/xpcom/lib/VirtualBox_i.c
+ else
+ VBoxCAPIGlue_SOURCES += \
+ $(VBOX_PATH_SDK)/bindings/mscom/lib/VirtualBox_i.c
+ endif
+ VBoxCAPIGlue_INCS = \
+ $(VBOX_PATH_SDK)/bindings/c/include \
+ $(VBOX_PATH_SDK)/bindings/c/glue
+ VBoxCAPIGlue_INTERMEDIATES = \
+ $(VBOX_PATH_SDK)/bindings/c/glue/VBoxCAPIGlue.h \
+ $(VBOX_PATH_SDK)/bindings/c/include/VBoxCAPI_v$(VBOX_API_VERSION).h
+
+ if defined(VBOX_WITH_TESTCASES) && "$(KBUILD_TARGET)" != "darwin"
+ #
+ # The testcase (also in samples).
+ # C testcase using the dynamic glue.
+ #
+ PROGRAMS += tstCAPIGlue
+ tstCAPIGlue_TEMPLATE = VBoxR3TstExe
+ tstCAPIGlue_INCS = \
+ $(VBOX_PATH_SDK)/bindings/c/include \
+ $(VBOX_PATH_SDK)/bindings/c/glue
+ ifdef VBOX_WITH_XPCOM
+ tstCAPIGlue_INCS += \
+ $(VBOX_PATH_SDK)/bindings/xpcom/include
+ else
+ tstCAPIGlue_INCS += \
+ $(VBOX_PATH_SDK)/bindings/mscom/include
+ endif
+ tstCAPIGlue_INTERMEDIATES = \
+ $(VBOX_PATH_SDK)/bindings/c/glue/VBoxCAPIGlue.h \
+ $(VBOX_PATH_SDK)/bindings/c/include/VBoxCAPI_v$(VBOX_API_VERSION).h \
+ $(if-expr !defined(VBOX_WITH_XPCOM),$(VBOX_PATH_SDK)/bindings/mscom/include/VirtualBox.h,)
+ tstCAPIGlue_SOURCES = \
+ tstCAPIGlue.c
+ tstCAPIGlue_LIBS = \
+ $(VBoxCAPIGlue_1_TARGET)
+ endif
+
+endif # !VBOX_ONLY_SDK
+
+# generate rules.
+include $(FILE_KBUILD_SUB_FOOTER)
+
diff --git a/src/VBox/Main/cbinding/VBoxCAPI.cpp b/src/VBox/Main/cbinding/VBoxCAPI.cpp
new file mode 100644
index 00000000..52d951e1
--- /dev/null
+++ b/src/VBox/Main/cbinding/VBoxCAPI.cpp
@@ -0,0 +1,1023 @@
+/* $Id: VBoxCAPI.cpp $ */
+/** @file VBoxCAPI.cpp
+ * Utility functions to use with the C API binding.
+ */
+
+/*
+ * Copyright (C) 2009-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#define LOG_GROUP LOG_GROUP_MAIN
+
+#include "VBoxCAPI.h"
+
+#ifdef VBOX_WITH_XPCOM
+# include <nsMemory.h>
+# include <nsIServiceManager.h>
+# include <nsEventQueueUtils.h>
+# include <nsIExceptionService.h>
+# include <stdlib.h>
+#endif /* VBOX_WITH_XPCOM */
+
+#include <iprt/env.h>
+#include <iprt/err.h>
+#include <iprt/initterm.h>
+#include <iprt/mem.h>
+#include <iprt/string.h>
+#include <iprt/utf16.h>
+#include <iprt/uuid.h>
+#include <VBox/log.h>
+#include <VBox/version.h>
+
+#include "VBox/com/com.h"
+#include "VBox/com/NativeEventQueue.h"
+
+
+#ifndef RT_OS_DARWIN /* Probably not used for xpcom, so clang gets upset: error: using directive refers to implicitly-defined namespace 'std' [-Werror]*/
+using namespace std;
+#endif
+
+/* The following 2 object references should be eliminated once the legacy
+ * way to initialize the COM/XPCOM C bindings is removed. */
+static ISession *g_Session = NULL;
+static IVirtualBox *g_VirtualBox = NULL;
+
+#ifdef VBOX_WITH_XPCOM
+/* This object reference should be eliminated once the legacy way of handling
+ * the event queue (XPCOM specific) is removed. */
+static nsIEventQueue *g_EventQueue = NULL;
+#endif /* VBOX_WITH_XPCOM */
+
+static void VBoxComUninitialize(void);
+static void VBoxClientUninitialize(void);
+
+static int
+VBoxUtf16ToUtf8(CBSTR pwszString, char **ppszString)
+{
+ if (!pwszString)
+ {
+ *ppszString = NULL;
+ return VINF_SUCCESS;
+ }
+ return RTUtf16ToUtf8(pwszString, ppszString);
+}
+
+static int
+VBoxUtf8ToUtf16(const char *pszString, BSTR *ppwszString)
+{
+ *ppwszString = NULL;
+ if (!pszString)
+ return VINF_SUCCESS;
+#ifdef VBOX_WITH_XPCOM
+ return RTStrToUtf16(pszString, ppwszString);
+#else /* !VBOX_WITH_XPCOM */
+ PRTUTF16 pwsz;
+ int vrc = RTStrToUtf16(pszString, &pwsz);
+ if (RT_SUCCESS(vrc))
+ {
+ *ppwszString = ::SysAllocString(pwsz);
+ if (!*ppwszString)
+ vrc = VERR_NO_STR_MEMORY;
+ RTUtf16Free(pwsz);
+ }
+ return vrc;
+#endif /* !VBOX_WITH_XPCOM */
+}
+
+static void
+VBoxUtf8Clear(char *pszString)
+{
+ RT_BZERO(pszString, strlen(pszString));
+}
+
+static void
+VBoxUtf16Clear(BSTR pwszString)
+{
+ RT_BZERO(pwszString, RTUtf16Len(pwszString) * sizeof(RTUTF16));
+}
+
+static void
+VBoxUtf16Free(BSTR pwszString)
+{
+#ifdef VBOX_WITH_XPCOM
+ RTUtf16Free(pwszString);
+#else
+ ::SysFreeString(pwszString);
+#endif
+}
+
+static void
+VBoxUtf8Free(char *pszString)
+{
+ RTStrFree(pszString);
+}
+
+static void
+VBoxComUnallocString(BSTR pwsz)
+{
+ if (pwsz)
+ {
+#ifdef VBOX_WITH_XPCOM
+ nsMemory::Free(pwsz);
+#else
+ ::SysFreeString(pwsz);
+#endif
+ }
+}
+
+static void
+VBoxComUnallocMem(void *pv)
+{
+ VBoxComUnallocString((BSTR)pv);
+}
+
+static ULONG
+VBoxVTElemSize(VARTYPE vt)
+{
+ switch (vt)
+ {
+ case VT_BOOL:
+ case VT_I1:
+ case VT_UI1:
+ return 1;
+ case VT_I2:
+ case VT_UI2:
+ return 2;
+ case VT_I4:
+ case VT_UI4:
+ case VT_HRESULT:
+ return 4;
+ case VT_I8:
+ case VT_UI8:
+ return 8;
+ case VT_BSTR:
+ case VT_DISPATCH:
+ case VT_UNKNOWN:
+ return sizeof(void *);
+ default:
+ return 0;
+ }
+}
+
+static SAFEARRAY *
+VBoxSafeArrayCreateVector(VARTYPE vt, LONG lLbound, ULONG cElements)
+{
+#ifdef VBOX_WITH_XPCOM
+ NOREF(lLbound);
+ ULONG cbElement = VBoxVTElemSize(vt);
+ if (!cbElement)
+ return NULL;
+ SAFEARRAY *psa = (SAFEARRAY *)RTMemAllocZ(sizeof(SAFEARRAY));
+ if (!psa)
+ return psa;
+ if (cElements)
+ {
+ void *pv = nsMemory::Alloc(cElements * cbElement);
+ if (!pv)
+ {
+ RTMemFree(psa);
+ return NULL;
+ }
+ psa->pv = pv;
+ psa->c = cElements;
+ }
+ return psa;
+#else /* !VBOX_WITH_XPCOM */
+ return SafeArrayCreateVector(vt, lLbound, cElements);
+#endif /* !VBOX_WITH_XPCOM */
+}
+
+static SAFEARRAY *
+VBoxSafeArrayOutParamAlloc(void)
+{
+#ifdef VBOX_WITH_XPCOM
+ return (SAFEARRAY *)RTMemAllocZ(sizeof(SAFEARRAY));
+#else /* !VBOX_WITH_XPCOM */
+ return NULL;
+#endif /* !VBOX_WITH_XPCOM */
+}
+
+static HRESULT
+VBoxSafeArrayDestroy(SAFEARRAY *psa)
+{
+#ifdef VBOX_WITH_XPCOM
+ if (psa)
+ {
+ if (psa->pv)
+ nsMemory::Free(psa->pv);
+ RTMemFree(psa);
+ }
+ return S_OK;
+#else /* !VBOX_WITH_XPCOM */
+ VARTYPE vt = VT_UNKNOWN;
+ HRESULT hrc = SafeArrayGetVartype(psa, &vt);
+ if (FAILED(hrc))
+ return hrc;
+ if (vt == VT_BSTR)
+ {
+ /* Special treatment: strings are to be freed explicitly, see sample
+ * C binding code, so zap it here. No way to reach compatible code
+ * behavior between COM and XPCOM without this kind of trickery. */
+ void *pData;
+ hrc = SafeArrayAccessData(psa, &pData);
+ if (FAILED(hrc))
+ return hrc;
+ ULONG cbElement = VBoxVTElemSize(vt);
+ if (!cbElement)
+ return E_INVALIDARG;
+ Assert(cbElement = psa->cbElements);
+ ULONG cElements = psa->rgsabound[0].cElements;
+ memset(pData, '\0', cbElement * cElements);
+ SafeArrayUnaccessData(psa);
+ }
+ return SafeArrayDestroy(psa);
+#endif /* !VBOX_WITH_XPCOM */
+}
+
+static HRESULT
+VBoxSafeArrayCopyInParamHelper(SAFEARRAY *psa, const void *pv, ULONG cb)
+{
+ if (!pv || !psa)
+ return E_POINTER;
+ if (!cb)
+ return S_OK;
+
+ void *pData;
+#ifdef VBOX_WITH_XPCOM
+ pData = psa->pv;
+#else /* !VBOX_WITH_XPCOM */
+ HRESULT hrc = SafeArrayAccessData(psa, &pData);
+ if (FAILED(hrc))
+ return hrc;
+#endif /* !VBOX_WITH_XPCOM */
+ memcpy(pData, pv, cb);
+#ifndef VBOX_WITH_XPCOM
+ SafeArrayUnaccessData(psa);
+#endif
+ return S_OK;
+}
+
+static HRESULT
+VBoxSafeArrayCopyOutParamHelper(void **ppv, ULONG *pcb, VARTYPE vt, SAFEARRAY *psa)
+{
+ if (!ppv)
+ return E_POINTER;
+ ULONG cbElement = VBoxVTElemSize(vt);
+ if (!cbElement)
+ {
+ *ppv = NULL;
+ if (pcb)
+ *pcb = 0;
+ return E_INVALIDARG;
+ }
+#ifndef VBOX_WITH_XPCOM
+ if (psa->cDims != 1)
+ {
+ *ppv = NULL;
+ if (pcb)
+ *pcb = 0;
+ return E_INVALIDARG;
+ }
+ Assert(cbElement = psa->cbElements);
+#endif /* !VBOX_WITH_XPCOM */
+ void *pData;
+ ULONG cElements;
+#ifdef VBOX_WITH_XPCOM
+ pData = psa->pv;
+ cElements = psa->c;
+#else /* !VBOX_WITH_XPCOM */
+ HRESULT hrc = SafeArrayAccessData(psa, &pData);
+ if (FAILED(hrc))
+ {
+ *ppv = NULL;
+ if (pcb)
+ *pcb = 0;
+ return hrc;
+ }
+ cElements = psa->rgsabound[0].cElements;
+#endif /* !VBOX_WITH_XPCOM */
+ size_t cbTotal = cbElement * cElements;
+ void *pv = NULL;
+ if (cbTotal)
+ {
+ pv = malloc(cbTotal);
+ if (!pv)
+ {
+ *ppv = NULL;
+ if (pcb)
+ *pcb = 0;
+ return E_OUTOFMEMORY;
+ }
+ else
+ memcpy(pv, pData, cbTotal);
+ }
+ *ppv = pv;
+ if (pcb)
+ *pcb = (ULONG)cbTotal;
+#ifndef VBOX_WITH_XPCOM
+ SafeArrayUnaccessData(psa);
+#endif
+ return S_OK;
+}
+
+static HRESULT
+VBoxSafeArrayCopyOutIfaceParamHelper(IUnknown ***ppaObj, ULONG *pcObj, SAFEARRAY *psa)
+{
+ ULONG mypcb;
+ HRESULT hrc = VBoxSafeArrayCopyOutParamHelper((void **)ppaObj, &mypcb, VT_UNKNOWN, psa);
+ if (FAILED(hrc))
+ {
+ if (pcObj)
+ *pcObj = 0;
+ return hrc;
+ }
+ ULONG cElements = mypcb / sizeof(void *);
+ if (pcObj)
+ *pcObj = cElements;
+#ifndef VBOX_WITH_XPCOM
+ /* Do this only for COM, as there the SAFEARRAY destruction will release
+ * the contained references automatically. XPCOM doesn't do that, which
+ * means that copying implicitly transfers ownership. */
+ IUnknown **paObj = *ppaObj;
+ for (ULONG i = 0; i < cElements; i++)
+ {
+ IUnknown *pObj = paObj[i];
+ if (pObj)
+ pObj->AddRef();
+ }
+#endif /* VBOX_WITH_XPCOM */
+ return S_OK;
+}
+
+static HRESULT
+VBoxArrayOutFree(void *pv)
+{
+ free(pv);
+ return S_OK;
+}
+
+static void
+VBoxComInitialize(const char *pszVirtualBoxIID, IVirtualBox **ppVirtualBox,
+ const char *pszSessionIID, ISession **ppSession)
+{
+ int vrc;
+ IID virtualBoxIID;
+ IID sessionIID;
+
+ *ppSession = NULL;
+ *ppVirtualBox = NULL;
+
+ /* convert the string representation of the UUIDs (if provided) to IID */
+ if (pszVirtualBoxIID && *pszVirtualBoxIID)
+ {
+ vrc = ::RTUuidFromStr((RTUUID *)&virtualBoxIID, pszVirtualBoxIID);
+ if (RT_FAILURE(vrc))
+ return;
+ }
+ else
+ virtualBoxIID = IID_IVirtualBox;
+ if (pszSessionIID && *pszSessionIID)
+ {
+ vrc = ::RTUuidFromStr((RTUUID *)&sessionIID, pszSessionIID);
+ if (RT_FAILURE(vrc))
+ return;
+ }
+ else
+ sessionIID = IID_ISession;
+
+ HRESULT hrc = com::Initialize(VBOX_COM_INIT_F_DEFAULT | VBOX_COM_INIT_F_NO_COM_PATCHING);
+ if (FAILED(hrc))
+ {
+ Log(("Cbinding: COM/XPCOM could not be initialized! hrc=%Rhrc\n", hrc));
+ VBoxComUninitialize();
+ return;
+ }
+
+#ifdef VBOX_WITH_XPCOM
+ hrc = NS_GetMainEventQ(&g_EventQueue);
+ if (FAILED(hrc))
+ {
+ Log(("Cbinding: Could not get XPCOM event queue! hrc=%Rhrc\n", hrc));
+ VBoxComUninitialize();
+ return;
+ }
+#endif /* VBOX_WITH_XPCOM */
+
+#ifdef VBOX_WITH_XPCOM
+ nsIComponentManager *pManager;
+ hrc = NS_GetComponentManager(&pManager);
+ if (FAILED(hrc))
+ {
+ Log(("Cbinding: Could not get component manager! hrc=%Rhrc\n", hrc));
+ VBoxComUninitialize();
+ return;
+ }
+
+ hrc = pManager->CreateInstanceByContractID(NS_VIRTUALBOX_CONTRACTID,
+ nsnull,
+ virtualBoxIID,
+ (void **)&g_VirtualBox);
+#else /* !VBOX_WITH_XPCOM */
+ IVirtualBoxClient *pVirtualBoxClient;
+ hrc = CoCreateInstance(CLSID_VirtualBoxClient, NULL, CLSCTX_INPROC_SERVER, IID_IVirtualBoxClient, (void **)&pVirtualBoxClient);
+ if (SUCCEEDED(hrc))
+ {
+ IVirtualBox *pVirtualBox;
+ hrc = pVirtualBoxClient->get_VirtualBox(&pVirtualBox);
+ if (SUCCEEDED(hrc))
+ {
+ hrc = pVirtualBox->QueryInterface(virtualBoxIID, (void **)&g_VirtualBox);
+ pVirtualBox->Release();
+ }
+ pVirtualBoxClient->Release();
+ }
+#endif /* !VBOX_WITH_XPCOM */
+ if (FAILED(hrc))
+ {
+ Log(("Cbinding: Could not instantiate VirtualBox object! hrc=%Rhrc\n",hrc));
+#ifdef VBOX_WITH_XPCOM
+ pManager->Release();
+ pManager = NULL;
+#endif /* VBOX_WITH_XPCOM */
+ VBoxComUninitialize();
+ return;
+ }
+
+ Log(("Cbinding: IVirtualBox object created.\n"));
+
+#ifdef VBOX_WITH_XPCOM
+ hrc = pManager->CreateInstanceByContractID(NS_SESSION_CONTRACTID, nsnull, sessionIID, (void **)&g_Session);
+#else /* !VBOX_WITH_XPCOM */
+ hrc = CoCreateInstance(CLSID_Session, NULL, CLSCTX_INPROC_SERVER, sessionIID, (void **)&g_Session);
+#endif /* !VBOX_WITH_XPCOM */
+ if (FAILED(hrc))
+ {
+ Log(("Cbinding: Could not instantiate Session object! hrc=%Rhrc\n",hrc));
+#ifdef VBOX_WITH_XPCOM
+ pManager->Release();
+ pManager = NULL;
+#endif /* VBOX_WITH_XPCOM */
+ VBoxComUninitialize();
+ return;
+ }
+
+ Log(("Cbinding: ISession object created.\n"));
+
+#ifdef VBOX_WITH_XPCOM
+ pManager->Release();
+ pManager = NULL;
+#endif /* VBOX_WITH_XPCOM */
+
+ *ppSession = g_Session;
+ *ppVirtualBox = g_VirtualBox;
+}
+
+static void
+VBoxComInitializeV1(IVirtualBox **ppVirtualBox, ISession **ppSession)
+{
+ VBoxComInitialize(NULL, ppVirtualBox, NULL, ppSession);
+}
+
+static void
+VBoxComUninitialize(void)
+{
+ if (g_Session)
+ {
+ g_Session->Release();
+ g_Session = NULL;
+ }
+ if (g_VirtualBox)
+ {
+ g_VirtualBox->Release();
+ g_VirtualBox = NULL;
+ }
+#ifdef VBOX_WITH_XPCOM
+ if (g_EventQueue)
+ {
+ g_EventQueue->Release();
+ g_EventQueue = NULL;
+ }
+#endif /* VBOX_WITH_XPCOM */
+ com::Shutdown();
+ Log(("Cbinding: Cleaned up the created objects.\n"));
+}
+
+#ifdef VBOX_WITH_XPCOM
+static void
+VBoxGetEventQueue(nsIEventQueue **ppEventQueue)
+{
+ *ppEventQueue = g_EventQueue;
+}
+#endif /* VBOX_WITH_XPCOM */
+
+static int
+VBoxProcessEventQueue(LONG64 iTimeoutMS)
+{
+ RTMSINTERVAL iTimeout;
+ if (iTimeoutMS < 0 || iTimeoutMS > UINT32_MAX)
+ iTimeout = RT_INDEFINITE_WAIT;
+ else
+ iTimeout = (RTMSINTERVAL)iTimeoutMS;
+ int vrc = com::NativeEventQueue::getMainEventQueue()->processEventQueue(iTimeout);
+ switch (vrc)
+ {
+ case VINF_SUCCESS:
+ return 0;
+ case VINF_INTERRUPTED:
+ return 1;
+ case VERR_INTERRUPTED:
+ return 2;
+ case VERR_TIMEOUT:
+ return 3;
+ case VERR_INVALID_CONTEXT:
+ return 4;
+ default:
+ return 5;
+ }
+}
+
+static int
+VBoxInterruptEventQueueProcessing(void)
+{
+ com::NativeEventQueue::getMainEventQueue()->interruptEventQueueProcessing();
+ return 0;
+}
+
+static HRESULT
+VBoxGetException(IErrorInfo **ppException)
+{
+ HRESULT hrc;
+
+ *ppException = NULL;
+
+#ifdef VBOX_WITH_XPCOM
+ nsIServiceManager *mgr = NULL;
+ hrc = NS_GetServiceManager(&mgr);
+ if (FAILED(hrc) || !mgr)
+ return hrc;
+
+ IID esid = NS_IEXCEPTIONSERVICE_IID;
+ nsIExceptionService *es = NULL;
+ hrc = mgr->GetServiceByContractID(NS_EXCEPTIONSERVICE_CONTRACTID, esid, (void **)&es);
+ if (FAILED(hrc) || !es)
+ {
+ mgr->Release();
+ return hrc;
+ }
+
+ nsIExceptionManager *em;
+ hrc = es->GetCurrentExceptionManager(&em);
+ if (FAILED(hrc) || !em)
+ {
+ es->Release();
+ mgr->Release();
+ return hrc;
+ }
+
+ nsIException *ex;
+ hrc = em->GetCurrentException(&ex);
+ if (FAILED(hrc))
+ {
+ em->Release();
+ es->Release();
+ mgr->Release();
+ return hrc;
+ }
+
+ *ppException = ex;
+ em->Release();
+ es->Release();
+ mgr->Release();
+#else /* !VBOX_WITH_XPCOM */
+ IErrorInfo *ex;
+ hrc = ::GetErrorInfo(0, &ex);
+ if (FAILED(hrc))
+ return hrc;
+
+ *ppException = ex;
+#endif /* !VBOX_WITH_XPCOM */
+
+ return hrc;
+}
+
+static HRESULT
+VBoxClearException(void)
+{
+ HRESULT hrc;
+
+#ifdef VBOX_WITH_XPCOM
+ nsIServiceManager *mgr = NULL;
+ hrc = NS_GetServiceManager(&mgr);
+ if (FAILED(hrc) || !mgr)
+ return hrc;
+
+ IID esid = NS_IEXCEPTIONSERVICE_IID;
+ nsIExceptionService *es = NULL;
+ hrc = mgr->GetServiceByContractID(NS_EXCEPTIONSERVICE_CONTRACTID, esid, (void **)&es);
+ if (FAILED(hrc) || !es)
+ {
+ mgr->Release();
+ return hrc;
+ }
+
+ nsIExceptionManager *em;
+ hrc = es->GetCurrentExceptionManager(&em);
+ if (FAILED(hrc) || !em)
+ {
+ es->Release();
+ mgr->Release();
+ return hrc;
+ }
+
+ hrc = em->SetCurrentException(NULL);
+ em->Release();
+ es->Release();
+ mgr->Release();
+#else /* !VBOX_WITH_XPCOM */
+ hrc = ::SetErrorInfo(0, NULL);
+#endif /* !VBOX_WITH_XPCOM */
+
+ return hrc;
+}
+
+static HRESULT
+VBoxClientInitialize(const char *pszVirtualBoxClientIID, IVirtualBoxClient **ppVirtualBoxClient)
+{
+ IID virtualBoxClientIID;
+
+ *ppVirtualBoxClient = NULL;
+
+ /* convert the string representation of UUID to IID type */
+ if (pszVirtualBoxClientIID && *pszVirtualBoxClientIID)
+ {
+ int vrc = ::RTUuidFromStr((RTUUID *)&virtualBoxClientIID, pszVirtualBoxClientIID);
+ if (RT_FAILURE(vrc))
+ return E_INVALIDARG;
+ }
+ else
+ virtualBoxClientIID = IID_IVirtualBoxClient;
+
+ HRESULT hrc = com::Initialize(VBOX_COM_INIT_F_DEFAULT | VBOX_COM_INIT_F_NO_COM_PATCHING);
+ if (FAILED(hrc))
+ {
+ Log(("Cbinding: COM/XPCOM could not be initialized! hrc=%Rhrc\n", hrc));
+ VBoxClientUninitialize();
+ return hrc;
+ }
+
+#ifdef VBOX_WITH_XPCOM
+ hrc = NS_GetMainEventQ(&g_EventQueue);
+ if (NS_FAILED(hrc))
+ {
+ Log(("Cbinding: Could not get XPCOM event queue! hrc=%Rhrc\n", hrc));
+ VBoxClientUninitialize();
+ return hrc;
+ }
+#endif /* VBOX_WITH_XPCOM */
+
+#ifdef VBOX_WITH_XPCOM
+ nsIComponentManager *pManager;
+ hrc = NS_GetComponentManager(&pManager);
+ if (FAILED(hrc))
+ {
+ Log(("Cbinding: Could not get component manager! hrc=%Rhrc\n", hrc));
+ VBoxClientUninitialize();
+ return hrc;
+ }
+
+ hrc = pManager->CreateInstanceByContractID(NS_VIRTUALBOXCLIENT_CONTRACTID,
+ nsnull,
+ virtualBoxClientIID,
+ (void **)ppVirtualBoxClient);
+#else /* !VBOX_WITH_XPCOM */
+ hrc = CoCreateInstance(CLSID_VirtualBoxClient, NULL, CLSCTX_INPROC_SERVER, virtualBoxClientIID, (void **)ppVirtualBoxClient);
+#endif /* !VBOX_WITH_XPCOM */
+ if (FAILED(hrc))
+ {
+ Log(("Cbinding: Could not instantiate VirtualBoxClient object! hrc=%Rhrc\n",hrc));
+#ifdef VBOX_WITH_XPCOM
+ pManager->Release();
+ pManager = NULL;
+#endif /* VBOX_WITH_XPCOM */
+ VBoxClientUninitialize();
+ return hrc;
+ }
+
+#ifdef VBOX_WITH_XPCOM
+ pManager->Release();
+ pManager = NULL;
+#endif /* VBOX_WITH_XPCOM */
+
+ Log(("Cbinding: IVirtualBoxClient object created.\n"));
+
+ return S_OK;
+}
+
+static HRESULT
+VBoxClientThreadInitialize(void)
+{
+ return com::Initialize(VBOX_COM_INIT_F_DEFAULT | VBOX_COM_INIT_F_NO_COM_PATCHING);
+}
+
+static HRESULT
+VBoxClientThreadUninitialize(void)
+{
+ return com::Shutdown();
+}
+
+static void
+VBoxClientUninitialize(void)
+{
+#ifdef VBOX_WITH_XPCOM
+ if (g_EventQueue)
+ {
+ NS_RELEASE(g_EventQueue);
+ g_EventQueue = NULL;
+ }
+#endif /* VBOX_WITH_XPCOM */
+ com::Shutdown();
+ Log(("Cbinding: Cleaned up the created objects.\n"));
+}
+
+static unsigned int
+VBoxVersion(void)
+{
+ return VBOX_VERSION_MAJOR * 1000 * 1000 + VBOX_VERSION_MINOR * 1000 + VBOX_VERSION_BUILD;
+}
+
+static unsigned int
+VBoxAPIVersion(void)
+{
+ return VBOX_VERSION_MAJOR * 1000 + VBOX_VERSION_MINOR + (VBOX_VERSION_BUILD > 50 ? 1 : 0);
+}
+
+VBOXCAPI_DECL(PCVBOXCAPI)
+VBoxGetCAPIFunctions(unsigned uVersion)
+{
+ /* This is the first piece of code which knows that IPRT exists, so
+ * initialize it properly. The limited initialization in VBoxC is not
+ * sufficient, and causes trouble with com::Initialize() misbehaving. */
+ RTR3InitDll(0);
+
+ /*
+ * The current interface version.
+ */
+ static const VBOXCAPI s_Functions =
+ {
+ sizeof(VBOXCAPI),
+ VBOX_CAPI_VERSION,
+
+ VBoxVersion,
+ VBoxAPIVersion,
+
+ VBoxClientInitialize,
+ VBoxClientThreadInitialize,
+ VBoxClientThreadUninitialize,
+ VBoxClientUninitialize,
+
+ VBoxComInitialize,
+ VBoxComUninitialize,
+
+ VBoxComUnallocString,
+
+ VBoxUtf16ToUtf8,
+ VBoxUtf8ToUtf16,
+ VBoxUtf8Free,
+ VBoxUtf16Free,
+
+ VBoxSafeArrayCreateVector,
+ VBoxSafeArrayOutParamAlloc,
+ VBoxSafeArrayCopyInParamHelper,
+ VBoxSafeArrayCopyOutParamHelper,
+ VBoxSafeArrayCopyOutIfaceParamHelper,
+ VBoxSafeArrayDestroy,
+ VBoxArrayOutFree,
+
+#ifdef VBOX_WITH_XPCOM
+ VBoxGetEventQueue,
+#endif /* VBOX_WITH_XPCOM */
+ VBoxGetException,
+ VBoxClearException,
+ VBoxProcessEventQueue,
+ VBoxInterruptEventQueueProcessing,
+
+ VBoxUtf8Clear,
+ VBoxUtf16Clear,
+
+ VBOX_CAPI_VERSION
+ };
+
+ if ((uVersion & 0xffff0000U) == (VBOX_CAPI_VERSION & 0xffff0000U))
+ return &s_Functions;
+
+ /*
+ * Legacy interface version 3.0.
+ */
+ static const struct VBOXCAPIV3
+ {
+ /** The size of the structure. */
+ unsigned cb;
+ /** The structure version. */
+ unsigned uVersion;
+
+ unsigned int (*pfnGetVersion)(void);
+
+ unsigned int (*pfnGetAPIVersion)(void);
+
+ HRESULT (*pfnClientInitialize)(const char *pszVirtualBoxClientIID,
+ IVirtualBoxClient **ppVirtualBoxClient);
+ void (*pfnClientUninitialize)(void);
+
+ void (*pfnComInitialize)(const char *pszVirtualBoxIID,
+ IVirtualBox **ppVirtualBox,
+ const char *pszSessionIID,
+ ISession **ppSession);
+
+ void (*pfnComUninitialize)(void);
+
+ void (*pfnComUnallocMem)(void *pv);
+
+ int (*pfnUtf16ToUtf8)(CBSTR pwszString, char **ppszString);
+ int (*pfnUtf8ToUtf16)(const char *pszString, BSTR *ppwszString);
+ void (*pfnUtf8Free)(char *pszString);
+ void (*pfnUtf16Free)(BSTR pwszString);
+
+#ifdef VBOX_WITH_XPCOM
+ void (*pfnGetEventQueue)(nsIEventQueue **ppEventQueue);
+#endif /* VBOX_WITH_XPCOM */
+ HRESULT (*pfnGetException)(IErrorInfo **ppException);
+ HRESULT (*pfnClearException)(void);
+
+ /** Tail version, same as uVersion. */
+ unsigned uEndVersion;
+ } s_Functions_v3_0 =
+ {
+ sizeof(s_Functions_v3_0),
+ 0x00030000U,
+
+ VBoxVersion,
+ VBoxAPIVersion,
+
+ VBoxClientInitialize,
+ VBoxClientUninitialize,
+
+ VBoxComInitialize,
+ VBoxComUninitialize,
+
+ VBoxComUnallocMem,
+
+ VBoxUtf16ToUtf8,
+ VBoxUtf8ToUtf16,
+ VBoxUtf8Free,
+ VBoxUtf16Free,
+
+#ifdef VBOX_WITH_XPCOM
+ VBoxGetEventQueue,
+#endif /* VBOX_WITH_XPCOM */
+ VBoxGetException,
+ VBoxClearException,
+
+ 0x00030000U
+ };
+
+ if ((uVersion & 0xffff0000U) == 0x00030000U)
+ return (PCVBOXCAPI)&s_Functions_v3_0;
+
+ /*
+ * Legacy interface version 2.0.
+ */
+ static const struct VBOXCAPIV2
+ {
+ /** The size of the structure. */
+ unsigned cb;
+ /** The structure version. */
+ 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)(BSTR pwszString);
+ void (*pfnUtf8Free)(char *pszString);
+
+ int (*pfnUtf16ToUtf8)(CBSTR pwszString, char **ppszString);
+ int (*pfnUtf8ToUtf16)(const char *pszString, BSTR *ppwszString);
+
+#ifdef VBOX_WITH_XPCOM
+ void (*pfnGetEventQueue)(nsIEventQueue **ppEventQueue);
+#endif /* VBOX_WITH_XPCOM */
+
+ /** Tail version, same as uVersion. */
+ unsigned uEndVersion;
+ } s_Functions_v2_0 =
+ {
+ sizeof(s_Functions_v2_0),
+ 0x00020000U,
+
+ VBoxVersion,
+
+ VBoxComInitialize,
+ VBoxComUninitialize,
+
+ VBoxComUnallocMem,
+ VBoxUtf16Free,
+ VBoxUtf8Free,
+
+ VBoxUtf16ToUtf8,
+ VBoxUtf8ToUtf16,
+
+#ifdef VBOX_WITH_XPCOM
+ VBoxGetEventQueue,
+#endif /* VBOX_WITH_XPCOM */
+
+ 0x00020000U
+ };
+
+ if ((uVersion & 0xffff0000U) == 0x00020000U)
+ return (PCVBOXCAPI)&s_Functions_v2_0;
+
+ /*
+ * Legacy interface version 1.0.
+ */
+ static const struct VBOXCAPIV1
+ {
+ /** The size of the structure. */
+ unsigned cb;
+ /** The structure version. */
+ unsigned uVersion;
+
+ unsigned int (*pfnGetVersion)(void);
+
+ void (*pfnComInitialize)(IVirtualBox **virtualBox, ISession **session);
+ void (*pfnComUninitialize)(void);
+
+ void (*pfnComUnallocMem)(void *pv);
+ void (*pfnUtf16Free)(BSTR pwszString);
+ void (*pfnUtf8Free)(char *pszString);
+
+ int (*pfnUtf16ToUtf8)(CBSTR pwszString, char **ppszString);
+ int (*pfnUtf8ToUtf16)(const char *pszString, BSTR *ppwszString);
+
+ /** Tail version, same as uVersion. */
+ unsigned uEndVersion;
+ } s_Functions_v1_0 =
+ {
+ sizeof(s_Functions_v1_0),
+ 0x00010000U,
+
+ VBoxVersion,
+
+ VBoxComInitializeV1,
+ VBoxComUninitialize,
+
+ VBoxComUnallocMem,
+ VBoxUtf16Free,
+ VBoxUtf8Free,
+
+ VBoxUtf16ToUtf8,
+ VBoxUtf8ToUtf16,
+
+ 0x00010000U
+ };
+
+ if ((uVersion & 0xffff0000U) == 0x00010000U)
+ return (PCVBOXCAPI)&s_Functions_v1_0;
+
+ /*
+ * Unsupported interface version.
+ */
+ return NULL;
+}
+
+#ifdef VBOX_WITH_XPCOM
+VBOXCAPI_DECL(PCVBOXCAPI)
+VBoxGetXPCOMCFunctions(unsigned uVersion)
+{
+ return VBoxGetCAPIFunctions(uVersion);
+}
+#endif /* VBOX_WITH_XPCOM */
+/* vim: set ts=4 sw=4 et: */
diff --git a/src/VBox/Main/cbinding/VBoxCAPI.rc b/src/VBox/Main/cbinding/VBoxCAPI.rc
new file mode 100644
index 00000000..59fe2115
--- /dev/null
+++ b/src/VBox/Main/cbinding/VBoxCAPI.rc
@@ -0,0 +1,61 @@
+/* $Id: VBoxCAPI.rc $ */
+/** @file
+ * VBoxCAPI - Resource file containing version info.
+ */
+
+/*
+ * Copyright (C) 2015-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#include <windows.h>
+#include <VBox/version.h>
+
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION VBOX_RC_FILE_VERSION
+ PRODUCTVERSION VBOX_RC_FILE_VERSION
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+ FILEFLAGS VBOX_RC_FILE_FLAGS
+ FILEOS VBOX_RC_FILE_OS
+ FILETYPE VBOX_RC_TYPE_DLL
+ FILESUBTYPE VFT2_UNKNOWN
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0" // Lang=US English, CharSet=Unicode
+ BEGIN
+ VALUE "FileDescription", "VirtualBox C Bindings\0"
+ VALUE "InternalName", "VBoxCAPI\0"
+ VALUE "OriginalFilename", "VBoxCAPI.dll\0"
+ VALUE "CompanyName", VBOX_RC_COMPANY_NAME
+ VALUE "FileVersion", VBOX_RC_FILE_VERSION_STR
+ VALUE "LegalCopyright", VBOX_RC_LEGAL_COPYRIGHT
+ VALUE "ProductName", VBOX_RC_PRODUCT_NAME_STR
+ VALUE "ProductVersion", VBOX_RC_PRODUCT_VERSION_STR
+ VBOX_RC_MORE_STRINGS
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
diff --git a/src/VBox/Main/cbinding/VBoxCAPIGlue.c b/src/VBox/Main/cbinding/VBoxCAPIGlue.c
new file mode 100644
index 00000000..476bfddf
--- /dev/null
+++ b/src/VBox/Main/cbinding/VBoxCAPIGlue.c
@@ -0,0 +1,345 @@
+/* $Id: VBoxCAPIGlue.c $ */
+/** @file
+ * Glue code for dynamically linking to VBoxCAPI.
+ */
+
+/*
+ * Copyright (C) 2008-2023 Oracle and/or its affiliates.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+/* NOTE: do NOT use any include files here which are only available in the
+ * VirtualBox tree, e.g. iprt. They are not available in the SDK, which is
+ * where this file will provided as source code and has to be compilable. */
+#include "VBoxCAPIGlue.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#ifdef WIN32
+# define _INTPTR 2 /* on Windows stdint.h compares this in #if, causing warnings if not defined */
+#endif /* WIN32 */
+#include <stdint.h>
+#ifndef WIN32
+# include <dlfcn.h>
+# include <pthread.h>
+#else /* WIN32 */
+# include <Windows.h>
+#endif /* WIN32 */
+
+
+/*********************************************************************************************************************************
+* Defined Constants And Macros *
+*********************************************************************************************************************************/
+#if defined(__linux__) || defined(__linux_gnu__) || defined(__sun__) || defined(__FreeBSD__)
+# define DYNLIB_NAME "VBoxXPCOMC.so"
+#elif defined(__APPLE__)
+# define DYNLIB_NAME "VBoxXPCOMC.dylib"
+#elif defined(__OS2__)
+# define DYNLIB_NAME "VBoxXPCOMC.dll"
+#elif defined(WIN32)
+# define DYNLIB_NAME "VBoxCAPI.dll"
+#else
+# error "Port me"
+#endif
+
+
+/*********************************************************************************************************************************
+* Global Variables *
+*********************************************************************************************************************************/
+/** The so/dynsym/dll handle for VBoxCAPI. */
+#ifndef WIN32
+void *g_hVBoxCAPI = NULL;
+#else /* WIN32 */
+HMODULE g_hVBoxCAPI = NULL;
+#endif /* WIN32 */
+/** The last load error. */
+char g_szVBoxErrMsg[256] = "";
+/** Pointer to the VBOXCAPI function table. */
+PCVBOXCAPI g_pVBoxFuncs = NULL;
+/** Pointer to VBoxGetCAPIFunctions for the loaded VBoxCAPI so/dylib/dll. */
+PFNVBOXGETCAPIFUNCTIONS g_pfnGetFunctions = NULL;
+
+typedef void FNDUMMY(void);
+typedef FNDUMMY *PFNDUMMY;
+/** Just a dummy global structure containing a bunch of
+ * function pointers to code which is wanted in the link. */
+PFNDUMMY g_apfnVBoxCAPIGlue[] =
+{
+#ifndef WIN32
+ /* The following link dependency is for helping gdb as it gets hideously
+ * confused if the application doesn't drag in pthreads, but uses it. */
+ (PFNDUMMY)pthread_create,
+#endif /* !WIN32 */
+ NULL
+};
+
+
+/**
+ * Wrapper for setting g_szVBoxErrMsg. Can be an empty stub.
+ *
+ * @param fAlways When 0 the g_szVBoxErrMsg is only set if empty.
+ * @param pszFormat The format string.
+ * @param ... The arguments.
+ */
+static void setErrMsg(int fAlways, const char *pszFormat, ...)
+{
+ if ( fAlways
+ || !g_szVBoxErrMsg[0])
+ {
+ va_list va;
+ va_start(va, pszFormat);
+ vsnprintf(g_szVBoxErrMsg, sizeof(g_szVBoxErrMsg), pszFormat, va);
+ va_end(va);
+ }
+}
+
+
+/**
+ * Try load C API .so/dylib/dll from the specified location and resolve all
+ * the symbols we need. Tries both the new style and legacy name.
+ *
+ * @returns 0 on success, -1 on failure.
+ * @param pszHome The directory where to try load VBoxCAPI/VBoxXPCOMC
+ * from. Can be NULL.
+ * @param fSetAppHome Whether to set the VBOX_APP_HOME env.var. or not
+ * (boolean).
+ */
+static int tryLoadLibrary(const char *pszHome, int fSetAppHome)
+{
+ size_t cchHome = pszHome ? strlen(pszHome) : 0;
+ size_t cbBufNeeded;
+ char szName[4096];
+
+ /*
+ * Construct the full name.
+ */
+ cbBufNeeded = cchHome + sizeof("/" DYNLIB_NAME);
+ if (cbBufNeeded > sizeof(szName))
+ {
+ setErrMsg(1, "path buffer too small: %u bytes needed",
+ (unsigned)cbBufNeeded);
+ return -1;
+ }
+ if (cchHome)
+ {
+ memcpy(szName, pszHome, cchHome);
+ szName[cchHome] = '/';
+ cchHome++;
+ }
+ memcpy(&szName[cchHome], DYNLIB_NAME, sizeof(DYNLIB_NAME));
+
+ /*
+ * Try load it by that name, setting the VBOX_APP_HOME first (for now).
+ * Then resolve and call the function table getter.
+ */
+ if (fSetAppHome)
+ {
+#ifndef WIN32
+ if (pszHome)
+ setenv("VBOX_APP_HOME", pszHome, 1 /* always override */);
+ else
+ unsetenv("VBOX_APP_HOME");
+#endif /* !WIN32 */
+ }
+
+#ifndef WIN32
+ g_hVBoxCAPI = dlopen(szName, RTLD_NOW | RTLD_LOCAL);
+#else /* WIN32 */
+ g_hVBoxCAPI = LoadLibraryExA(szName, NULL /* hFile */, 0 /* dwFlags */);
+#endif /* WIN32 */
+ if (g_hVBoxCAPI)
+ {
+ PFNVBOXGETCAPIFUNCTIONS pfnGetFunctions;
+#ifndef WIN32
+ pfnGetFunctions = (PFNVBOXGETCAPIFUNCTIONS)(uintptr_t)
+ dlsym(g_hVBoxCAPI, VBOX_GET_CAPI_FUNCTIONS_SYMBOL_NAME);
+# ifdef VBOX_GET_XPCOM_FUNCTIONS_SYMBOL_NAME
+ if (!pfnGetFunctions)
+ pfnGetFunctions = (PFNVBOXGETCAPIFUNCTIONS)(uintptr_t)
+ dlsym(g_hVBoxCAPI, VBOX_GET_XPCOM_FUNCTIONS_SYMBOL_NAME);
+# endif /* VBOX_GET_XPCOM_FUNCTIONS_SYMBOL_NAME */
+#else /* WIN32 */
+ pfnGetFunctions = (PFNVBOXGETCAPIFUNCTIONS)
+ GetProcAddress(g_hVBoxCAPI, VBOX_GET_CAPI_FUNCTIONS_SYMBOL_NAME);
+#endif /* WIN32 */
+ if (pfnGetFunctions)
+ {
+ g_pVBoxFuncs = pfnGetFunctions(VBOX_CAPI_VERSION);
+ if (g_pVBoxFuncs)
+ {
+ if ( ( VBOX_CAPI_MAJOR(g_pVBoxFuncs->uVersion)
+ == VBOX_CAPI_MAJOR(VBOX_CAPI_VERSION))
+ && ( VBOX_CAPI_MINOR(g_pVBoxFuncs->uVersion)
+ >= VBOX_CAPI_MINOR(VBOX_CAPI_VERSION)))
+ {
+ g_pfnGetFunctions = pfnGetFunctions;
+ return 0;
+ }
+ setErrMsg(1, "%.80s: pfnGetFunctions(%#x) returned incompatible version %#x",
+ szName, VBOX_CAPI_VERSION, g_pVBoxFuncs->uVersion);
+ g_pVBoxFuncs = NULL;
+ }
+ else
+ {
+ /* bail out */
+ setErrMsg(1, "%.80s: pfnGetFunctions(%#x) failed",
+ szName, VBOX_CAPI_VERSION);
+ }
+ }
+ else
+ {
+#ifndef WIN32
+ setErrMsg(1, "dlsym(%.80s/%.32s): %.128s",
+ szName, VBOX_GET_CAPI_FUNCTIONS_SYMBOL_NAME, dlerror());
+#else /* WIN32 */
+ setErrMsg(1, "GetProcAddress(%.80s/%.32s): %d",
+ szName, VBOX_GET_CAPI_FUNCTIONS_SYMBOL_NAME, GetLastError());
+#endif /* WIN32 */
+ }
+
+#ifndef WIN32
+ dlclose(g_hVBoxCAPI);
+#else /* WIN32 */
+ FreeLibrary(g_hVBoxCAPI);
+#endif /* WIN32 */
+ g_hVBoxCAPI = NULL;
+ }
+ else
+ {
+#ifndef WIN32
+ setErrMsg(0, "dlopen(%.80s): %.160s", szName, dlerror());
+#else /* WIN32 */
+ setErrMsg(0, "LoadLibraryEx(%.80s): %d", szName, GetLastError());
+#endif /* WIN32 */
+ }
+
+ return -1;
+}
+
+
+/**
+ * Tries to locate and load VBoxCAPI.so/dylib/dll, resolving all the related
+ * function pointers.
+ *
+ * @returns 0 on success, -1 on failure.
+ *
+ * @remark This should be considered moved into a separate glue library since
+ * its its going to be pretty much the same for any user of VBoxCAPI
+ * and it will just cause trouble to have duplicate versions of this
+ * source code all around the place.
+ */
+int VBoxCGlueInit(void)
+{
+ const char *pszHome;
+
+ memset(g_szVBoxErrMsg, 0, sizeof(g_szVBoxErrMsg));
+
+ /*
+ * If the user specifies the location, try only that.
+ */
+ pszHome = getenv("VBOX_APP_HOME");
+ if (pszHome)
+ return tryLoadLibrary(pszHome, 0);
+
+ /*
+ * Try the known standard locations.
+ */
+#if defined(__gnu__linux__) || defined(__linux__)
+ if (tryLoadLibrary("/opt/VirtualBox", 1) == 0)
+ return 0;
+ if (tryLoadLibrary("/usr/lib/virtualbox", 1) == 0)
+ return 0;
+#elif defined(__sun__)
+ if (tryLoadLibrary("/opt/VirtualBox/amd64", 1) == 0)
+ return 0;
+ if (tryLoadLibrary("/opt/VirtualBox/i386", 1) == 0)
+ return 0;
+#elif defined(__APPLE__)
+ if (tryLoadLibrary("/Applications/VirtualBox.app/Contents/MacOS", 1) == 0)
+ return 0;
+#elif defined(__FreeBSD__)
+ if (tryLoadLibrary("/usr/local/lib/virtualbox", 1) == 0)
+ return 0;
+#elif defined(__OS2__)
+ if (tryLoadLibrary("C:/Apps/VirtualBox", 1) == 0)
+ return 0;
+#elif defined(WIN32)
+ pszHome = getenv("ProgramFiles");
+ if (pszHome)
+ {
+ char szPath[4096];
+ size_t cb = sizeof(szPath);
+ char *tmp = szPath;
+ strncpy(tmp, pszHome, cb);
+ tmp[cb - 1] = '\0';
+ cb -= strlen(tmp);
+ tmp += strlen(tmp);
+ strncpy(tmp, "/Oracle/VirtualBox", cb);
+ tmp[cb - 1] = '\0';
+ if (tryLoadLibrary(szPath, 1) == 0)
+ return 0;
+ }
+ if (tryLoadLibrary("C:/Program Files/Oracle/VirtualBox", 1) == 0)
+ return 0;
+#else
+# error "port me"
+#endif
+
+ /*
+ * Finally try the dynamic linker search path.
+ */
+ if (tryLoadLibrary(NULL, 1) == 0)
+ return 0;
+
+ /* No luck, return failure. */
+ return -1;
+}
+
+
+/**
+ * Terminate the C glue library.
+ */
+void VBoxCGlueTerm(void)
+{
+ if (g_hVBoxCAPI)
+ {
+#if 0 /* VBoxRT.so doesn't like being reloaded. See @bugref{3725}. */
+#ifndef WIN32
+ dlclose(g_hVBoxCAPI);
+#else
+ FreeLibrary(g_hVBoxCAPI);
+#endif
+#endif
+ g_hVBoxCAPI = NULL;
+ }
+ g_pVBoxFuncs = NULL;
+ g_pfnGetFunctions = NULL;
+ memset(g_szVBoxErrMsg, 0, sizeof(g_szVBoxErrMsg));
+}
+
diff --git a/src/VBox/Main/cbinding/VBoxCAPIGlue.h.in b/src/VBox/Main/cbinding/VBoxCAPIGlue.h.in
new file mode 100644
index 00000000..60ec8b6f
--- /dev/null
+++ b/src/VBox/Main/cbinding/VBoxCAPIGlue.h.in
@@ -0,0 +1,68 @@
+/* $Id: VBoxCAPIGlue.h.in $ */
+/** @file VBoxCAPIGlue.h
+ * Glue for dynamically linking with VBoxCAPI.
+ */
+
+/*
+ * Copyright (C) 2008-2023 Oracle and/or its affiliates.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ___VBoxCAPIGlue_h
+#define ___VBoxCAPIGlue_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#undef VBOX_WITH_GLUE
+#define VBOX_WITH_GLUE
+#include "VBoxCAPI_v@VBOX_API_VERSION@.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** The so/dynsym/dll handle for VBoxCAPI. */
+#ifndef WIN32
+extern void *g_hVBoxCAPI;
+#else
+extern HMODULE g_hVBoxCAPI;
+#endif
+/** The last load error. */
+extern char g_szVBoxErrMsg[256];
+/** Pointer to the VBOXCAPI function table. */
+extern PCVBOXCAPI g_pVBoxFuncs;
+/** Pointer to VBoxGetCAPIFunctions for the loaded VBoxCAPI so/dylib/dll. */
+extern PFNVBOXGETCAPIFUNCTIONS g_pfnGetFunctions;
+
+
+int VBoxCGlueInit(void);
+void VBoxCGlueTerm(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !___VBoxCAPIGlue_h */
+
diff --git a/src/VBox/Main/cbinding/capiidl.xsl b/src/VBox/Main/cbinding/capiidl.xsl
new file mode 100644
index 00000000..b9dabcfd
--- /dev/null
+++ b/src/VBox/Main/cbinding/capiidl.xsl
@@ -0,0 +1,2736 @@
+<?xml version="1.0"?>
+<!-- $Id: capiidl.xsl $ -->
+
+<!--
+ * A template to generate a C header file for all relevant XPCOM interfaces
+ * provided or needed for calling the VirtualBox API. The header file also
+ * works on Windows, by using the C bindings header created by the MS COM IDL
+ * compiler (which simultaneously supports C and C++, unlike XPCOM).
+-->
+<!--
+ Copyright (C) 2008-2023 Oracle and/or its affiliates.
+
+ This file is part of VirtualBox base platform packages, as
+ available from https://www.virtualbox.org.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation, in version 3 of the
+ License.
+
+ This program 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <https://www.gnu.org/licenses>.
+
+ SPDX-License-Identifier: GPL-3.0-only
+-->
+
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:output method="text"/>
+
+<xsl:strip-space elements="*"/>
+
+
+<xsl:include href="../idl/typemap-shared.inc.xsl"/>
+
+<!--
+// Keys for more efficiently looking up of types.
+/////////////////////////////////////////////////////////////////////////////
+-->
+
+<xsl:key name="G_keyInterfacesByName" match="//interface[@name]" use="@name"/>
+
+
+<!--
+// templates
+/////////////////////////////////////////////////////////////////////////////
+-->
+
+
+<!--
+ * not explicitly matched elements and attributes
+-->
+<xsl:template match="*"/>
+
+
+<!--
+ * header
+-->
+<xsl:template match="/idl">
+ <xsl:text>/*
+ * DO NOT EDIT! This is a generated file.
+ *
+ * Header file which provides C declarations for VirtualBox Main API
+ * (COM interfaces), generated from XIDL (XML interface definition).
+ * On Windows (which uses COM instead of XPCOM) the native C support
+ * is used, and most of this file is not used.
+ *
+ * Source : src/VBox/Main/idl/VirtualBox.xidl
+ * Generator : src/VBox/Main/cbinding/capiidl.xsl
+ *
+ * This file contains portions from the following Mozilla XPCOM files:
+ * xpcom/include/xpcom/nsID.h
+ * xpcom/include/nsIException.h
+ * xpcom/include/nsprpub/prtypes.h
+ * xpcom/include/xpcom/nsISupportsBase.h
+ *
+ * These files were originally triple-licensed (MPL/GPL2/LGPL2.1). Oracle
+ * elects to distribute this derived work under the LGPL2.1 only.
+ */
+
+/*
+ * Copyright (C) 2008-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of a free software library; you can redistribute
+ * it and/or modify it under the terms of the GNU Lesser General
+ * Public License version 2.1 as published by the Free Software
+ * Foundation and shipped in the "COPYING.LIB" file with this library.
+ * The library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY of any kind.
+ *
+ * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if
+ * any license choice other than GPL or LGPL is available it will
+ * apply instead, Oracle elects to use only the Lesser General Public
+ * License version 2.1 (LGPLv2) at this time for any software where
+ * a choice of LGPL license versions is made available with the
+ * language indicating that LGPLv2 or any later version may be used,
+ * or where a choice of which version of the LGPL is applied is
+ * otherwise unspecified.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ */
+
+#ifndef ___VirtualBox_CAPI_h
+#define ___VirtualBox_CAPI_h
+
+#ifdef _WIN32
+# ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable:4668 4255) /* -Wall and windows.h */
+# if _MSC_VER >= 1800 /*RT_MSC_VER_VC120*/
+# pragma warning(disable:4005) /* sdk/v7.1/include/sal_supp.h(57) : warning C4005: '__useHeader' : macro redefinition */
+# endif
+# ifdef __cplusplus
+# if _MSC_VER >= 1900 /*RT_MSC_VER_VC140*/
+# pragma warning(disable:5039) /* winbase.h(13179): warning C5039: 'TpSetCallbackCleanupGroup': pointer or reference to potentially throwing function passed to 'extern "C"' function under -EHc. Undefined behavior may occur if this function throws an exception. */
+# endif
+# endif
+# endif
+# undef COBJMACROS
+# define COBJMACROS
+# include "Windows.h"
+# pragma warning(pop)
+#endif /* _WIN32 */
+
+#ifdef WIN32
+# ifdef IN_VBOXCAPI
+# define VBOXCAPI_DECL(type) extern __declspec(dllexport) type
+# else /* !IN_VBOXCAPI */
+# define VBOXCAPI_DECL(type) __declspec(dllimport) type
+# endif /* !IN_VBOXCAPI */
+#endif /* WIN32 */
+
+#ifdef __cplusplus
+/* The C++ treatment in this file is not meant for SDK users, it only exists
+ * so that this file can be used to produce the VBoxCAPI shared library which
+ * has to use C++ as it does all the conversion magic. */
+# ifdef IN_VBOXCAPI
+# include "VBox/com/VirtualBox.h"
+# ifndef WIN32
+# include "nsIEventQueue.h"
+# endif /* !WIN32 */
+# else /* !IN_VBOXCAPI */
+# error Do not include this header file from C++ code
+# endif /* !IN_VBOXCAPI */
+#endif /* __cplusplus */
+
+#ifdef __GNUC__
+# define VBOX_EXTERN_CONST(type, name) extern const type name __attribute__((nocommon))
+#else /* !__GNUC__ */
+# define VBOX_EXTERN_CONST(type, name) extern const type name
+#endif /* !__GNUC__ */
+
+/* Treat WIN32 completely separately, as on Windows VirtualBox uses COM, not
+ * XPCOM like on all other platforms. While the code below would also compile
+ * on Windows, we need to switch to the native C support provided by the header
+ * files produced by the COM IDL compiler. */
+#ifdef WIN32
+# include "ObjBase.h"
+# include "oaidl.h"
+# include "VirtualBox.h"
+
+#ifndef __cplusplus
+/* Skip this in the C++ case as there's already a definition for CBSTR. */
+typedef const BSTR CBSTR;
+#endif /* !__cplusplus */
+
+#define VBOX_WINAPI WINAPI
+
+#define ComSafeArrayAsInParam(f) (f)
+#define ComSafeArrayAsOutParam(f) (&amp;(f))
+#define ComSafeArrayAsOutTypeParam(f,t) (&amp;(f))
+#define ComSafeArrayAsOutIfaceParam(f,t) (&amp;(f))
+
+#else /* !WIN32 */
+
+#include &lt;stddef.h&gt;
+#include "wchar.h"
+
+#ifdef IN_VBOXCAPI
+# define VBOXCAPI_DECL(type) PR_EXPORT(type)
+#else /* !IN_VBOXCAPI */
+# define VBOXCAPI_DECL(type) PR_IMPORT(type)
+#endif /* !IN_VBOXCAPI */
+
+#ifndef __cplusplus
+
+#if defined(WIN32)
+
+#define PR_EXPORT(__type) extern __declspec(dllexport) __type
+#define PR_EXPORT_DATA(__type) extern __declspec(dllexport) __type
+#define PR_IMPORT(__type) __declspec(dllimport) __type
+#define PR_IMPORT_DATA(__type) __declspec(dllimport) __type
+
+#define PR_EXTERN(__type) extern __declspec(dllexport) __type
+#define PR_IMPLEMENT(__type) __declspec(dllexport) __type
+#define PR_EXTERN_DATA(__type) extern __declspec(dllexport) __type
+#define PR_IMPLEMENT_DATA(__type) __declspec(dllexport) __type
+
+#define PR_CALLBACK
+#define PR_CALLBACK_DECL
+#define PR_STATIC_CALLBACK(__x) static __x
+
+#elif defined(XP_BEOS)
+
+#define PR_EXPORT(__type) extern __declspec(dllexport) __type
+#define PR_EXPORT_DATA(__type) extern __declspec(dllexport) __type
+#define PR_IMPORT(__type) extern __declspec(dllexport) __type
+#define PR_IMPORT_DATA(__type) extern __declspec(dllexport) __type
+
+#define PR_EXTERN(__type) extern __declspec(dllexport) __type
+#define PR_IMPLEMENT(__type) __declspec(dllexport) __type
+#define PR_EXTERN_DATA(__type) extern __declspec(dllexport) __type
+#define PR_IMPLEMENT_DATA(__type) __declspec(dllexport) __type
+
+#define PR_CALLBACK
+#define PR_CALLBACK_DECL
+#define PR_STATIC_CALLBACK(__x) static __x
+
+#elif defined(WIN16)
+
+#define PR_CALLBACK_DECL __cdecl
+
+#if defined(_WINDLL)
+#define PR_EXPORT(__type) extern __type _cdecl _export _loadds
+#define PR_IMPORT(__type) extern __type _cdecl _export _loadds
+#define PR_EXPORT_DATA(__type) extern __type _export
+#define PR_IMPORT_DATA(__type) extern __type _export
+
+#define PR_EXTERN(__type) extern __type _cdecl _export _loadds
+#define PR_IMPLEMENT(__type) __type _cdecl _export _loadds
+#define PR_EXTERN_DATA(__type) extern __type _export
+#define PR_IMPLEMENT_DATA(__type) __type _export
+
+#define PR_CALLBACK __cdecl __loadds
+#define PR_STATIC_CALLBACK(__x) static __x PR_CALLBACK
+
+#else /* this must be .EXE */
+#define PR_EXPORT(__type) extern __type _cdecl _export
+#define PR_IMPORT(__type) extern __type _cdecl _export
+#define PR_EXPORT_DATA(__type) extern __type _export
+#define PR_IMPORT_DATA(__type) extern __type _export
+
+#define PR_EXTERN(__type) extern __type _cdecl _export
+#define PR_IMPLEMENT(__type) __type _cdecl _export
+#define PR_EXTERN_DATA(__type) extern __type _export
+#define PR_IMPLEMENT_DATA(__type) __type _export
+
+#define PR_CALLBACK __cdecl __loadds
+#define PR_STATIC_CALLBACK(__x) __x PR_CALLBACK
+#endif /* _WINDLL */
+
+#elif defined(XP_MAC)
+
+#define PR_EXPORT(__type) extern __declspec(export) __type
+#define PR_EXPORT_DATA(__type) extern __declspec(export) __type
+#define PR_IMPORT(__type) extern __declspec(export) __type
+#define PR_IMPORT_DATA(__type) extern __declspec(export) __type
+
+#define PR_EXTERN(__type) extern __declspec(export) __type
+#define PR_IMPLEMENT(__type) __declspec(export) __type
+#define PR_EXTERN_DATA(__type) extern __declspec(export) __type
+#define PR_IMPLEMENT_DATA(__type) __declspec(export) __type
+
+#define PR_CALLBACK
+#define PR_CALLBACK_DECL
+#define PR_STATIC_CALLBACK(__x) static __x
+
+#elif defined(XP_OS2) &amp;&amp; defined(__declspec)
+
+#define PR_EXPORT(__type) extern __declspec(dllexport) __type
+#define PR_EXPORT_DATA(__type) extern __declspec(dllexport) __type
+#define PR_IMPORT(__type) __declspec(dllimport) __type
+#define PR_IMPORT_DATA(__type) __declspec(dllimport) __type
+
+#define PR_EXTERN(__type) extern __declspec(dllexport) __type
+#define PR_IMPLEMENT(__type) __declspec(dllexport) __type
+#define PR_EXTERN_DATA(__type) extern __declspec(dllexport) __type
+#define PR_IMPLEMENT_DATA(__type) __declspec(dllexport) __type
+
+#define PR_CALLBACK
+#define PR_CALLBACK_DECL
+#define PR_STATIC_CALLBACK(__x) static __x
+
+#elif defined(XP_OS2_VACPP)
+
+#define PR_EXPORT(__type) extern __type
+#define PR_EXPORT_DATA(__type) extern __type
+#define PR_IMPORT(__type) extern __type
+#define PR_IMPORT_DATA(__type) extern __type
+
+#define PR_EXTERN(__type) extern __type
+#define PR_IMPLEMENT(__type) __type
+#define PR_EXTERN_DATA(__type) extern __type
+#define PR_IMPLEMENT_DATA(__type) __type
+#define PR_CALLBACK _Optlink
+#define PR_CALLBACK_DECL
+#define PR_STATIC_CALLBACK(__x) static __x PR_CALLBACK
+
+#else /* Unix */
+
+# ifdef VBOX_HAVE_VISIBILITY_HIDDEN
+# define PR_EXPORT(__type) __attribute__((visibility("default"))) extern __type
+# define PR_EXPORT_DATA(__type) __attribute__((visibility("default"))) extern __type
+# define PR_IMPORT(__type) extern __type
+# define PR_IMPORT_DATA(__type) extern __type
+# define PR_EXTERN(__type) __attribute__((visibility("default"))) extern __type
+# define PR_IMPLEMENT(__type) __attribute__((visibility("default"))) __type
+# define PR_EXTERN_DATA(__type) __attribute__((visibility("default"))) extern __type
+# define PR_IMPLEMENT_DATA(__type) __attribute__((visibility("default"))) __type
+# define PR_CALLBACK
+# define PR_CALLBACK_DECL
+# define PR_STATIC_CALLBACK(__x) static __x
+# else
+# define PR_EXPORT(__type) extern __type
+# define PR_EXPORT_DATA(__type) extern __type
+# define PR_IMPORT(__type) extern __type
+# define PR_IMPORT_DATA(__type) extern __type
+# define PR_EXTERN(__type) extern __type
+# define PR_IMPLEMENT(__type) __type
+# define PR_EXTERN_DATA(__type) extern __type
+# define PR_IMPLEMENT_DATA(__type) __type
+# define PR_CALLBACK
+# define PR_CALLBACK_DECL
+# define PR_STATIC_CALLBACK(__x) static __x
+# endif
+#endif
+
+#if defined(_NSPR_BUILD_)
+#define NSPR_API(__type) PR_EXPORT(__type)
+#define NSPR_DATA_API(__type) PR_EXPORT_DATA(__type)
+#else
+#define NSPR_API(__type) PR_IMPORT(__type)
+#define NSPR_DATA_API(__type) PR_IMPORT_DATA(__type)
+#endif
+
+typedef unsigned char PRUint8;
+#if (defined(HPUX) &amp;&amp; defined(__cplusplus) \
+ &amp;&amp; !defined(__GNUC__) &amp;&amp; __cplusplus &lt; 199707L) \
+ || (defined(SCO) &amp;&amp; defined(__cplusplus) \
+ &amp;&amp; !defined(__GNUC__) &amp;&amp; __cplusplus == 1L)
+typedef char PRInt8;
+#else
+typedef signed char PRInt8;
+#endif
+
+#define PR_INT8_MAX 127
+#define PR_INT8_MIN (-128)
+#define PR_UINT8_MAX 255U
+
+typedef unsigned short PRUint16;
+typedef short PRInt16;
+
+#define PR_INT16_MAX 32767
+#define PR_INT16_MIN (-32768)
+#define PR_UINT16_MAX 65535U
+
+typedef unsigned int PRUint32;
+typedef int PRInt32;
+#define PR_INT32(x) x
+#define PR_UINT32(x) x ## U
+
+#define PR_INT32_MAX PR_INT32(2147483647)
+#define PR_INT32_MIN (-PR_INT32_MAX - 1)
+#define PR_UINT32_MAX PR_UINT32(4294967295)
+
+typedef long PRInt64;
+typedef unsigned long PRUint64;
+typedef int PRIntn;
+typedef unsigned int PRUintn;
+
+typedef double PRFloat64;
+typedef size_t PRSize;
+
+typedef ptrdiff_t PRPtrdiff;
+
+typedef unsigned long PRUptrdiff;
+
+typedef PRIntn PRBool;
+
+#define PR_TRUE 1
+#define PR_FALSE 0
+
+typedef PRUint8 PRPackedBool;
+
+/*
+** Status code used by some routines that have a single point of failure or
+** special status return.
+*/
+typedef enum { PR_FAILURE = -1, PR_SUCCESS = 0 } PRStatus;
+
+#ifndef __PRUNICHAR__
+#define __PRUNICHAR__
+#if defined(WIN32) || defined(XP_MAC)
+typedef wchar_t PRUnichar;
+#else
+typedef PRUint16 PRUnichar;
+#endif
+typedef PRUnichar *BSTR;
+typedef const PRUnichar *CBSTR;
+#endif
+
+typedef long PRWord;
+typedef unsigned long PRUword;
+
+#define nsnull 0
+typedef PRUint32 nsresult;
+
+#if defined(__GNUC__) &amp;&amp; (__GNUC__ > 2)
+#define NS_LIKELY(x) (__builtin_expect((x), 1))
+#define NS_UNLIKELY(x) (__builtin_expect((x), 0))
+#else
+#define NS_LIKELY(x) (x)
+#define NS_UNLIKELY(x) (x)
+#endif
+
+#define NS_FAILED(_nsresult) (NS_UNLIKELY((_nsresult) &amp; 0x80000000))
+#define NS_SUCCEEDED(_nsresult) (NS_LIKELY(!((_nsresult) &amp; 0x80000000)))
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+# define PR_IntervalNow VBoxNsprPR_IntervalNow
+# define PR_TicksPerSecond VBoxNsprPR_TicksPerSecond
+# define PR_SecondsToInterval VBoxNsprPR_SecondsToInterval
+# define PR_MillisecondsToInterval VBoxNsprPR_MillisecondsToInterval
+# define PR_MicrosecondsToInterval VBoxNsprPR_MicrosecondsToInterval
+# define PR_IntervalToSeconds VBoxNsprPR_IntervalToSeconds
+# define PR_IntervalToMilliseconds VBoxNsprPR_IntervalToMilliseconds
+# define PR_IntervalToMicroseconds VBoxNsprPR_IntervalToMicroseconds
+# define PR_EnterMonitor VBoxNsprPR_EnterMonitor
+# define PR_ExitMonitor VBoxNsprPR_ExitMonitor
+# define PR_Notify VBoxNsprPR_Notify
+# define PR_NotifyAll VBoxNsprPR_NotifyAll
+# define PR_Wait VBoxNsprPR_Wait
+# define PR_NewMonitor VBoxNsprPR_NewMonitor
+# define PR_DestroyMonitor VBoxNsprPR_DestroyMonitor
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+typedef PRUint32 PRIntervalTime;
+
+#define PR_INTERVAL_MIN 1000UL
+#define PR_INTERVAL_MAX 100000UL
+#define PR_INTERVAL_NO_WAIT 0UL
+#define PR_INTERVAL_NO_TIMEOUT 0xffffffffUL
+
+NSPR_API(PRIntervalTime) PR_IntervalNow(void);
+NSPR_API(PRUint32) PR_TicksPerSecond(void);
+NSPR_API(PRIntervalTime) PR_SecondsToInterval(PRUint32 seconds);
+NSPR_API(PRIntervalTime) PR_MillisecondsToInterval(PRUint32 milli);
+NSPR_API(PRIntervalTime) PR_MicrosecondsToInterval(PRUint32 micro);
+NSPR_API(PRUint32) PR_IntervalToSeconds(PRIntervalTime ticks);
+NSPR_API(PRUint32) PR_IntervalToMilliseconds(PRIntervalTime ticks);
+NSPR_API(PRUint32) PR_IntervalToMicroseconds(PRIntervalTime ticks);
+
+typedef struct PRMonitor PRMonitor;
+
+NSPR_API(PRMonitor*) PR_NewMonitor(void);
+NSPR_API(void) PR_DestroyMonitor(PRMonitor *mon);
+NSPR_API(void) PR_EnterMonitor(PRMonitor *mon);
+NSPR_API(PRStatus) PR_ExitMonitor(PRMonitor *mon);
+NSPR_API(PRStatus) PR_Wait(PRMonitor *mon, PRIntervalTime ticks);
+NSPR_API(PRStatus) PR_Notify(PRMonitor *mon);
+NSPR_API(PRStatus) PR_NotifyAll(PRMonitor *mon);
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+# define PR_CreateThread VBoxNsprPR_CreateThread
+# define PR_JoinThread VBoxNsprPR_JoinThread
+# define PR_Sleep VBoxNsprPR_Sleep
+# define PR_GetCurrentThread VBoxNsprPR_GetCurrentThread
+# define PR_GetThreadState VBoxNsprPR_GetThreadState
+# define PR_SetThreadPrivate VBoxNsprPR_SetThreadPrivate
+# define PR_GetThreadPrivate VBoxNsprPR_GetThreadPrivate
+# define PR_NewThreadPrivateIndex VBoxNsprPR_NewThreadPrivateIndex
+# define PR_GetThreadPriority VBoxNsprPR_GetThreadPriority
+# define PR_SetThreadPriority VBoxNsprPR_SetThreadPriority
+# define PR_Interrupt VBoxNsprPR_Interrupt
+# define PR_ClearInterrupt VBoxNsprPR_ClearInterrupt
+# define PR_BlockInterrupt VBoxNsprPR_BlockInterrupt
+# define PR_UnblockInterrupt VBoxNsprPR_UnblockInterrupt
+# define PR_GetThreadScope VBoxNsprPR_GetThreadScope
+# define PR_GetThreadType VBoxNsprPR_GetThreadType
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+typedef struct PRThread PRThread;
+typedef struct PRThreadStack PRThreadStack;
+
+typedef enum PRThreadType {
+ PR_USER_THREAD,
+ PR_SYSTEM_THREAD
+} PRThreadType;
+
+typedef enum PRThreadScope {
+ PR_LOCAL_THREAD,
+ PR_GLOBAL_THREAD,
+ PR_GLOBAL_BOUND_THREAD
+} PRThreadScope;
+
+typedef enum PRThreadState {
+ PR_JOINABLE_THREAD,
+ PR_UNJOINABLE_THREAD
+} PRThreadState;
+
+typedef enum PRThreadPriority
+{
+ PR_PRIORITY_FIRST = 0, /* just a placeholder */
+ PR_PRIORITY_LOW = 0, /* the lowest possible priority */
+ PR_PRIORITY_NORMAL = 1, /* most common expected priority */
+ PR_PRIORITY_HIGH = 2, /* slightly more aggressive scheduling */
+ PR_PRIORITY_URGENT = 3, /* it does little good to have more than one */
+ PR_PRIORITY_LAST = 3 /* this is just a placeholder */
+} PRThreadPriority;
+
+NSPR_API(PRThread*) PR_CreateThread(PRThreadType type,
+ void (PR_CALLBACK *start)(void *arg),
+ void *arg,
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize);
+NSPR_API(PRStatus) PR_JoinThread(PRThread *thread);
+NSPR_API(PRThread*) PR_GetCurrentThread(void);
+#ifndef NO_NSPR_10_SUPPORT
+#define PR_CurrentThread() PR_GetCurrentThread() /* for nspr1.0 compat. */
+#endif /* NO_NSPR_10_SUPPORT */
+NSPR_API(PRThreadPriority) PR_GetThreadPriority(const PRThread *thread);
+NSPR_API(void) PR_SetThreadPriority(PRThread *thread, PRThreadPriority priority);
+
+typedef void (PR_CALLBACK *PRThreadPrivateDTOR)(void *priv);
+
+NSPR_API(PRStatus) PR_NewThreadPrivateIndex(
+ PRUintn *newIndex, PRThreadPrivateDTOR destructor);
+NSPR_API(PRStatus) PR_SetThreadPrivate(PRUintn tpdIndex, void *priv);
+NSPR_API(void*) PR_GetThreadPrivate(PRUintn tpdIndex);
+NSPR_API(PRStatus) PR_Interrupt(PRThread *thread);
+NSPR_API(void) PR_ClearInterrupt(void);
+NSPR_API(void) PR_BlockInterrupt(void);
+NSPR_API(void) PR_UnblockInterrupt(void);
+NSPR_API(PRStatus) PR_Sleep(PRIntervalTime ticks);
+NSPR_API(PRThreadScope) PR_GetThreadScope(const PRThread *thread);
+NSPR_API(PRThreadType) PR_GetThreadType(const PRThread *thread);
+NSPR_API(PRThreadState) PR_GetThreadState(const PRThread *thread);
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+# define PR_DestroyLock VBoxNsprPR_DestroyLock
+# define PR_Lock VBoxNsprPR_Lock
+# define PR_NewLock VBoxNsprPR_NewLock
+# define PR_Unlock VBoxNsprPR_Unlock
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+typedef struct PRLock PRLock;
+
+NSPR_API(PRLock*) PR_NewLock(void);
+NSPR_API(void) PR_DestroyLock(PRLock *lock);
+NSPR_API(void) PR_Lock(PRLock *lock);
+NSPR_API(PRStatus) PR_Unlock(PRLock *lock);
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+# define PR_NewCondVar VBoxNsprPR_NewCondVar
+# define PR_DestroyCondVar VBoxNsprPR_DestroyCondVar
+# define PR_WaitCondVar VBoxNsprPR_WaitCondVar
+# define PR_NotifyCondVar VBoxNsprPR_NotifyCondVar
+# define PR_NotifyAllCondVar VBoxNsprPR_NotifyAllCondVar
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+typedef struct PRCondVar PRCondVar;
+
+NSPR_API(PRCondVar*) PR_NewCondVar(PRLock *lock);
+NSPR_API(void) PR_DestroyCondVar(PRCondVar *cvar);
+NSPR_API(PRStatus) PR_WaitCondVar(PRCondVar *cvar, PRIntervalTime timeout);
+NSPR_API(PRStatus) PR_NotifyCondVar(PRCondVar *cvar);
+NSPR_API(PRStatus) PR_NotifyAllCondVar(PRCondVar *cvar);
+
+typedef struct PRCListStr PRCList;
+
+struct PRCListStr {
+ PRCList *next;
+ PRCList *prev;
+};
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+# define PL_DestroyEvent VBoxNsplPL_DestroyEvent
+# define PL_HandleEvent VBoxNsplPL_HandleEvent
+# define PL_InitEvent VBoxNsplPL_InitEvent
+# define PL_CreateEventQueue VBoxNsplPL_CreateEventQueue
+# define PL_CreateMonitoredEventQueue VBoxNsplPL_CreateMonitoredEventQueue
+# define PL_CreateNativeEventQueue VBoxNsplPL_CreateNativeEventQueue
+# define PL_DequeueEvent VBoxNsplPL_DequeueEvent
+# define PL_DestroyEventQueue VBoxNsplPL_DestroyEventQueue
+# define PL_EventAvailable VBoxNsplPL_EventAvailable
+# define PL_EventLoop VBoxNsplPL_EventLoop
+# define PL_GetEvent VBoxNsplPL_GetEvent
+# define PL_GetEventOwner VBoxNsplPL_GetEventOwner
+# define PL_GetEventQueueMonitor VBoxNsplPL_GetEventQueueMonitor
+# define PL_GetEventQueueSelectFD VBoxNsplPL_GetEventQueueSelectFD
+# define PL_MapEvents VBoxNsplPL_MapEvents
+# define PL_PostEvent VBoxNsplPL_PostEvent
+# define PL_PostSynchronousEvent VBoxNsplPL_PostSynchronousEvent
+# define PL_ProcessEventsBeforeID VBoxNsplPL_ProcessEventsBeforeID
+# define PL_ProcessPendingEvents VBoxNsplPL_ProcessPendingEvents
+# define PL_RegisterEventIDFunc VBoxNsplPL_RegisterEventIDFunc
+# define PL_RevokeEvents VBoxNsplPL_RevokeEvents
+# define PL_UnregisterEventIDFunc VBoxNsplPL_UnregisterEventIDFunc
+# define PL_WaitForEvent VBoxNsplPL_WaitForEvent
+# define PL_IsQueueNative VBoxNsplPL_IsQueueNative
+# define PL_IsQueueOnCurrentThread VBoxNsplPL_IsQueueOnCurrentThread
+# define PL_FavorPerformanceHint VBoxNsplPL_FavorPerformanceHint
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+typedef struct PLEvent PLEvent;
+typedef struct PLEventQueue PLEventQueue;
+
+PR_EXTERN(PLEventQueue*)
+PL_CreateEventQueue(const char* name, PRThread* handlerThread);
+PR_EXTERN(PLEventQueue *)
+ PL_CreateNativeEventQueue(
+ const char *name,
+ PRThread *handlerThread
+ );
+PR_EXTERN(PLEventQueue *)
+ PL_CreateMonitoredEventQueue(
+ const char *name,
+ PRThread *handlerThread
+ );
+PR_EXTERN(void)
+PL_DestroyEventQueue(PLEventQueue* self);
+PR_EXTERN(PRMonitor*)
+PL_GetEventQueueMonitor(PLEventQueue* self);
+
+#define PL_ENTER_EVENT_QUEUE_MONITOR(queue) \
+ PR_EnterMonitor(PL_GetEventQueueMonitor(queue))
+
+#define PL_EXIT_EVENT_QUEUE_MONITOR(queue) \
+ PR_ExitMonitor(PL_GetEventQueueMonitor(queue))
+
+PR_EXTERN(PRStatus) PL_PostEvent(PLEventQueue* self, PLEvent* event);
+PR_EXTERN(void*) PL_PostSynchronousEvent(PLEventQueue* self, PLEvent* event);
+PR_EXTERN(PLEvent*) PL_GetEvent(PLEventQueue* self);
+PR_EXTERN(PRBool) PL_EventAvailable(PLEventQueue* self);
+
+typedef void (PR_CALLBACK *PLEventFunProc)(PLEvent* event, void* data, PLEventQueue* queue);
+
+PR_EXTERN(void) PL_MapEvents(PLEventQueue* self, PLEventFunProc fun, void* data);
+PR_EXTERN(void) PL_RevokeEvents(PLEventQueue* self, void* owner);
+PR_EXTERN(void) PL_ProcessPendingEvents(PLEventQueue* self);
+PR_EXTERN(PLEvent*) PL_WaitForEvent(PLEventQueue* self);
+PR_EXTERN(void) PL_EventLoop(PLEventQueue* self);
+PR_EXTERN(PRInt32) PL_GetEventQueueSelectFD(PLEventQueue* self);
+PR_EXTERN(PRBool) PL_IsQueueOnCurrentThread( PLEventQueue *queue );
+PR_EXTERN(PRBool) PL_IsQueueNative(PLEventQueue *queue);
+
+typedef void* (PR_CALLBACK *PLHandleEventProc)(PLEvent* self);
+typedef void (PR_CALLBACK *PLDestroyEventProc)(PLEvent* self);
+PR_EXTERN(void)
+PL_InitEvent(PLEvent* self, void* owner,
+ PLHandleEventProc handler,
+ PLDestroyEventProc destructor);
+PR_EXTERN(void*) PL_GetEventOwner(PLEvent* self);
+PR_EXTERN(void) PL_HandleEvent(PLEvent* self);
+PR_EXTERN(void) PL_DestroyEvent(PLEvent* self);
+PR_EXTERN(void) PL_DequeueEvent(PLEvent* self, PLEventQueue* queue);
+PR_EXTERN(void) PL_FavorPerformanceHint(PRBool favorPerformanceOverEventStarvation, PRUint32 starvationDelay);
+
+struct PLEvent {
+ PRCList link;
+ PLHandleEventProc handler;
+ PLDestroyEventProc destructor;
+ void* owner;
+ void* synchronousResult;
+ PRLock* lock;
+ PRCondVar* condVar;
+ PRBool handled;
+#ifdef PL_POST_TIMINGS
+ PRIntervalTime postTime;
+#endif
+#ifdef XP_UNIX
+ unsigned long id;
+#endif /* XP_UNIX */
+ /* other fields follow... */
+};
+
+#if defined(XP_WIN) || defined(XP_OS2)
+
+PR_EXTERN(HWND)
+ PL_GetNativeEventReceiverWindow(
+ PLEventQueue *eqp
+ );
+#endif /* XP_WIN || XP_OS2 */
+
+#ifdef XP_UNIX
+
+PR_EXTERN(PRInt32)
+PL_ProcessEventsBeforeID(PLEventQueue *aSelf, unsigned long aID);
+
+typedef unsigned long (PR_CALLBACK *PLGetEventIDFunc)(void *aClosure);
+
+PR_EXTERN(void)
+PL_RegisterEventIDFunc(PLEventQueue *aSelf, PLGetEventIDFunc aFunc,
+ void *aClosure);
+PR_EXTERN(void) PL_UnregisterEventIDFunc(PLEventQueue *aSelf);
+
+#endif /* XP_UNIX */
+
+/* Standard "it worked" return value */
+#define NS_OK 0
+
+#define NS_ERROR_BASE ((nsresult) 0xC1F30000)
+
+/* Returned when an instance is not initialized */
+#define NS_ERROR_NOT_INITIALIZED (NS_ERROR_BASE + 1)
+
+/* Returned when an instance is already initialized */
+#define NS_ERROR_ALREADY_INITIALIZED (NS_ERROR_BASE + 2)
+
+/* Returned by a not implemented function */
+#define NS_ERROR_NOT_IMPLEMENTED ((nsresult) 0x80004001L)
+
+/* Returned when a given interface is not supported. */
+#define NS_NOINTERFACE ((nsresult) 0x80004002L)
+#define NS_ERROR_NO_INTERFACE NS_NOINTERFACE
+
+#define NS_ERROR_INVALID_POINTER ((nsresult) 0x80004003L)
+#define NS_ERROR_NULL_POINTER NS_ERROR_INVALID_POINTER
+
+/* Returned when a function aborts */
+#define NS_ERROR_ABORT ((nsresult) 0x80004004L)
+
+/* Returned when a function fails */
+#define NS_ERROR_FAILURE ((nsresult) 0x80004005L)
+
+/* Returned when an unexpected error occurs */
+#define NS_ERROR_UNEXPECTED ((nsresult) 0x8000ffffL)
+
+/* Returned when a memory allocation fails */
+#define NS_ERROR_OUT_OF_MEMORY ((nsresult) 0x8007000eL)
+
+/* Returned when an illegal value is passed */
+#define NS_ERROR_ILLEGAL_VALUE ((nsresult) 0x80070057L)
+#define NS_ERROR_INVALID_ARG NS_ERROR_ILLEGAL_VALUE
+
+/* Returned when a class doesn't allow aggregation */
+#define NS_ERROR_NO_AGGREGATION ((nsresult) 0x80040110L)
+
+/* Returned when an operation can't complete due to an unavailable resource */
+#define NS_ERROR_NOT_AVAILABLE ((nsresult) 0x80040111L)
+
+/* Returned when a class is not registered */
+#define NS_ERROR_FACTORY_NOT_REGISTERED ((nsresult) 0x80040154L)
+
+/* Returned when a class cannot be registered, but may be tried again later */
+#define NS_ERROR_FACTORY_REGISTER_AGAIN ((nsresult) 0x80040155L)
+
+/* Returned when a dynamically loaded factory couldn't be found */
+#define NS_ERROR_FACTORY_NOT_LOADED ((nsresult) 0x800401f8L)
+
+/* Returned when a factory doesn't support signatures */
+#define NS_ERROR_FACTORY_NO_SIGNATURE_SUPPORT \
+ (NS_ERROR_BASE + 0x101)
+
+/* Returned when a factory already is registered */
+#define NS_ERROR_FACTORY_EXISTS (NS_ERROR_BASE + 0x100)
+
+/**
+ * An "interface id" which can be used to uniquely identify a given
+ * interface.
+ * A "unique identifier". This is modeled after OSF DCE UUIDs.
+ */
+
+struct nsID {
+ PRUint32 m0;
+ PRUint16 m1;
+ PRUint16 m2;
+ PRUint8 m3[8];
+};
+
+typedef struct nsID nsID;
+typedef nsID nsIID;
+typedef nsID nsCID;
+
+#endif /* __cplusplus */
+
+#define VBOX_WINAPI
+
+/* Various COM types defined by their XPCOM equivalent */
+typedef PRInt64 LONG64;
+typedef PRInt32 LONG;
+typedef PRInt32 DWORD;
+typedef PRInt16 SHORT;
+typedef PRUint64 ULONG64;
+typedef PRUint32 ULONG;
+typedef PRUint16 USHORT;
+
+typedef PRBool BOOL;
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE 1
+#endif
+
+#define HRESULT nsresult
+#define SUCCEEDED NS_SUCCEEDED
+#define FAILED NS_FAILED
+
+/* OLE error codes */
+#define S_OK ((nsresult)NS_OK)
+#define E_UNEXPECTED NS_ERROR_UNEXPECTED
+#define E_NOTIMPL NS_ERROR_NOT_IMPLEMENTED
+#define E_OUTOFMEMORY NS_ERROR_OUT_OF_MEMORY
+#define E_INVALIDARG NS_ERROR_INVALID_ARG
+#define E_NOINTERFACE NS_ERROR_NO_INTERFACE
+#define E_POINTER NS_ERROR_NULL_POINTER
+#define E_ABORT NS_ERROR_ABORT
+#define E_FAIL NS_ERROR_FAILURE
+/* Note: a better analog for E_ACCESSDENIED would probably be
+ * NS_ERROR_NOT_AVAILABLE, but we want binary compatibility for now. */
+#define E_ACCESSDENIED ((nsresult)0x80070005L)
+
+/* Basic vartype for COM compatibility. */
+typedef enum VARTYPE
+{
+ VT_I2 = 2,
+ VT_I4 = 3,
+ VT_BSTR = 8,
+ VT_DISPATCH = 9,
+ VT_BOOL = 11,
+ VT_UNKNOWN = 13,
+ VT_I1 = 16,
+ VT_UI1 = 17,
+ VT_UI2 = 18,
+ VT_UI4 = 19,
+ VT_I8 = 20,
+ VT_UI8 = 21,
+ VT_HRESULT = 25
+} VARTYPE;
+
+/* Basic safearray type for COM compatibility. */
+typedef struct SAFEARRAY
+{
+ void *pv;
+ ULONG c;
+} SAFEARRAY;
+
+#define ComSafeArrayAsInParam(f) ((f) ? (f)->c : 0), ((f) ? (f)->pv : NULL)
+#define ComSafeArrayAsOutParam(f) (&amp;((f)->c)), (&amp;((f)->pv))
+#define ComSafeArrayAsOutTypeParam(f,t) (&amp;((f)->c)), (t**)(&amp;((f)->pv))
+#define ComSafeArrayAsOutIfaceParam(f,t) (&amp;((f)->c)), (t**)(&amp;((f)->pv))
+
+/* Glossing over differences between COM and XPCOM */
+#define IErrorInfo nsIException
+#define IUnknown nsISupports
+#define IDispatch nsISupports
+
+/* Make things as COM compatible as possible */
+#define interface struct
+#ifdef CONST_VTABLE
+# define CONST_VTBL const
+#else /* !CONST_VTABLE */
+# define CONST_VTBL
+#endif /* !CONST_VTABLE */
+
+#ifndef __cplusplus
+
+/** @todo this first batch of forward declarations (and the corresponding ones
+ * generated for each interface) are 100% redundant, remove eventually. */
+interface nsISupports; /* forward declaration */
+interface nsIException; /* forward declaration */
+interface nsIStackFrame; /* forward declaration */
+interface nsIEventTarget;/* forward declaration */
+interface nsIEventQueue; /* forward declaration */
+
+typedef interface nsISupports nsISupports; /* forward declaration */
+typedef interface nsIException nsIException; /* forward declaration */
+typedef interface nsIStackFrame nsIStackFrame; /* forward declaration */
+typedef interface nsIEventTarget nsIEventTarget;/* forward declaration */
+typedef interface nsIEventQueue nsIEventQueue; /* forward declaration */
+
+/* starting interface: nsISupports */
+#define NS_ISUPPORTS_IID_STR "00000000-0000-0000-c000-000000000046"
+
+#define NS_ISUPPORTS_IID \
+ { 0x00000000, 0x0000, 0x0000, \
+ {0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} }
+
+/**
+ * Reference count values
+ *
+ * This is the return type for AddRef() and Release() in nsISupports.
+ * IUnknown of COM returns an unsigned long from equivalent functions.
+ * The following ifdef exists to maintain binary compatibility with
+ * IUnknown.
+ */
+#if defined(XP_WIN) &amp;&amp; PR_BYTES_PER_LONG == 4
+typedef unsigned long nsrefcnt;
+#else
+typedef PRUint32 nsrefcnt;
+#endif
+
+/**
+ * Basic component object model interface. Objects which implement
+ * this interface support runtime interface discovery (QueryInterface)
+ * and a reference counted memory model (AddRef/Release). This is
+ * modelled after the win32 IUnknown API.
+ */
+#ifndef VBOX_WITH_GLUE
+struct nsISupports_vtbl
+{
+ nsresult (*QueryInterface)(nsISupports *pThis, const nsID *iid, void **resultp);
+ nsrefcnt (*AddRef)(nsISupports *pThis);
+ nsrefcnt (*Release)(nsISupports *pThis);
+};
+#else /* !VBOX_WITH_GLUE */
+struct nsISupportsVtbl
+{
+ nsresult (*QueryInterface)(nsISupports *pThis, const nsID *iid, void **resultp);
+ nsrefcnt (*AddRef)(nsISupports *pThis);
+ nsrefcnt (*Release)(nsISupports *pThis);
+};
+#define nsISupports_QueryInterface(p, iid, resultp) ((p)->lpVtbl->QueryInterface(p, iid, resultp))
+#define nsISupports_AddRef(p) ((p)->lpVtbl->AddRef(p))
+#define nsISupports_Release(p) ((p)->lpVtbl->Release(p))
+#define IUnknown_QueryInterface(p, iid, resultp) ((p)->lpVtbl->QueryInterface(p, iid, resultp))
+#define IUnknown_AddRef(p) ((p)->lpVtbl->AddRef(p))
+#define IUnknown_Release(p) ((p)->lpVtbl->Release(p))
+#define IDispatch_QueryInterface(p, iid, resultp) ((p)->lpVtbl->QueryInterface(p, iid, resultp))
+#define IDispatch_AddRef(p) ((p)->lpVtbl->AddRef(p))
+#define IDispatch_Release(p) ((p)->lpVtbl->Release(p))
+#endif /* !VBOX_WITH_GLUE */
+
+interface nsISupports
+{
+#ifndef VBOX_WITH_GLUE
+ struct nsISupports_vtbl *vtbl;
+#else /* !VBOX_WITH_GLUE */
+ CONST_VTBL struct nsISupportsVtbl *lpVtbl;
+#endif /* !VBOX_WITH_GLUE */
+};
+
+/* starting interface: nsIException */
+#define NS_IEXCEPTION_IID_STR "f3a8d3b4-c424-4edc-8bf6-8974c983ba78"
+
+#define NS_IEXCEPTION_IID \
+ {0xf3a8d3b4, 0xc424, 0x4edc, \
+ { 0x8b, 0xf6, 0x89, 0x74, 0xc9, 0x83, 0xba, 0x78 }}
+
+#ifndef VBOX_WITH_GLUE
+struct nsIException_vtbl
+{
+ /* Methods from the interface nsISupports */
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetMessage)(nsIException *pThis, PRUnichar * *aMessage);
+ nsresult (*GetResult)(nsIException *pThis, nsresult *aResult);
+ nsresult (*GetName)(nsIException *pThis, PRUnichar * *aName);
+ nsresult (*GetFilename)(nsIException *pThis, PRUnichar * *aFilename);
+ nsresult (*GetLineNumber)(nsIException *pThis, PRUint32 *aLineNumber);
+ nsresult (*GetColumnNumber)(nsIException *pThis, PRUint32 *aColumnNumber);
+ nsresult (*GetLocation)(nsIException *pThis, nsIStackFrame * *aLocation);
+ nsresult (*GetInner)(nsIException *pThis, nsIException * *aInner);
+ nsresult (*GetData)(nsIException *pThis, nsISupports * *aData);
+ nsresult (*ToString)(nsIException *pThis, PRUnichar **_retval);
+};
+#else /* !VBOX_WITH_GLUE */
+struct nsIExceptionVtbl
+{
+ nsresult (*QueryInterface)(nsIException *pThis, const nsID *iid, void **resultp);
+ nsrefcnt (*AddRef)(nsIException *pThis);
+ nsrefcnt (*Release)(nsIException *pThis);
+
+ nsresult (*GetMessage)(nsIException *pThis, PRUnichar * *aMessage);
+ nsresult (*GetResult)(nsIException *pThis, nsresult *aResult);
+ nsresult (*GetName)(nsIException *pThis, PRUnichar * *aName);
+ nsresult (*GetFilename)(nsIException *pThis, PRUnichar * *aFilename);
+ nsresult (*GetLineNumber)(nsIException *pThis, PRUint32 *aLineNumber);
+ nsresult (*GetColumnNumber)(nsIException *pThis, PRUint32 *aColumnNumber);
+ nsresult (*GetLocation)(nsIException *pThis, nsIStackFrame * *aLocation);
+ nsresult (*GetInner)(nsIException *pThis, nsIException * *aInner);
+ nsresult (*GetData)(nsIException *pThis, nsISupports * *aData);
+ nsresult (*ToString)(nsIException *pThis, PRUnichar **_retval);
+};
+#define nsIException_QueryInterface(p, iid, resultp) ((p)->lpVtbl->QueryInterface(p, iid, resultp))
+#define nsIException_AddRef(p) ((p)->lpVtbl->AddRef(p))
+#define nsIException_Release(p) ((p)->lpVtbl->Release(p))
+#define nsIException_get_Message(p, aMessage) ((p)->lpVtbl->GetMessage(p, aMessage))
+#define nsIException_GetMessage(p, aMessage) ((p)->lpVtbl->GetMessage(p, aMessage))
+#define nsIException_get_Result(p, aResult) ((p)->lpVtbl->GetResult(p, aResult))
+#define nsIException_GetResult(p, aResult) ((p)->lpVtbl->GetResult(p, aResult))
+#define nsIException_get_Name(p, aName) ((p)->lpVtbl->GetName(p, aName))
+#define nsIException_GetName(p, aName) ((p)->lpVtbl->GetName(p, aName))
+#define nsIException_get_Filename(p, aFilename) ((p)->lpVtbl->GetFilename(p, aFilename))
+#define nsIException_GetFilename(p, aFilename) ((p)->lpVtbl->GetFilename(p, aFilename))
+#define nsIException_get_LineNumber(p, aLineNumber) ((p)->lpVtbl->GetLineNumber(p, aLineNumber))
+#define nsIException_GetLineNumber(p, aLineNumber) ((p)->lpVtbl->GetLineNumber(p, aLineNumber))
+#define nsIException_get_ColumnNumber(p, aColumnNumber) ((p)->lpVtbl->GetColumnNumber(p, aColumnNumber))
+#define nsIException_GetColumnNumber(p, aColumnNumber) ((p)->lpVtbl->GetColumnNumber(p, aColumnNumber))
+#define nsIException_get_Inner(p, aInner) ((p)->lpVtbl->GetInner(p, aInner))
+#define nsIException_GetInner(p, aInner) ((p)->lpVtbl->GetInner(p, aInner))
+#define nsIException_get_Data(p, aData) ((p)->lpVtbl->GetData(p, aData))
+#define nsIException_GetData(p, aData) ((p)->lpVtbl->GetData(p, aData))
+#define nsIException_ToString(p, retval) ((p)->lpVtbl->ToString(p, retval))
+#define IErrorInfo_QueryInterface(p, iid, resultp) ((p)->lpVtbl->QueryInterface(p, iid, resultp))
+#define IErrorInfo_AddRef(p) ((p)->lpVtbl->AddRef(p))
+#define IErrorInfo_Release(p) ((p)->lpVtbl->Release(p))
+#define IErrorInfo_get_Message(p, aMessage) ((p)->lpVtbl->GetMessage(p, aMessage))
+#define IErrorInfo_GetMessage(p, aMessage) ((p)->lpVtbl->GetMessage(p, aMessage))
+#define IErrorInfo_get_Result(p, aResult) ((p)->lpVtbl->GetResult(p, aResult))
+#define IErrorInfo_GetResult(p, aResult) ((p)->lpVtbl->GetResult(p, aResult))
+#define IErrorInfo_get_Name(p, aName) ((p)->lpVtbl->GetName(p, aName))
+#define IErrorInfo_GetName(p, aName) ((p)->lpVtbl->GetName(p, aName))
+#define IErrorInfo_get_Filename(p, aFilename) ((p)->lpVtbl->GetFilename(p, aFilename))
+#define IErrorInfo_GetFilename(p, aFilename) ((p)->lpVtbl->GetFilename(p, aFilename))
+#define IErrorInfo_get_LineNumber(p, aLineNumber) ((p)->lpVtbl->GetLineNumber(p, aLineNumber))
+#define IErrorInfo_GetLineNumber(p, aLineNumber) ((p)->lpVtbl->GetLineNumber(p, aLineNumber))
+#define IErrorInfo_get_ColumnNumber(p, aColumnNumber) ((p)->lpVtbl->GetColumnNumber(p, aColumnNumber))
+#define IErrorInfo_GetColumnNumber(p, aColumnNumber) ((p)->lpVtbl->GetColumnNumber(p, aColumnNumber))
+#define IErrorInfo_get_Inner(p, aInner) ((p)->lpVtbl->GetInner(p, aInner))
+#define IErrorInfo_GetInner(p, aInner) ((p)->lpVtbl->GetInner(p, aInner))
+#define IErrorInfo_get_Data(p, aData) ((p)->lpVtbl->GetData(p, aData))
+#define IErrorInfo_GetData(p, aData) ((p)->lpVtbl->GetData(p, aData))
+#define IErrorInfo_ToString(p, retval) ((p)->lpVtbl->ToString(p, retval))
+#endif /* !VBOX_WITH_GLUE */
+
+interface nsIException
+{
+#ifndef VBOX_WITH_GLUE
+ struct nsIException_vtbl *vtbl;
+#else /* !VBOX_WITH_GLUE */
+ CONST_VTBL struct nsIExceptionVtbl *lpVtbl;
+#endif /* !VBOX_WITH_GLUE */
+};
+
+/* starting interface: nsIStackFrame */
+#define NS_ISTACKFRAME_IID_STR "91d82105-7c62-4f8b-9779-154277c0ee90"
+
+#define NS_ISTACKFRAME_IID \
+ {0x91d82105, 0x7c62, 0x4f8b, \
+ { 0x97, 0x79, 0x15, 0x42, 0x77, 0xc0, 0xee, 0x90 }}
+
+#ifndef VBOX_WITH_GLUE
+struct nsIStackFrame_vtbl
+{
+ /* Methods from the interface nsISupports */
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetLanguage)(nsIStackFrame *pThis, PRUint32 *aLanguage);
+ nsresult (*GetLanguageName)(nsIStackFrame *pThis, PRUnichar * *aLanguageName);
+ nsresult (*GetFilename)(nsIStackFrame *pThis, PRUnichar * *aFilename);
+ nsresult (*GetName)(nsIStackFrame *pThis, PRUnichar * *aName);
+ nsresult (*GetLineNumber)(nsIStackFrame *pThis, PRInt32 *aLineNumber);
+ nsresult (*GetSourceLine)(nsIStackFrame *pThis, PRUnichar * *aSourceLine);
+ nsresult (*GetCaller)(nsIStackFrame *pThis, nsIStackFrame * *aCaller);
+ nsresult (*ToString)(nsIStackFrame *pThis, PRUnichar **_retval);
+};
+#else /* !VBOX_WITH_GLUE */
+struct nsIStackFrameVtbl
+{
+ nsresult (*QueryInterface)(nsIStackFrame *pThis, const nsID *iid, void **resultp);
+ nsrefcnt (*AddRef)(nsIStackFrame *pThis);
+ nsrefcnt (*Release)(nsIStackFrame *pThis);
+
+ nsresult (*GetLanguage)(nsIStackFrame *pThis, PRUint32 *aLanguage);
+ nsresult (*GetLanguageName)(nsIStackFrame *pThis, PRUnichar * *aLanguageName);
+ nsresult (*GetFilename)(nsIStackFrame *pThis, PRUnichar * *aFilename);
+ nsresult (*GetName)(nsIStackFrame *pThis, PRUnichar * *aName);
+ nsresult (*GetLineNumber)(nsIStackFrame *pThis, PRInt32 *aLineNumber);
+ nsresult (*GetSourceLine)(nsIStackFrame *pThis, PRUnichar * *aSourceLine);
+ nsresult (*GetCaller)(nsIStackFrame *pThis, nsIStackFrame * *aCaller);
+ nsresult (*ToString)(nsIStackFrame *pThis, PRUnichar **_retval);
+};
+#define nsIStackFrame_QueryInterface(p, iid, resultp) ((p)->lpVtbl->QueryInterface(p, iid, resultp))
+#define nsIStackFrame_AddRef(p) ((p)->lpVtbl->AddRef(p))
+#define nsIStackFrame_Release(p) ((p)->lpVtbl->Release(p))
+#define nsIStackFrame_get_Language(p, aLanguage) ((p)->lpVtbl->GetLanguge(p, aLanguage))
+#define nsIStackFrame_GetLanguage(p, aLanguage) ((p)->lpVtbl->GetLanguge(p, aLanguage))
+#define nsIStackFrame_get_LanguageName(p, aLanguageName) ((p)->lpVtbl->GetLanguageName(p, aLanguageName))
+#define nsIStackFrame_GetLanguageName(p, aLanguageName) ((p)->lpVtbl->GetLanguageName(p, aLanguageName))
+#define nsIStackFrame_get_Filename(p, aFilename) ((p)->lpVtbl->GetFilename(p, aFilename))
+#define nsIStackFrame_GetFilename(p, aFilename) ((p)->lpVtbl->GetFilename(p, aFilename))
+#define nsIStackFrame_get_Name(p, aName) ((p)->lpVtbl->GetName(p, aName))
+#define nsIStackFrame_GetName(p, aName) ((p)->lpVtbl->GetName(p, aName))
+#define nsIStackFrame_get_LineNumber(p, aLineNumber) ((p)->lpVtbl->GetLineNumber(p, aLineNumber))
+#define nsIStackFrame_GetLineNumber(p, aLineNumber) ((p)->lpVtbl->GetLineNumber(p, aLineNumber))
+#define nsIStackFrame_get_SourceLine(p, aSourceLine) ((p)->lpVtbl->GetSourceLine(p, aSourceLine))
+#define nsIStackFrame_GetSourceLine(p, aSourceLine) ((p)->lpVtbl->GetSourceLine(p, aSourceLine))
+#define nsIStackFrame_get_Caller(p, aCaller) ((p)->lpVtbl->GetCaller(p, aCaller))
+#define nsIStackFrame_GetCaller(p, aCaller) ((p)->lpVtbl->GetCaller(p, aCaller))
+#define nsIStackFrame_ToString(p, retval) ((p)->lpVtbl->ToString(p, retval))
+#endif /* !VBOX_WITH_GLUE */
+
+interface nsIStackFrame
+{
+#ifndef VBOX_WITH_GLUE
+ struct nsIStackFrame_vtbl *vtbl;
+#else /* !VBOX_WITH_GLUE */
+ CONST_VTBL struct nsIStackFrameVtbl *lpVtbl;
+#endif /* !VBOX_WITH_GLUE */
+};
+
+/* starting interface: nsIEventTarget */
+#define NS_IEVENTTARGET_IID_STR "ea99ad5b-cc67-4efb-97c9-2ef620a59f2a"
+
+#define NS_IEVENTTARGET_IID \
+ {0xea99ad5b, 0xcc67, 0x4efb, \
+ { 0x97, 0xc9, 0x2e, 0xf6, 0x20, 0xa5, 0x9f, 0x2a }}
+
+#ifndef VBOX_WITH_GLUE
+struct nsIEventTarget_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*PostEvent)(nsIEventTarget *pThis, PLEvent * aEvent);
+ nsresult (*IsOnCurrentThread)(nsIEventTarget *pThis, PRBool *_retval);
+};
+#else /* !VBOX_WITH_GLUE */
+struct nsIEventTargetVtbl
+{
+ nsresult (*QueryInterface)(nsIEventTarget *pThis, const nsID *iid, void **resultp);
+ nsrefcnt (*AddRef)(nsIEventTarget *pThis);
+ nsrefcnt (*Release)(nsIEventTarget *pThis);
+
+ nsresult (*PostEvent)(nsIEventTarget *pThis, PLEvent * aEvent);
+ nsresult (*IsOnCurrentThread)(nsIEventTarget *pThis, PRBool *_retval);
+};
+#define nsIEventTarget_QueryInterface(p, iid, resultp) ((p)->lpVtbl->QueryInterface(p, iid, resultp))
+#define nsIEventTarget_AddRef(p) ((p)->lpVtbl->AddRef(p))
+#define nsIEventTarget_Release(p) ((p)->lpVtbl->Release(p))
+#define nsIEventTarget_PostEvent(p, aEvent) ((p)->lpVtbl->PostEvent(p, aEvent))
+#define nsIEventTarget_IsOnCurrentThread(p, retval) ((p)->lpVtbl->IsOnCurrentThread(p, retval))
+#endif /* !VBOX_WITH_GLUE */
+
+interface nsIEventTarget
+{
+#ifndef VBOX_WITH_GLUE
+ struct nsIEventTarget_vtbl *vtbl;
+#else /* !VBOX_WITH_GLUE */
+ CONST_VTBL struct nsIEventTargetVtbl *lpVtbl;
+#endif /* !VBOX_WITH_GLUE */
+};
+
+/* starting interface: nsIEventQueue */
+#define NS_IEVENTQUEUE_IID_STR "176afb41-00a4-11d3-9f2a-00400553eef0"
+
+#define NS_IEVENTQUEUE_IID \
+ {0x176afb41, 0x00a4, 0x11d3, \
+ { 0x9f, 0x2a, 0x00, 0x40, 0x05, 0x53, 0xee, 0xf0 }}
+
+#ifndef VBOX_WITH_GLUE
+struct nsIEventQueue_vtbl
+{
+ struct nsIEventTarget_vtbl nsieventtarget;
+
+ nsresult (*InitEvent)(nsIEventQueue *pThis, PLEvent * aEvent, void * owner, PLHandleEventProc handler, PLDestroyEventProc destructor);
+ nsresult (*PostSynchronousEvent)(nsIEventQueue *pThis, PLEvent * aEvent, void * *aResult);
+ nsresult (*PendingEvents)(nsIEventQueue *pThis, PRBool *_retval);
+ nsresult (*ProcessPendingEvents)(nsIEventQueue *pThis);
+ nsresult (*EventLoop)(nsIEventQueue *pThis);
+ nsresult (*EventAvailable)(nsIEventQueue *pThis, PRBool *aResult);
+ nsresult (*GetEvent)(nsIEventQueue *pThis, PLEvent * *_retval);
+ nsresult (*HandleEvent)(nsIEventQueue *pThis, PLEvent * aEvent);
+ nsresult (*WaitForEvent)(nsIEventQueue *pThis, PLEvent * *_retval);
+ PRInt32 (*GetEventQueueSelectFD)(nsIEventQueue *pThis);
+ nsresult (*Init)(nsIEventQueue *pThis, PRBool aNative);
+ nsresult (*InitFromPRThread)(nsIEventQueue *pThis, PRThread * thread, PRBool aNative);
+ nsresult (*InitFromPLQueue)(nsIEventQueue *pThis, PLEventQueue * aQueue);
+ nsresult (*EnterMonitor)(nsIEventQueue *pThis);
+ nsresult (*ExitMonitor)(nsIEventQueue *pThis);
+ nsresult (*RevokeEvents)(nsIEventQueue *pThis, void * owner);
+ nsresult (*GetPLEventQueue)(nsIEventQueue *pThis, PLEventQueue * *_retval);
+ nsresult (*IsQueueNative)(nsIEventQueue *pThis, PRBool *_retval);
+ nsresult (*StopAcceptingEvents)(nsIEventQueue *pThis);
+};
+#else /* !VBOX_WITH_GLUE */
+struct nsIEventQueueVtbl
+{
+ nsresult (*QueryInterface)(nsIEventQueue *pThis, const nsID *iid, void **resultp);
+ nsrefcnt (*AddRef)(nsIEventQueue *pThis);
+ nsrefcnt (*Release)(nsIEventQueue *pThis);
+
+ nsresult (*PostEvent)(nsIEventQueue *pThis, PLEvent * aEvent);
+ nsresult (*IsOnCurrentThread)(nsIEventQueue *pThis, PRBool *_retval);
+
+ nsresult (*InitEvent)(nsIEventQueue *pThis, PLEvent * aEvent, void * owner, PLHandleEventProc handler, PLDestroyEventProc destructor);
+ nsresult (*PostSynchronousEvent)(nsIEventQueue *pThis, PLEvent * aEvent, void * *aResult);
+ nsresult (*PendingEvents)(nsIEventQueue *pThis, PRBool *_retval);
+ nsresult (*ProcessPendingEvents)(nsIEventQueue *pThis);
+ nsresult (*EventLoop)(nsIEventQueue *pThis);
+ nsresult (*EventAvailable)(nsIEventQueue *pThis, PRBool *aResult);
+ nsresult (*GetEvent)(nsIEventQueue *pThis, PLEvent * *_retval);
+ nsresult (*HandleEvent)(nsIEventQueue *pThis, PLEvent * aEvent);
+ nsresult (*WaitForEvent)(nsIEventQueue *pThis, PLEvent * *_retval);
+ PRInt32 (*GetEventQueueSelectFD)(nsIEventQueue *pThis);
+ nsresult (*Init)(nsIEventQueue *pThis, PRBool aNative);
+ nsresult (*InitFromPRThread)(nsIEventQueue *pThis, PRThread * thread, PRBool aNative);
+ nsresult (*InitFromPLQueue)(nsIEventQueue *pThis, PLEventQueue * aQueue);
+ nsresult (*EnterMonitor)(nsIEventQueue *pThis);
+ nsresult (*ExitMonitor)(nsIEventQueue *pThis);
+ nsresult (*RevokeEvents)(nsIEventQueue *pThis, void * owner);
+ nsresult (*GetPLEventQueue)(nsIEventQueue *pThis, PLEventQueue * *_retval);
+ nsresult (*IsQueueNative)(nsIEventQueue *pThis, PRBool *_retval);
+ nsresult (*StopAcceptingEvents)(nsIEventQueue *pThis);
+};
+#define nsIEventQueue_QueryInterface(p, iid, resultp) ((p)->lpVtbl->QueryInterface(p, iid, resultp))
+#define nsIEventQueue_AddRef(p) ((p)->lpVtbl->AddRef(p))
+#define nsIEventQueue_Release(p) ((p)->lpVtbl->Release(p))
+#define nsIEventQueue_PostEvent(p, aEvent) ((p)->lpVtbl->PostEvent(p, aEvent))
+#define nsIEventQueue_IsOnCurrentThread(p, retval) ((p)->lpVtbl->IsOnCurrentThread(p, retval))
+#define nsIEventQueue_InitEvent(p, aEvent, owner, handler, destructor) ((p)->lpVtbl->InitEvent(p, aEvent, owner, handler, destructor))
+#define nsIEventQueue_PostSynchronousEvent(p, aEvent, aResult) ((p)->lpVtbl->PostSynchronousEvent(p, aEvent, aResult))
+#define nsIEventQueue_ProcessPendingEvents(p) ((p)->lpVtbl->ProcessPendingEvents(p))
+#define nsIEventQueue_EventLoop(p) ((p)->lpVtbl->EventLoop(p))
+#define nsIEventQueue_EventAvailable(p, aResult) ((p)->lpVtbl->EventAvailable(p, aResult))
+#define nsIEventQueue_get_Event(p, aEvent) ((p)->lpVtbl->GetEvent(p, aEvent))
+#define nsIEventQueue_GetEvent(p, aEvent) ((p)->lpVtbl->GetEvent(p, aEvent))
+#define nsIEventQueue_HandleEvent(p, aEvent) ((p)->lpVtbl->HandleEvent(p, aEvent))
+#define nsIEventQueue_WaitForEvent(p, aEvent) ((p)->lpVtbl->WaitForEvent(p, aEvent))
+#define nsIEventQueue_GetEventQueueSelectFD(p) ((p)->lpVtbl->GetEventQueueSelectFD(p))
+#define nsIEventQueue_Init(p, aNative) ((p)->lpVtbl->Init(p, aNative))
+#define nsIEventQueue_InitFromPLQueue(p, aQueue) ((p)->lpVtbl->InitFromPLQueue(p, aQueue))
+#define nsIEventQueue_EnterMonitor(p) ((p)->lpVtbl->EnterMonitor(p))
+#define nsIEventQueue_ExitMonitor(p) ((p)->lpVtbl->ExitMonitor(p))
+#define nsIEventQueue_RevokeEvents(p, owner) ((p)->lpVtbl->RevokeEvents(p, owner))
+#define nsIEventQueue_GetPLEventQueue(p, retval) ((p)->lpVtbl->GetPLEventQueue(p, retval))
+#define nsIEventQueue_IsQueueNative(p, retval) ((p)->lpVtbl->IsQueueNative(p, retval))
+#define nsIEventQueue_StopAcceptingEvents(p) ((p)->lpVtbl->StopAcceptingEvents(p))
+#endif /* !VBOX_WITH_GLUE */
+
+interface nsIEventQueue
+{
+#ifndef VBOX_WITH_GLUE
+ struct nsIEventQueue_vtbl *vtbl;
+#else /* !VBOX_WITH_GLUE */
+ CONST_VTBL struct nsIEventQueueVtbl *lpVtbl;
+#endif /* !VBOX_WITH_GLUE */
+};
+</xsl:text>
+ <xsl:call-template name="xsltprocNewlineOutputHack"/>
+ <xsl:apply-templates/>
+ <xsl:text>
+
+#endif /* __cplusplus */
+
+#endif /* !WIN32 */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+
+/**
+ * Function table for dynamic linking.
+ * Use VBoxGetCAPIFunctions() to obtain the pointer to it.
+ */
+typedef struct VBOXCAPI
+{
+ /** The size of the structure. */
+ unsigned cb;
+ /** The structure version. */
+ unsigned uVersion;
+
+ /** Gets the VirtualBox version, major * 1000000 + minor * 1000 + patch. */
+ unsigned int (*pfnGetVersion)(void);
+
+ /** Gets the VirtualBox API version, major * 1000 + minor, e.g. 4003. */
+ unsigned int (*pfnGetAPIVersion)(void);
+
+ /**
+ * New and preferred way to initialize the C bindings for an API client.
+ *
+ * This way is much more flexible, as it can easily handle multiple
+ * sessions (important with more complicated API clients, including
+ * multithreaded ones), and even VBoxSVC crashes can be detected and
+ * processed appropriately by listening for events from the associated
+ * event source in VirtualBoxClient. It is completely up to the client
+ * to decide what to do (terminate or continue after getting new
+ * object references to server-side objects). Must be called in the
+ * primary thread of the client, later API use can be done in any
+ * thread.
+ *
+ * Note that the returned reference is owned by the caller, and thus it's
+ * the caller's responsibility to handle the reference count appropriately.
+ *
+ * @param pszVirtualBoxClientIID pass IVIRTUALBOXCLIENT_IID_STR
+ * @param ppVirtualBoxClient output parameter for VirtualBoxClient
+ * reference, handled as usual with COM/XPCOM.
+ * @returns COM/XPCOM error code
+ */
+ HRESULT (*pfnClientInitialize)(const char *pszVirtualBoxClientIID,
+ IVirtualBoxClient **ppVirtualBoxClient);
+ /**
+ * Initialize the use of the C bindings in a non-primary thread.
+ *
+ * Must be called on any newly created thread which wants to use the
+ * VirtualBox API.
+ *
+ * @returns COM/XPCOM error code
+ */
+ HRESULT (*pfnClientThreadInitialize)(void);
+ /**
+ * Uninitialize the use of the C bindings in a non-primary thread.
+ *
+ * Should be called before terminating the thread which initialized the
+ * C bindings using pfnClientThreadInitialize.
+ *
+ * @returns COM/XPCOM error code
+ */
+ HRESULT (*pfnClientThreadUninitialize)(void);
+ /**
+ * Uninitialize the C bindings for an API client.
+ *
+ * Should be called when the API client is about to terminate and does
+ * not want to use the C bindings any more. It will invalidate all
+ * object references. It is possible, however, to change one's mind,
+ * and call pfnClientInitialize again to continue using the API, as long
+ * as none of the object references from before the re-initialization
+ * are used. Must be called from the primary thread of the client.
+ */
+ void (*pfnClientUninitialize)(void);
+
+ /**
+ * Deprecated way to initialize the C bindings and getting important
+ * object references. Kept for backwards compatibility.
+ *
+ * If any returned reference is NULL then the initialization failed.
+ * Note that the returned references are owned by the C bindings. The
+ * number of calls to Release in the client code must match the number
+ * of calls to AddRef, and additionally at no point in time there can
+ * be more Release calls than AddRef calls.
+ *
+ * @param pszVirtualBoxIID pass IVIRTUALBOX_IID_STR
+ * @param ppVirtualBox output parameter for VirtualBox reference,
+ * owned by C bindings
+ * @param pszSessionIID pass ISESSION_IID_STR
+ * @param ppSession output parameter for Session reference,
+ * owned by C bindings
+ */
+ void (*pfnComInitialize)(const char *pszVirtualBoxIID,
+ IVirtualBox **ppVirtualBox,
+ const char *pszSessionIID,
+ ISession **ppSession);
+ /**
+ * Deprecated way to uninitialize the C bindings for an API client.
+ * Kept for backwards compatibility and must be used if the C bindings
+ * were initialized using pfnComInitialize. */
+ void (*pfnComUninitialize)(void);
+
+ /**
+ * Free string managed by COM/XPCOM.
+ *
+ * @param pwsz pointer to string to be freed
+ */
+ void (*pfnComUnallocString)(BSTR pwsz);
+#ifndef WIN32
+ /** Legacy function, was always for freeing strings only. */
+#define pfnComUnallocMem(pv) pfnComUnallocString((BSTR)(pv))
+#endif /* !WIN32 */
+
+ /**
+ * Convert string from UTF-16 encoding to UTF-8 encoding.
+ *
+ * @param pwszString input string
+ * @param ppszString output string
+ * @returns IPRT status code
+ */
+ int (*pfnUtf16ToUtf8)(CBSTR pwszString, char **ppszString);
+ /**
+ * Convert string from UTF-8 encoding to UTF-16 encoding.
+ *
+ * @param pszString input string
+ * @param ppwszString output string
+ * @returns IPRT status code
+ */
+ int (*pfnUtf8ToUtf16)(const char *pszString, BSTR *ppwszString);
+ /**
+ * Free memory returned by pfnUtf16ToUtf8. Do not use for anything else.
+ *
+ * @param pszString string to be freed.
+ */
+ void (*pfnUtf8Free)(char *pszString);
+ /**
+ * Free memory returned by pfnUtf8ToUtf16. Do not use for anything else.
+ *
+ * @param pwszString string to be freed.
+ */
+ void (*pfnUtf16Free)(BSTR pwszString);
+
+ /**
+ * Create a safearray (used for passing arrays to COM/XPCOM)
+ *
+ * Must be freed by pfnSafeArrayDestroy.
+ *
+ * @param vt variant type, defines the size of the elements
+ * @param lLbound lower bound of the index, should be 0
+ * @param cElements number of elements
+ * @returns pointer to safearray
+ */
+ SAFEARRAY *(*pfnSafeArrayCreateVector)(VARTYPE vt, LONG lLbound, ULONG cElements);
+ /**
+ * Pre-allocate a safearray to be used by an out safearray parameter
+ *
+ * Must be freed by pfnSafeArrayDestroy.
+ *
+ * @returns pointer to safearray (system dependent, may be NULL if
+ * there is no need to pre-allocate a safearray)
+ */
+ SAFEARRAY *(*pfnSafeArrayOutParamAlloc)(void);
+ /**
+ * Copy a C array into a safearray (for passing as an input parameter)
+ *
+ * @param psa pointer to already created safearray.
+ * @param pv pointer to memory block to copy into safearray.
+ * @param cb number of bytes to copy.
+ * @returns COM/XPCOM error code
+ */
+ HRESULT (*pfnSafeArrayCopyInParamHelper)(SAFEARRAY *psa, const void *pv, ULONG cb);
+ /**
+ * Copy a safearray into a C array (for getting an output parameter)
+ *
+ * @param ppv output pointer to newly created array, which has to
+ * be freed with pfnArrayOutFree.
+ * @param pcb number of bytes in the output buffer.
+ * @param vt variant type, defines the size of the elements
+ * @param psa pointer to safearray for getting the data
+ * @returns COM/XPCOM error code
+ */
+ HRESULT (*pfnSafeArrayCopyOutParamHelper)(void **ppv, ULONG *pcb, VARTYPE vt, SAFEARRAY *psa);
+ /**
+ * Copy a safearray into a C array (special variant for interface pointers)
+ *
+ * @param ppaObj output pointer to newly created array, which has
+ * to be freed with pfnArrayOutFree. Note that it's the caller's
+ * responsibility to call Release() on each non-NULL interface
+ * pointer before freeing.
+ * @param pcObj number of pointers in the output buffer.
+ * @param psa pointer to safearray for getting the data
+ * @returns COM/XPCOM error code
+ */
+ HRESULT (*pfnSafeArrayCopyOutIfaceParamHelper)(IUnknown ***ppaObj, ULONG *pcObj, SAFEARRAY *psa);
+ /**
+ * Free a safearray
+ *
+ * @param psa pointer to safearray
+ * @returns COM/XPCOM error code
+ */
+ HRESULT (*pfnSafeArrayDestroy)(SAFEARRAY *psa);
+ /**
+ * Free an out array created by pfnSafeArrayCopyOutParamHelper or
+ * pdnSafeArrayCopyOutIfaceParamHelper.
+ *
+ * @param psa pointer to memory block
+ * @returns COM/XPCOM error code
+ */
+ HRESULT (*pfnArrayOutFree)(void *pv);
+
+#ifndef WIN32
+ /**
+ * Get XPCOM event queue. Deprecated!
+ *
+ * @param ppEventQueue output parameter for nsIEventQueue reference,
+ * owned by C bindings.
+ */
+ void (*pfnGetEventQueue)(nsIEventQueue **ppEventQueue);
+#endif /* !WIN32 */
+
+ /**
+ * Get current COM/XPCOM exception.
+ *
+ * @param ppException output parameter for exception info reference,
+ * may be @c NULL if no exception object has been created by
+ * a previous COM/XPCOM call.
+ * @returns COM/XPCOM error code
+ */
+ HRESULT (*pfnGetException)(IErrorInfo **ppException);
+ /**
+ * Clears current COM/XPCOM exception.
+ *
+ * @returns COM/XPCOM error code
+ */
+ HRESULT (*pfnClearException)(void);
+
+ /**
+ * Process the event queue for a given amount of time.
+ *
+ * Must be called on the primary thread. Typical timeouts are from 200 to
+ * 5000 msecs, to allow for checking a volatile variable if the event queue
+ * processing should be terminated (,
+ * or 0 if only the pending events should be processed, without waiting.
+ *
+ * @param iTimeoutMS how long to process the event queue, -1 means
+ * infinitely long
+ * @returns status code
+ * @retval 0 if at least one event has been processed
+ * @retval 1 if any signal interrupted the native system call (or returned
+ * otherwise)
+ * @retval 2 if the event queue was explicitly interrupted
+ * @retval 3 if the timeout expired
+ * @retval 4 if the function was called from the wrong thread
+ * @retval 5 for all other (unexpected) errors
+ */
+ int (*pfnProcessEventQueue)(LONG64 iTimeoutMS);
+ /**
+ * Interrupt event queue processing.
+ *
+ * Can be called on any thread. Note that this function is not async-signal
+ * safe, so never use it in such a context, instead use a volatile global
+ * variable and a sensible timeout.
+ * @returns 0 if successful, 1 otherwise.
+ */
+ int (*pfnInterruptEventQueueProcessing)(void);
+
+ /**
+ * Clear memory used by a UTF-8 string. Must be zero terminated.
+ * Can be used for any UTF-8 or ASCII/ANSI string.
+ *
+ * @param pszString input/output string
+ */
+ void (*pfnUtf8Clear)(char *pszString);
+ /**
+ * Clear memory used by a UTF-16 string. Must be zero terminated.
+ * Can be used for any UTF-16 or UCS-2 string.
+ *
+ * @param pwszString input/output string
+ */
+ void (*pfnUtf16Clear)(BSTR pwszString);
+
+ /** Tail version, same as uVersion.
+ *
+ * This should only be accessed if for some reason an API client needs
+ * exactly the version it requested, or if cb is used to calculate the
+ * address of this field. It may move as the structure before this is
+ * allowed to grow as long as all the data from earlier minor versions
+ * remains at the same place.
+ */
+ unsigned uEndVersion;
+} VBOXCAPI;
+/** Pointer to a const VBOXCAPI function table. */
+typedef VBOXCAPI const *PCVBOXCAPI;
+#ifndef WIN32
+/** Backwards compatibility: Pointer to a const VBOXCAPI function table.
+ * Use PCVBOXCAPI instead. */
+typedef VBOXCAPI const *PCVBOXXPCOM;
+#endif /* !WIN32 */
+
+#ifndef WIN32
+/** Backwards compatibility: make sure old code using VBOXXPCOMC still compiles.
+ * Use VBOXCAPI instead. */
+#define VBOXXPCOMC VBOXCAPI
+#endif /* !WIN32 */
+
+/** Extract the C API style major version.
+ * Useful for comparing the interface version in VBOXCAPI::uVersion. */
+#define VBOX_CAPI_MAJOR(x) (((x) &amp; 0xffff0000U) &gt;&gt; 16)
+
+/** Extract the C API style major version.
+ * Useful for comparing the interface version in VBOXCAPI::uVersion. */
+#define VBOX_CAPI_MINOR(x) ((x) &amp; 0x0000ffffU)
+
+/** The current interface version.
+ * For use with VBoxGetCAPIFunctions and to be found in VBOXCAPI::uVersion. */
+#define VBOX_CAPI_VERSION 0x00040001U
+
+#ifndef WIN32
+/** Backwards compatibility: The current interface version.
+ * Use VBOX_CAPI_VERSION instead. */
+#define VBOX_XPCOMC_VERSION VBOX_CAPI_VERSION
+#endif /* !WIN32 */
+
+/** VBoxGetCAPIFunctions. */
+VBOXCAPI_DECL(PCVBOXCAPI) VBoxGetCAPIFunctions(unsigned uVersion);
+#ifndef WIN32
+/** Backwards compatibility: VBoxGetXPCOMCFunctions.
+ * Use VBoxGetCAPIFunctions instead. */
+VBOXCAPI_DECL(PCVBOXCAPI) VBoxGetXPCOMCFunctions(unsigned uVersion);
+#endif /* !WIN32 */
+
+/** Typedef for VBoxGetCAPIFunctions. */
+typedef PCVBOXCAPI (*PFNVBOXGETCAPIFUNCTIONS)(unsigned uVersion);
+#ifndef WIN32
+/** Backwards compatibility: Typedef for VBoxGetXPCOMCFunctions.
+ * Use PFNVBOXGETCAPIFUNCTIONS instead. */
+typedef PCVBOXCAPI (*PFNVBOXGETXPCOMCFUNCTIONS)(unsigned uVersion);
+#endif /* !WIN32 */
+
+/** The symbol name of VBoxGetCAPIFunctions. */
+#ifdef __OS2__
+# define VBOX_GET_CAPI_FUNCTIONS_SYMBOL_NAME "_VBoxGetCAPIFunctions"
+#else /* !__OS2__ */
+# define VBOX_GET_CAPI_FUNCTIONS_SYMBOL_NAME "VBoxGetCAPIFunctions"
+#endif /* !__OS2__ */
+#ifndef WIN32
+/** Backwards compatibility: The symbol name of VBoxGetXPCOMCFunctions.
+ * Use VBOX_GET_CAPI_FUNCTIONS_SYMBOL_NAME instead. */
+# ifdef __OS2__
+# define VBOX_GET_XPCOMC_FUNCTIONS_SYMBOL_NAME "_VBoxGetXPCOMCFunctions"
+# else /* !__OS2__ */
+# define VBOX_GET_XPCOMC_FUNCTIONS_SYMBOL_NAME "VBoxGetXPCOMCFunctions"
+# endif /* !__OS2__ */
+#endif /* !WIN32 */
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* !___VirtualBox_CAPI_h */
+</xsl:text>
+</xsl:template>
+
+<!--
+ * ignore all |if|s except those for XPIDL target
+-->
+<xsl:template match="if">
+ <xsl:if test="@target='xpidl'">
+ <xsl:apply-templates/>
+ </xsl:if>
+</xsl:template>
+<xsl:template match="if" mode="forward">
+ <xsl:if test="@target='xpidl'">
+ <xsl:apply-templates mode="forward"/>
+ </xsl:if>
+</xsl:template>
+<xsl:template match="if" mode="forwarder">
+ <xsl:if test="@target='midl'">
+ <xsl:apply-templates mode="forwarder"/>
+ </xsl:if>
+</xsl:template>
+
+
+<!--
+ * libraries
+-->
+<xsl:template match="idl/library">
+ <!-- result codes -->
+ <xsl:call-template name="xsltprocNewlineOutputHack"/>
+ <xsl:for-each select="application/result">
+ <xsl:apply-templates select="."/>
+ </xsl:for-each>
+ <xsl:call-template name="xsltprocNewlineOutputHack"/>
+ <xsl:call-template name="xsltprocNewlineOutputHack"/>
+ <!-- forward declarations -->
+ <xsl:apply-templates select="application/interface | application/if/interface" mode="forward"/>
+ <xsl:call-template name="xsltprocNewlineOutputHack"/>
+ <!-- typedef'ing the struct declarations -->
+ <xsl:apply-templates select="application/interface | application/if/interface" mode="typedef"/>
+ <xsl:call-template name="xsltprocNewlineOutputHack"/>
+ <!-- all enums go first -->
+ <xsl:apply-templates select="application/enum | application/if/enum"/>
+ <!-- everything else but result codes and enums
+ <xsl:apply-templates select="*[not(self::result or self::enum) and
+ not(self::if[result] or self::if[enum])]"/> -->
+ <!-- the modules (i.e. everything else) -->
+ <xsl:apply-templates select="application/interface | application/if[interface]
+ | application/module | application/if[module]"/>
+ <!-- -->
+</xsl:template>
+
+
+<!--
+ * result codes
+-->
+<xsl:template match="result">
+ <xsl:value-of select="concat('#define ',@name,' ((HRESULT)',@value, ')')"/>
+ <xsl:text>&#x0A;</xsl:text>
+</xsl:template>
+
+
+<!--
+ * forward declarations
+-->
+<xsl:template match="interface" mode="forward">
+ <xsl:if test="not(@internal='yes')">
+ <xsl:text>interface </xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:text>;&#x0A;</xsl:text>
+ </xsl:if>
+</xsl:template>
+
+
+<!--
+ * typedef'ing the struct declarations
+-->
+<xsl:template match="interface" mode="typedef">
+ <xsl:if test="not(@internal='yes')">
+ <xsl:text>typedef interface </xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:text>;&#x0A;</xsl:text>
+ </xsl:if>
+</xsl:template>
+
+
+<!--
+ * COBJMACRO style convenience macros for calling methods
+-->
+<xsl:template match="interface" mode="cobjmacro">
+ <xsl:param name="iface"/>
+
+ <xsl:variable name="extends" select="@extends"/>
+ <xsl:choose>
+ <xsl:when test="$extends='$unknown'">
+ <xsl:text>#define </xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text>_QueryInterface(p, iid, resultp) ((p)->lpVtbl->QueryInterface(p, iid, resultp))&#x0A;</xsl:text>
+ <xsl:text>#define </xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text>_AddRef(p) ((p)->lpVtbl->AddRef(p))&#x0A;</xsl:text>
+ <xsl:text>#define </xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text>_Release(p) ((p)->lpVtbl->Release(p))&#x0A;</xsl:text>
+ </xsl:when>
+ <xsl:when test="$extends='$errorinfo'">
+ <xsl:text>#define </xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text>_QueryInterface(p, iid, resultp) ((p)->lpVtbl->QueryInterface(p, iid, resultp))&#x0A;</xsl:text>
+ <xsl:text>#define </xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text>_AddRef(p) ((p)->lpVtbl->AddRef(p))&#x0A;</xsl:text>
+ <xsl:text>#define </xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text>_Release(p) ((p)->lpVtbl->Release(p))&#x0A;</xsl:text>
+ <xsl:text>#define </xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text>_get_Message(p, aMessage) ((p)->lpVtbl->GetMessage(p, aMessage))&#x0A;</xsl:text>
+ <xsl:text>#define </xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text>_GetMessage(p, aMessage) ((p)->lpVtbl->GetMessage(p, aMessage))&#x0A;</xsl:text>
+ <xsl:text>#define </xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text>_get_Result(p, aResult) ((p)->lpVtbl->GetResult(p, aResult))&#x0A;</xsl:text>
+ <xsl:text>#define </xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text>_GetResult(p, aResult) ((p)->lpVtbl->GetResult(p, aResult))&#x0A;</xsl:text>
+ <xsl:text>#define </xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text>_get_Name(p, aName) ((p)->lpVtbl->GetName(p, aName))&#x0A;</xsl:text>
+ <xsl:text>#define </xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text>_GetName(p, aName) ((p)->lpVtbl->GetName(p, aName))&#x0A;</xsl:text>
+ <xsl:text>#define </xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text>_get_Filename(p, aFilename) ((p)->lpVtbl->GetFilename(p, aFilename))&#x0A;</xsl:text>
+ <xsl:text>#define </xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text>_GetFilename(p, aFilename) ((p)->lpVtbl->GetFilename(p, aFilename))&#x0A;</xsl:text>
+ <xsl:text>#define </xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text>_get_LineNumber(p, aLineNumber) ((p)->lpVtbl->GetLineNumber(p, aLineNumber))&#x0A;</xsl:text>
+ <xsl:text>#define </xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text>_GetLineNumber(p, aLineNumber) ((p)->lpVtbl->GetLineNumber(p, aLineNumber))&#x0A;</xsl:text>
+ <xsl:text>#define </xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text>_get_ColumnNumber(p, aColumnNumber) ((p)->lpVtbl->GetColumnNumber(p, aColumnNumber))&#x0A;</xsl:text>
+ <xsl:text>#define </xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text>_GetColumnNumber(p, aColumnNumber) ((p)->lpVtbl->GetColumnNumber(p, aColumnNumber))&#x0A;</xsl:text>
+ <xsl:text>#define </xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text>_get_Location(p, aLocation) ((p)->lpVtbl->GetLocation(p, aLocation))&#x0A;</xsl:text>
+ <xsl:text>#define </xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text>_GetLocation(p, aLocation) ((p)->lpVtbl->GetLocation(p, aLocation))&#x0A;</xsl:text>
+ <xsl:text>#define </xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text>_get_Inner(p, aInner) ((p)->lpVtbl->GetInner(p, aInner))&#x0A;</xsl:text>
+ <xsl:text>#define </xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text>_GetInner(p, aInner) ((p)->lpVtbl->GetInner(p, aInner))&#x0A;</xsl:text>
+ <xsl:text>#define </xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text>_get_Data(p, aData) ((p)->lpVtbl->GetData(p, aData))&#x0A;</xsl:text>
+ <xsl:text>#define </xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text>_GetData(p, aData) ((p)->lpVtbl->GetData(p, aData))&#x0A;</xsl:text>
+ <xsl:text>#define </xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text>_ToString(p, retval) ((p)->lpVtbl->ToString(p, retval))&#x0A;</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select="key('G_keyInterfacesByName', $extends)" mode="cobjmacro">
+ <xsl:with-param name="iface" select="$iface"/>
+ </xsl:apply-templates>
+ </xsl:otherwise>
+ </xsl:choose>
+ <!-- attributes (properties) -->
+ <xsl:apply-templates select="attribute | if/attribute" mode="cobjmacro">
+ <xsl:with-param name="iface" select="$iface"/>
+ </xsl:apply-templates>
+ <!-- methods -->
+ <xsl:apply-templates select="method | if/method" mode="cobjmacro">
+ <xsl:with-param name="iface" select="$iface"/>
+ </xsl:apply-templates>
+</xsl:template>
+
+
+<!--
+ * emit flat vtable, compatible with COM
+-->
+<xsl:template match="interface" mode="vtab_flat">
+ <xsl:param name="iface"/>
+
+ <xsl:variable name="name" select="@name"/>
+ <xsl:variable name="extends" select="@extends"/>
+ <xsl:choose>
+ <xsl:when test="$extends='$unknown'">
+ <xsl:text> nsresult (*QueryInterface)(</xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text> *pThis, const nsID *iid, void **resultp);&#x0A;</xsl:text>
+ <xsl:text> nsrefcnt (*AddRef)(</xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text> *pThis);&#x0A;</xsl:text>
+ <xsl:text> nsrefcnt (*Release)(</xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text> *pThis);&#x0A;</xsl:text>
+ </xsl:when>
+ <xsl:when test="$extends='$errorinfo'">
+ <xsl:text> nsresult (*QueryInterface)(</xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text> *pThis, const nsID *iid, void **resultp);&#x0A;</xsl:text>
+ <xsl:text> nsrefcnt (*AddRef)(</xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text> *pThis);&#x0A;</xsl:text>
+ <xsl:text> nsrefcnt (*Release)(</xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text> *pThis);&#x0A;</xsl:text>
+ <xsl:text> nsresult (*GetMessage)(</xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text> *pThis, PRUnichar * *aMessage);&#x0A;</xsl:text>
+ <xsl:text> nsresult (*GetResult)(</xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text> *pThis, nsresult *aResult);&#x0A;</xsl:text>
+ <xsl:text> nsresult (*GetName)(</xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text>*pThis, PRUnichar * *aName);&#x0A;</xsl:text>
+ <xsl:text> nsresult (*GetFilename)(</xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text> *pThis, PRUnichar * *aFilename);&#x0A;</xsl:text>
+ <xsl:text> nsresult (*GetLineNumber)(</xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text> *pThis, PRUint32 *aLineNumber);&#x0A;</xsl:text>
+ <xsl:text> nsresult (*GetColumnNumber)(</xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text> *pThis, PRUint32 *aColumnNumber);&#x0A;</xsl:text>
+ <xsl:text> nsresult (*GetLocation)(</xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text> *pThis, nsIStackFrame * *aLocation);&#x0A;</xsl:text>
+ <xsl:text> nsresult (*GetInner)(</xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text> *pThis, nsIException * *aInner);&#x0A;</xsl:text>
+ <xsl:text> nsresult (*GetData)(</xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text> *pThis, nsISupports * *aData);&#x0A;</xsl:text>
+ <xsl:text> nsresult (*ToString)(</xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text> *pThis, PRUnichar **_retval);&#x0A;</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select="key('G_keyInterfacesByName', $extends)" mode="vtab_flat">
+ <xsl:with-param name="iface" select="$iface"/>
+ </xsl:apply-templates>
+ </xsl:otherwise>
+ </xsl:choose>
+ <!-- attributes (properties) -->
+ <xsl:apply-templates select="attribute | if/attribute">
+ <xsl:with-param name="iface" select="$iface"/>
+ </xsl:apply-templates>
+ <xsl:variable name="reservedAttributes" select="@reservedAttributes"/>
+ <xsl:if test="$reservedAttributes > 0">
+ <!-- tricky way to do a "for" loop without recursion -->
+ <xsl:for-each select="(//*)[position() &lt;= $reservedAttributes]">
+ <xsl:text> nsresult (*GetInternalAndReservedAttribute</xsl:text>
+ <xsl:value-of select="concat(position(), $name)"/>
+ <xsl:text>)(</xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text> *pThis, PRUint32 *reserved);&#x0A;&#x0A;</xsl:text>
+ </xsl:for-each>
+ </xsl:if>
+ <!-- methods -->
+ <xsl:apply-templates select="method | if/method">
+ <xsl:with-param name="iface" select="$iface"/>
+ </xsl:apply-templates>
+ <xsl:variable name="reservedMethods" select="@reservedMethods"/>
+ <xsl:if test="$reservedMethods > 0">
+ <!-- tricky way to do a "for" loop without recursion -->
+ <xsl:for-each select="(//*)[position() &lt;= $reservedMethods]">
+ <xsl:text> nsresult (*InternalAndReservedMethod</xsl:text>
+ <xsl:value-of select="concat(position(), $name)"/>
+ <xsl:text>)(</xsl:text>
+ <xsl:value-of select="$iface"/>
+ <xsl:text> *pThis);&#x0A;&#x0A;</xsl:text>
+ </xsl:for-each>
+ </xsl:if>
+</xsl:template>
+
+
+<!--
+ * interfaces
+-->
+<xsl:template match="interface">
+ <xsl:if test="not(@internal='yes')">
+ <xsl:variable name="name" select="@name"/>
+ <xsl:text>/* Start of struct </xsl:text>
+ <xsl:value-of select="$name"/>
+ <xsl:text> declaration */&#x0A;</xsl:text>
+ <xsl:text>#define </xsl:text>
+ <xsl:call-template name="string-to-upper">
+ <xsl:with-param name="str" select="$name"/>
+ </xsl:call-template>
+ <xsl:value-of select="concat('_IID_STR &quot;',@uuid,'&quot;')"/>
+ <xsl:text>&#x0A;</xsl:text>
+ <xsl:text>#define </xsl:text>
+ <xsl:call-template name="string-to-upper">
+ <xsl:with-param name="str" select="$name"/>
+ </xsl:call-template>
+ <xsl:text>_IID { \&#x0A;</xsl:text>
+ <xsl:text> 0x</xsl:text><xsl:value-of select="substring(@uuid,1,8)"/>
+ <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,10,4)"/>
+ <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,15,4)"/>
+ <xsl:text>, \&#x0A; </xsl:text>
+ <xsl:text>{ 0x</xsl:text><xsl:value-of select="substring(@uuid,20,2)"/>
+ <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,22,2)"/>
+ <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,25,2)"/>
+ <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,27,2)"/>
+ <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,29,2)"/>
+ <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,31,2)"/>
+ <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,33,2)"/>
+ <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,35,2)"/>
+ <xsl:text> } \&#x0A;}&#x0A;</xsl:text>
+ <xsl:text>/* COM compatibility */&#x0A;</xsl:text>
+ <xsl:text>VBOX_EXTERN_CONST(nsIID, IID_</xsl:text>
+ <xsl:value-of select="$name"/>
+ <xsl:text>);&#x0A;</xsl:text>
+ <xsl:text>#ifndef VBOX_WITH_GLUE&#x0A;</xsl:text>
+ <xsl:text>struct </xsl:text>
+ <xsl:value-of select="$name"/>
+ <xsl:text>_vtbl&#x0A;{&#x0A;</xsl:text>
+ <xsl:text> </xsl:text>
+ <xsl:choose>
+ <xsl:when test="@extends='$unknown'">struct nsISupports_vtbl nsisupports;</xsl:when>
+ <xsl:when test="@extends='$errorinfo'">struct nsIException_vtbl nsiexception;</xsl:when>
+ <xsl:otherwise>
+ <xsl:text>struct </xsl:text>
+ <xsl:value-of select="@extends"/>
+ <xsl:text>_vtbl </xsl:text>
+ <xsl:call-template name="string-to-lower">
+ <xsl:with-param name="str" select="@extends"/>
+ </xsl:call-template>
+ <xsl:text>;</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text>&#x0A;&#x0A;</xsl:text>
+ <!-- attributes (properties) -->
+ <xsl:apply-templates select="attribute | if/attribute"/>
+ <xsl:variable name="reservedAttributes" select="@reservedAttributes"/>
+ <xsl:if test="$reservedAttributes > 0">
+ <!-- tricky way to do a "for" loop without recursion -->
+ <xsl:for-each select="(//*)[position() &lt;= $reservedAttributes]">
+ <xsl:text> nsresult (*GetInternalAndReservedAttribute</xsl:text>
+ <xsl:value-of select="concat(position(), $name)"/>
+ <xsl:text>)(</xsl:text>
+ <xsl:value-of select="$name"/>
+ <xsl:text> *pThis, PRUint32 *reserved);&#x0A;&#x0A;</xsl:text>
+ </xsl:for-each>
+ </xsl:if>
+ <!-- methods -->
+ <xsl:apply-templates select="method | if/method"/>
+ <xsl:variable name="reservedMethods" select="@reservedMethods"/>
+ <xsl:if test="$reservedMethods > 0">
+ <!-- tricky way to do a "for" loop without recursion -->
+ <xsl:for-each select="(//*)[position() &lt;= $reservedMethods]">
+ <xsl:text> nsresult (*InternalAndReservedMethod</xsl:text>
+ <xsl:value-of select="concat(position(), $name)"/>
+ <xsl:text>)(</xsl:text>
+ <xsl:value-of select="$name"/>
+ <xsl:text> *pThis);&#x0A;&#x0A;</xsl:text>
+ </xsl:for-each>
+ </xsl:if>
+ <!-- -->
+ <xsl:text>};&#x0A;</xsl:text>
+ <xsl:text>#else /* VBOX_WITH_GLUE */&#x0A;</xsl:text>
+ <xsl:text>struct </xsl:text>
+ <xsl:value-of select="$name"/>
+ <xsl:text>Vtbl&#x0A;{&#x0A;</xsl:text>
+ <xsl:apply-templates select="." mode="vtab_flat">
+ <xsl:with-param name="iface" select="$name"/>
+ </xsl:apply-templates>
+ <xsl:text>};&#x0A;</xsl:text>
+ <xsl:apply-templates select="." mode="cobjmacro">
+ <xsl:with-param name="iface" select="$name"/>
+ </xsl:apply-templates>
+ <!-- -->
+ <xsl:text>#endif /* VBOX_WITH_GLUE */&#x0A;</xsl:text>
+ <xsl:text>&#x0A;</xsl:text>
+ <xsl:text>interface </xsl:text>
+ <xsl:value-of select="$name"/>
+ <xsl:text>&#x0A;{&#x0A;</xsl:text>
+ <xsl:text>#ifndef VBOX_WITH_GLUE&#x0A;</xsl:text>
+ <xsl:text> struct </xsl:text>
+ <xsl:value-of select="$name"/>
+ <xsl:text>_vtbl *vtbl;&#x0A;</xsl:text>
+ <xsl:text>#else /* VBOX_WITH_GLUE */&#x0A;</xsl:text>
+ <xsl:text> CONST_VTBL struct </xsl:text>
+ <xsl:value-of select="$name"/>
+ <xsl:text>Vtbl *lpVtbl;&#x0A;</xsl:text>
+ <xsl:text>#endif /* VBOX_WITH_GLUE */&#x0A;</xsl:text>
+ <xsl:text>};&#x0A;</xsl:text>
+ <xsl:text>/* End of struct </xsl:text>
+ <xsl:value-of select="$name"/>
+ <xsl:text> declaration */&#x0A;&#x0A;</xsl:text>
+ <xsl:call-template name="xsltprocNewlineOutputHack"/>
+ </xsl:if>
+</xsl:template>
+
+
+<!--
+ * attributes
+-->
+<xsl:template match="attribute">
+ <xsl:param name="iface" select="ancestor::interface/@name"/>
+
+ <xsl:choose>
+ <!-- safearray pseudo attribute -->
+ <xsl:when test="@safearray='yes'">
+ <!-- getter -->
+ <xsl:text> nsresult (*Get</xsl:text>
+ <xsl:call-template name="capitalize">
+ <xsl:with-param name="str" select="@name"/>
+ </xsl:call-template>
+ <xsl:text>)(</xsl:text>
+ <xsl:value-of select="$iface" />
+ <xsl:text> *pThis, </xsl:text>
+ <!-- array size -->
+ <xsl:text>PRUint32 *</xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:text>Size, </xsl:text>
+ <!-- array pointer -->
+ <xsl:apply-templates select="@type" mode="forwarder"/>
+ <xsl:text> **</xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:text>);&#x0A;</xsl:text>
+ <!-- setter -->
+ <xsl:if test="not(@readonly='yes')">
+ <xsl:text> nsresult (*Set</xsl:text>
+ <xsl:call-template name="capitalize">
+ <xsl:with-param name="str" select="@name"/>
+ </xsl:call-template>
+ <xsl:text>)(</xsl:text>
+ <xsl:value-of select="$iface" />
+ <xsl:text> *pThis, </xsl:text>
+ <!-- array size -->
+ <xsl:text>PRUint32 </xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:text>Size, </xsl:text>
+ <!-- array pointer -->
+ <xsl:apply-templates select="@type" mode="forwarder"/>
+ <xsl:text> *</xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:text>);&#x0A;</xsl:text>
+ </xsl:if>
+ </xsl:when>
+ <!-- normal attribute -->
+ <xsl:otherwise>
+ <xsl:text> </xsl:text>
+ <xsl:if test="@readonly='yes'">
+ <xsl:text>nsresult (*Get</xsl:text>
+ <xsl:call-template name="capitalize">
+ <xsl:with-param name="str" select="@name"/>
+ </xsl:call-template>
+ <xsl:text>)(</xsl:text>
+ <xsl:value-of select="$iface" />
+ <xsl:text> *pThis, </xsl:text>
+ <xsl:apply-templates select="@type" mode="forwarder"/>
+ <xsl:text> *</xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:text>);&#x0A;</xsl:text>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="@readonly='yes'">
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>nsresult (*Get</xsl:text>
+ <xsl:call-template name="capitalize">
+ <xsl:with-param name="str" select="@name"/>
+ </xsl:call-template>
+ <xsl:text>)(</xsl:text>
+ <xsl:value-of select="$iface" />
+ <xsl:text> *pThis, </xsl:text>
+ <xsl:apply-templates select="@type" mode="forwarder"/>
+ <xsl:text> *</xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:text>);&#x0A; </xsl:text>
+ <xsl:text>nsresult (*Set</xsl:text>
+ <xsl:call-template name="capitalize">
+ <xsl:with-param name="str" select="@name"/>
+ </xsl:call-template>
+ <xsl:text>)(</xsl:text>
+ <xsl:value-of select="$iface" />
+ <xsl:text> *pThis, </xsl:text>
+ <xsl:apply-templates select="@type" mode="forwarder"/>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:text>);&#x0A;</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text>&#x0A;</xsl:text>
+</xsl:template>
+
+<xsl:template match="attribute" mode="cobjmacro">
+ <xsl:param name="iface"/>
+
+ <!-- getter (COM compatible) -->
+ <xsl:text>#define </xsl:text>
+ <xsl:value-of select="concat($iface, '_get_')"/>
+ <xsl:call-template name="capitalize">
+ <xsl:with-param name="str" select="@name"/>
+ </xsl:call-template>
+ <xsl:text>(p, a</xsl:text>
+ <xsl:call-template name="capitalize">
+ <xsl:with-param name="str" select="@name"/>
+ </xsl:call-template>
+ <xsl:text>) ((p)->lpVtbl->Get</xsl:text>
+ <xsl:call-template name="capitalize">
+ <xsl:with-param name="str" select="@name"/>
+ </xsl:call-template>
+ <xsl:text>(p, a</xsl:text>
+ <xsl:call-template name="capitalize">
+ <xsl:with-param name="str" select="@name"/>
+ </xsl:call-template>
+ <xsl:text>))&#x0A;</xsl:text>
+
+ <!-- getter (XPCOM compatible) -->
+ <xsl:text>#define </xsl:text>
+ <xsl:value-of select="concat($iface, '_Get')"/>
+ <xsl:call-template name="capitalize">
+ <xsl:with-param name="str" select="@name"/>
+ </xsl:call-template>
+ <xsl:text>(p, a</xsl:text>
+ <xsl:call-template name="capitalize">
+ <xsl:with-param name="str" select="@name"/>
+ </xsl:call-template>
+ <xsl:text>) ((p)->lpVtbl->Get</xsl:text>
+ <xsl:call-template name="capitalize">
+ <xsl:with-param name="str" select="@name"/>
+ </xsl:call-template>
+ <xsl:text>(p, a</xsl:text>
+ <xsl:call-template name="capitalize">
+ <xsl:with-param name="str" select="@name"/>
+ </xsl:call-template>
+ <xsl:text>))&#x0A;</xsl:text>
+
+ <xsl:if test="not(@readonly='yes')">
+ <!-- setter (COM compatible) -->
+ <xsl:text>#define </xsl:text>
+ <xsl:value-of select="concat($iface, '_put_')"/>
+ <xsl:call-template name="capitalize">
+ <xsl:with-param name="str" select="@name"/>
+ </xsl:call-template>
+ <xsl:text>(p, a</xsl:text>
+ <xsl:call-template name="capitalize">
+ <xsl:with-param name="str" select="@name"/>
+ </xsl:call-template>
+ <xsl:text>) ((p)->lpVtbl->Set</xsl:text>
+ <xsl:call-template name="capitalize">
+ <xsl:with-param name="str" select="@name"/>
+ </xsl:call-template>
+ <xsl:text>(p, a</xsl:text>
+ <xsl:call-template name="capitalize">
+ <xsl:with-param name="str" select="@name"/>
+ </xsl:call-template>
+ <xsl:text>))&#x0A;</xsl:text>
+
+ <!-- setter (XPCOM compatible) -->
+ <xsl:text>#define </xsl:text>
+ <xsl:value-of select="concat($iface, '_Set')"/>
+ <xsl:call-template name="capitalize">
+ <xsl:with-param name="str" select="@name"/>
+ </xsl:call-template>
+ <xsl:text>(p, a</xsl:text>
+ <xsl:call-template name="capitalize">
+ <xsl:with-param name="str" select="@name"/>
+ </xsl:call-template>
+ <xsl:text>) ((p)->lpVtbl->Set</xsl:text>
+ <xsl:call-template name="capitalize">
+ <xsl:with-param name="str" select="@name"/>
+ </xsl:call-template>
+ <xsl:text>(p, a</xsl:text>
+ <xsl:call-template name="capitalize">
+ <xsl:with-param name="str" select="@name"/>
+ </xsl:call-template>
+ <xsl:text>))&#x0A;</xsl:text>
+
+ </xsl:if>
+</xsl:template>
+
+<!--
+ * methods
+-->
+<xsl:template match="method">
+ <xsl:param name="iface" select="ancestor::interface/@name"/>
+
+ <xsl:if test="param/@mod='ptr'">
+ <!-- methods using native types must be non-scriptable
+ <xsl:text> [noscript]&#x0A;</xsl:text>-->
+ </xsl:if>
+ <xsl:text> nsresult (*</xsl:text>
+ <xsl:call-template name="capitalize">
+ <xsl:with-param name="str" select="@name"/>
+ </xsl:call-template>
+ <xsl:if test="param">
+ <xsl:text>)(&#x0A;</xsl:text>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="$iface" />
+ <xsl:text> *pThis,&#x0A;</xsl:text>
+ <xsl:for-each select="param [position() != last()]">
+ <xsl:text> </xsl:text>
+ <xsl:apply-templates select="."/>
+ <xsl:text>,&#x0A;</xsl:text>
+ </xsl:for-each>
+ <xsl:text> </xsl:text>
+ <xsl:apply-templates select="param [last()]"/>
+ <xsl:text>&#x0A; );&#x0A;</xsl:text>
+ </xsl:if>
+ <xsl:if test="not(param)">
+ <xsl:text>)(</xsl:text>
+ <xsl:value-of select="$iface" />
+ <xsl:text> *pThis );&#x0A;</xsl:text>
+ </xsl:if>
+ <xsl:text>&#x0A;</xsl:text>
+</xsl:template>
+
+<xsl:template match="method" mode="cobjmacro">
+ <xsl:param name="iface"/>
+
+ <xsl:text>#define </xsl:text>
+ <xsl:value-of select="concat($iface, '_')"/>
+ <xsl:call-template name="capitalize">
+ <xsl:with-param name="str" select="@name"/>
+ </xsl:call-template>
+ <xsl:text>(p</xsl:text>
+ <xsl:for-each select="param">
+ <xsl:text>, a</xsl:text>
+ <xsl:call-template name="capitalize">
+ <xsl:with-param name="str" select="@name"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ <xsl:text>) ((p)->lpVtbl-></xsl:text>
+ <xsl:call-template name="capitalize">
+ <xsl:with-param name="str" select="@name"/>
+ </xsl:call-template>
+ <xsl:text>(p</xsl:text>
+ <xsl:for-each select="param">
+ <xsl:text>, a</xsl:text>
+ <xsl:call-template name="capitalize">
+ <xsl:with-param name="str" select="@name"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ <xsl:text>))&#x0A;</xsl:text>
+</xsl:template>
+
+
+<!--
+ * modules
+-->
+<xsl:template match="module">
+ <xsl:apply-templates select="class"/>
+</xsl:template>
+
+
+<!--
+ * co-classes
+-->
+<xsl:template match="module/class">
+ <!-- class and contract id -->
+ <xsl:text>&#x0A;</xsl:text>
+ <xsl:text>#define NS_</xsl:text>
+ <xsl:call-template name="string-to-upper">
+ <xsl:with-param name="str" select="@name"/>
+ </xsl:call-template>
+ <xsl:text>_CID { \&#x0A;</xsl:text>
+ <xsl:text> 0x</xsl:text><xsl:value-of select="substring(@uuid,1,8)"/>
+ <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,10,4)"/>
+ <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,15,4)"/>
+ <xsl:text>, \&#x0A; </xsl:text>
+ <xsl:text>{ 0x</xsl:text><xsl:value-of select="substring(@uuid,20,2)"/>
+ <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,22,2)"/>
+ <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,25,2)"/>
+ <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,27,2)"/>
+ <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,29,2)"/>
+ <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,31,2)"/>
+ <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,33,2)"/>
+ <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,35,2)"/>
+ <xsl:text> } \&#x0A;}&#x0A;</xsl:text>
+ <xsl:text>#define NS_</xsl:text>
+ <xsl:call-template name="string-to-upper">
+ <xsl:with-param name="str" select="@name"/>
+ </xsl:call-template>
+ <!-- Contract ID -->
+ <xsl:text>_CONTRACTID &quot;@</xsl:text>
+ <xsl:value-of select="@namespace"/>
+ <xsl:text>/</xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:text>;1&quot;&#x0A;</xsl:text>
+ <!-- CLSID_xxx declarations for XPCOM, for compatibility with Win32 -->
+ <xsl:text>/* COM compatibility */&#x0A;</xsl:text>
+ <xsl:text>VBOX_EXTERN_CONST(nsCID, CLSID_</xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:text>);&#x0A;</xsl:text>
+ <xsl:text>&#x0A;&#x0A;</xsl:text>
+</xsl:template>
+
+
+<!--
+ * enums
+-->
+<xsl:template match="enum">
+ <xsl:text>/* Start of enum </xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:text> declaration */&#x0A;</xsl:text>
+ <xsl:text>#define </xsl:text>
+ <xsl:call-template name="string-to-upper">
+ <xsl:with-param name="str" select="@name"/>
+ </xsl:call-template>
+ <xsl:value-of select="concat('_IID_STR &quot;',@uuid,'&quot;')"/>
+ <xsl:text>&#x0A;</xsl:text>
+ <xsl:text>#define </xsl:text>
+ <xsl:call-template name="string-to-upper">
+ <xsl:with-param name="str" select="@name"/>
+ </xsl:call-template>
+ <xsl:text>_IID { \&#x0A;</xsl:text>
+ <xsl:text> 0x</xsl:text><xsl:value-of select="substring(@uuid,1,8)"/>
+ <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,10,4)"/>
+ <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,15,4)"/>
+ <xsl:text>, \&#x0A; </xsl:text>
+ <xsl:text>{ 0x</xsl:text><xsl:value-of select="substring(@uuid,20,2)"/>
+ <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,22,2)"/>
+ <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,25,2)"/>
+ <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,27,2)"/>
+ <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,29,2)"/>
+ <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,31,2)"/>
+ <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,33,2)"/>
+ <xsl:text>, 0x</xsl:text><xsl:value-of select="substring(@uuid,35,2)"/>
+ <xsl:text> } \&#x0A;}&#x0A;</xsl:text>
+ <xsl:text>typedef enum </xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:text>&#x0A;{&#x0A;</xsl:text>
+ <xsl:variable name="this" select="."/>
+ <xsl:for-each select="const">
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="$this/@name"/>
+ <xsl:text>_</xsl:text>
+ <xsl:value-of select="@name"/> = <xsl:value-of select="@value"/>
+ <xsl:if test="position() != last()">
+ <xsl:text>,</xsl:text>
+ </xsl:if>
+ <xsl:text>&#x0A;</xsl:text>
+ </xsl:for-each>
+ <xsl:text>} </xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:text>;&#x0A;</xsl:text>
+ <xsl:text>/* End of enum </xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:text> declaration */
+#define </xsl:text>
+ <xsl:value-of select="concat(@name, '_T PRUint32&#x0A;&#x0A;&#x0A;')"/>
+</xsl:template>
+
+
+<!--
+ * method parameters
+-->
+<xsl:template match="method/param">
+ <xsl:choose>
+ <!-- safearray parameters -->
+ <xsl:when test="@safearray='yes'">
+ <!-- array size -->
+ <xsl:choose>
+ <xsl:when test="@dir='in'">
+ <xsl:text>PRUint32 </xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:text>Size,&#x0A;</xsl:text>
+ </xsl:when>
+ <xsl:when test="@dir='out'">
+ <xsl:text>PRUint32 *</xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:text>Size,&#x0A;</xsl:text>
+ </xsl:when>
+ <xsl:when test="@dir='return'">
+ <xsl:text>PRUint32 *</xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:text>Size,&#x0A;</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>PRUint32 </xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:text>Size,&#x0A;</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ <!-- array pointer -->
+ <xsl:text> </xsl:text>
+ <xsl:choose>
+ <xsl:when test="@dir='in'">
+ <xsl:apply-templates select="@type" mode="forwarder"/>
+ <xsl:text>*</xsl:text>
+ </xsl:when>
+ <xsl:when test="@dir='out'">
+ <xsl:apply-templates select="@type" mode="forwarder"/>
+ <xsl:text>**</xsl:text>
+ </xsl:when>
+ <xsl:when test="@dir='return'">
+ <xsl:apply-templates select="@type" mode="forwarder"/>
+ <xsl:text>**</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select="@type" mode="forwarder"/>
+ <xsl:text>*</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="@name"/>
+ </xsl:when>
+ <!-- normal and array parameters -->
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="@dir='in'">
+ <xsl:apply-templates select="@type" mode="forwarder"/>
+ <xsl:text></xsl:text>
+ </xsl:when>
+ <xsl:when test="@dir='out'">
+ <xsl:apply-templates select="@type" mode="forwarder"/>
+ <xsl:text> *</xsl:text>
+ </xsl:when>
+ <xsl:when test="@dir='return'">
+ <xsl:apply-templates select="@type" mode="forwarder"/>
+ <xsl:text> *</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select="@type" mode="forwarder"/>
+ <xsl:text></xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="@name"/>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<xsl:template match="method/param" mode="forwarder">
+ <xsl:if test="@safearray='yes'">
+ <xsl:text>PRUint32</xsl:text>
+ <xsl:if test="@dir='out' or @dir='return'">
+ <xsl:text> *</xsl:text>
+ </xsl:if>
+ <xsl:text> a</xsl:text>
+ <xsl:call-template name="capitalize">
+ <xsl:with-param name="str" select="@name"/>
+ </xsl:call-template>
+ <xsl:text>Size, </xsl:text>
+ </xsl:if>
+ <xsl:apply-templates select="@type" mode="forwarder"/>
+ <xsl:if test="@dir='out' or @dir='return'">
+ <xsl:text> *</xsl:text>
+ </xsl:if>
+ <xsl:if test="@safearray='yes'">
+ <xsl:text> *</xsl:text>
+ </xsl:if>
+ <xsl:text> a</xsl:text>
+ <xsl:call-template name="capitalize">
+ <xsl:with-param name="str" select="@name"/>
+ </xsl:call-template>
+</xsl:template>
+
+
+<!--
+ * attribute/parameter type conversion
+-->
+<xsl:template match="attribute/@type | param/@type">
+ <xsl:variable name="self_target" select="current()/ancestor::if/@target"/>
+
+ <xsl:choose>
+ <!-- modifiers -->
+ <xsl:when test="name(current())='type' and ../@mod">
+ <xsl:choose>
+ <xsl:when test="../@mod='ptr'">
+ <xsl:choose>
+ <!-- standard types -->
+ <!--xsl:when test=".='result'">??</xsl:when-->
+ <xsl:when test=".='boolean'">booleanPtr</xsl:when>
+ <xsl:when test=".='octet'">octetPtr</xsl:when>
+ <xsl:when test=".='short'">shortPtr</xsl:when>
+ <xsl:when test=".='unsigned short'">ushortPtr</xsl:when>
+ <xsl:when test=".='long'">longPtr</xsl:when>
+ <xsl:when test=".='long long'">llongPtr</xsl:when>
+ <xsl:when test=".='unsigned long'">ulongPtr</xsl:when>
+ <xsl:when test=".='unsigned long long'">ullongPtr</xsl:when>
+ <xsl:otherwise>
+ <xsl:message terminate="yes">
+ <xsl:value-of select="concat(../../../@name,'::',../../@name,'::',../@name,': ')"/>
+ <xsl:text>attribute 'mod=</xsl:text>
+ <xsl:value-of select="concat('&quot;',../@mod,'&quot;')"/>
+ <xsl:text>' cannot be used with type </xsl:text>
+ <xsl:value-of select="concat('&quot;',current(),'&quot;!')"/>
+ </xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="../@mod='string'">
+ <xsl:choose>
+ <!-- standard types -->
+ <!--xsl:when test=".='result'">??</xsl:when-->
+ <xsl:when test=".='uuid'">wstring</xsl:when>
+ <xsl:otherwise>
+ <xsl:message terminate="yes">
+ <xsl:value-of select="concat(../../../@name,'::',../../@name,'::',../@name,': ')"/>
+ <xsl:text>attribute 'mod=</xsl:text>
+ <xsl:value-of select="concat('&quot;',../@mod,'&quot;')"/>
+ <xsl:text>' cannot be used with type </xsl:text>
+ <xsl:value-of select="concat('&quot;',current(),'&quot;!')"/>
+ </xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message terminate="yes">
+ <xsl:value-of select="concat(../../../@name,'::',../../@name,'::',../@name,': ')"/>
+ <xsl:value-of select="concat('value &quot;',../@mod,'&quot; ')"/>
+ <xsl:text>of attribute 'mod' is invalid!</xsl:text>
+ </xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <!-- no modifiers -->
+ <xsl:otherwise>
+ <xsl:choose>
+ <!-- standard types -->
+ <xsl:when test=".='result'">nsresult</xsl:when>
+ <xsl:when test=".='boolean'">boolean</xsl:when>
+ <xsl:when test=".='octet'">octet</xsl:when>
+ <xsl:when test=".='short'">short</xsl:when>
+ <xsl:when test=".='unsigned short'">unsigned short</xsl:when>
+ <xsl:when test=".='long'">long</xsl:when>
+ <xsl:when test=".='long long'">long long</xsl:when>
+ <xsl:when test=".='unsigned long'">unsigned long</xsl:when>
+ <xsl:when test=".='unsigned long long'">unsigned long long</xsl:when>
+ <xsl:when test=".='char'">char</xsl:when>
+ <xsl:when test=".='wchar'">wchar</xsl:when>
+ <xsl:when test=".='string'">string</xsl:when>
+ <xsl:when test=".='wstring'">wstring</xsl:when>
+ <!-- UUID type -->
+ <xsl:when test=".='uuid'">
+ <xsl:choose>
+ <xsl:when test="name(..)='attribute'">
+ <xsl:choose>
+ <xsl:when test="../@readonly='yes'">
+ <xsl:text>nsIDPtr</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message terminate="yes">
+ <xsl:value-of select="../@name"/>
+ <xsl:text>: Non-readonly uuid attributes are not supported!</xsl:text>
+ </xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="name(..)='param'">
+ <xsl:choose>
+ <xsl:when test="../@dir='in' and not(../@safearray='yes')">
+ <xsl:text>nsIDRef</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>nsIDPtr</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:when>
+ <!-- system interface types -->
+ <xsl:when test=".='$unknown'">nsISupports</xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <!-- enum types -->
+ <xsl:when test="
+ (ancestor::library/application/enum[@name=current()]) or
+ (ancestor::library/application/if[@target=$self_target]/enum[@name=current()])
+ ">
+ <xsl:text>PRUint32</xsl:text>
+ </xsl:when>
+ <!-- custom interface types -->
+ <xsl:when test="
+ (ancestor::library/application/interface[@name=current()]) or
+ (ancestor::library/application/if[@target=$self_target]/interface[@name=current()])
+ ">
+ <xsl:value-of select="."/>
+ </xsl:when>
+ <!-- other types -->
+ <xsl:otherwise>
+ <xsl:message terminate="yes">
+ <xsl:text>Unknown parameter type: </xsl:text>
+ <xsl:value-of select="."/>
+ </xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<xsl:template match="attribute/@type | param/@type" mode="forwarder">
+
+ <xsl:variable name="self_target" select="current()/ancestor::if/@target"/>
+
+ <xsl:choose>
+ <!-- modifiers -->
+ <xsl:when test="name(current())='type' and ../@mod">
+ <xsl:choose>
+ <xsl:when test="../@mod='ptr'">
+ <xsl:choose>
+ <!-- standard types -->
+ <!--xsl:when test=".='result'">??</xsl:when-->
+ <xsl:when test=".='boolean'">PRBool *</xsl:when>
+ <xsl:when test=".='octet'">PRUint8 *</xsl:when>
+ <xsl:when test=".='short'">PRInt16 *</xsl:when>
+ <xsl:when test=".='unsigned short'">PRUint16 *</xsl:when>
+ <xsl:when test=".='long'">PRInt32 *</xsl:when>
+ <xsl:when test=".='long long'">PRInt64 *</xsl:when>
+ <xsl:when test=".='unsigned long'">PRUint32 *</xsl:when>
+ <xsl:when test=".='unsigned long long'">PRUint64 *</xsl:when>
+ <xsl:otherwise>
+ <xsl:message terminate="yes">
+ <xsl:value-of select="concat(../../../@name,'::',../../@name,'::',../@name,': ')"/>
+ <xsl:text>attribute 'mod=</xsl:text>
+ <xsl:value-of select="concat('&quot;',../@mod,'&quot;')"/>
+ <xsl:text>' cannot be used with type </xsl:text>
+ <xsl:value-of select="concat('&quot;',current(),'&quot;!')"/>
+ </xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="../@mod='string'">
+ <xsl:choose>
+ <!-- standard types -->
+ <!--xsl:when test=".='result'">??</xsl:when-->
+ <xsl:when test=".='uuid'">PRUnichar *</xsl:when>
+ <xsl:otherwise>
+ <xsl:message terminate="yes">
+ <xsl:value-of select="concat(../../../@name,'::',../../@name,'::',../@name,': ')"/>
+ <xsl:text>attribute 'mod=</xsl:text>
+ <xsl:value-of select="concat('&quot;',../@mod,'&quot;')"/>
+ <xsl:text>' cannot be used with type </xsl:text>
+ <xsl:value-of select="concat('&quot;',current(),'&quot;!')"/>
+ </xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:when>
+ <!-- no modifiers -->
+ <xsl:otherwise>
+ <xsl:choose>
+ <!-- standard types -->
+ <xsl:when test=".='result'">nsresult</xsl:when>
+ <xsl:when test=".='boolean'">PRBool</xsl:when>
+ <xsl:when test=".='octet'">PRUint8</xsl:when>
+ <xsl:when test=".='short'">PRInt16</xsl:when>
+ <xsl:when test=".='unsigned short'">PRUint16</xsl:when>
+ <xsl:when test=".='long'">PRInt32</xsl:when>
+ <xsl:when test=".='long long'">PRInt64</xsl:when>
+ <xsl:when test=".='unsigned long'">PRUint32</xsl:when>
+ <xsl:when test=".='unsigned long long'">PRUint64</xsl:when>
+ <xsl:when test=".='char'">char</xsl:when>
+ <xsl:when test=".='wchar'">PRUnichar</xsl:when>
+ <!-- string types -->
+ <xsl:when test=".='string'">char *</xsl:when>
+ <xsl:when test=".='wstring'">PRUnichar *</xsl:when>
+ <!-- UUID type -->
+ <xsl:when test=".='uuid'">
+ <xsl:choose>
+ <xsl:when test="name(..)='attribute'">
+ <xsl:choose>
+ <xsl:when test="../@readonly='yes'">
+ <xsl:text>nsID *</xsl:text>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="name(..)='param'">
+ <xsl:choose>
+ <xsl:when test="../@dir='in' and not(../@safearray='yes')">
+ <xsl:text>const nsID *</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>nsID *</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:when>
+ <!-- system interface types -->
+ <xsl:when test=".='$unknown'">nsISupports *</xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <!-- enum types -->
+ <xsl:when test="
+ (ancestor::library/application/enum[@name=current()]) or
+ (ancestor::library/application/if[@target=$self_target]/enum[@name=current()])
+ ">
+ <xsl:text>PRUint32</xsl:text>
+ </xsl:when>
+ <!-- custom interface types -->
+ <xsl:when test="
+ (ancestor::library/application/interface[@name=current()]) or
+ (ancestor::library/application/if[@target=$self_target]/interface[@name=current()])
+ ">
+ <xsl:value-of select="."/>
+ <xsl:text> *</xsl:text>
+ </xsl:when>
+ <!-- other types -->
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+
+<xsl:template match="application[@uuid='ec0e78e8-fa43-43e8-ac0a-02c784c4a4fa']//module/class" />
+
+<xsl:template match="application[@uuid='ec0e78e8-fa43-43e8-ac0a-02c784c4a4fa']/if//interface
+| application[@uuid='ec0e78e8-fa43-43e8-ac0a-02c784c4a4fa']//interface" />
+
+<xsl:template match="application[@uuid='ec0e78e8-fa43-43e8-ac0a-02c784c4a4fa']//interface" mode="forward" />
+
+
+</xsl:stylesheet>
diff --git a/src/VBox/Main/cbinding/makefile.tstCAPIGlue b/src/VBox/Main/cbinding/makefile.tstCAPIGlue
new file mode 100644
index 00000000..53975964
--- /dev/null
+++ b/src/VBox/Main/cbinding/makefile.tstCAPIGlue
@@ -0,0 +1,63 @@
+# $Id: makefile.tstCAPIGlue $
+## @file makefile.tstCAPIGlue
+# Makefile for sample program illustrating use of C binding for COM/XPCOM.
+#
+
+#
+# Copyright (C) 2009-2023 Oracle and/or its affiliates.
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+
+PATH_SDK = ../../..
+CAPI_INC = -I$(PATH_SDK)/bindings/c/include
+ifdef ProgramFiles
+PLATFORM_INC = -I$(PATH_SDK)/bindings/mscom/include
+PLATFORM_LIB = $(PATH_SDK)/bindings/mscom/lib
+else
+PLATFORM_INC = -I$(PATH_SDK)/bindings/xpcom/include
+PLATFORM_LIB = $(PATH_SDK)/bindings/xpcom/lib
+endif
+GLUE_DIR = $(PATH_SDK)/bindings/c/glue
+GLUE_INC = -I$(GLUE_DIR)
+
+CC = gcc
+CFLAGS = -g -Wall
+
+.PHONY: all
+all: tstCAPIGlue
+
+.PHONY: clean
+clean:
+ rm -f tstCAPIGlue.o VBoxCAPIGlue.o VirtualBox_i.o tstCAPIGlue
+
+tstCAPIGlue: tstCAPIGlue.o VBoxCAPIGlue.o VirtualBox_i.o
+ $(CC) -o $@ $^ -ldl -lpthread
+
+tstCAPIGlue.o: tstCAPIGlue.c
+ $(CC) $(CFLAGS) $(CAPI_INC) $(PLATFORM_INC) $(GLUE_INC) -o $@ -c $<
+
+VBoxCAPIGlue.o: $(GLUE_DIR)/VBoxCAPIGlue.c
+ $(CC) $(CFLAGS) $(CAPI_INC) $(PLATFORM_INC) $(GLUE_INC) -o $@ -c $<
+
+VirtualBox_i.o: $(PLATFORM_LIB)/VirtualBox_i.c
+ $(CC) $(CFLAGS) $(CAPI_INC) $(PLATFORM_INC) $(GLUE_INC) -o $@ -c $<
diff --git a/src/VBox/Main/cbinding/tstCAPIGlue.c b/src/VBox/Main/cbinding/tstCAPIGlue.c
new file mode 100644
index 00000000..d78a8085
--- /dev/null
+++ b/src/VBox/Main/cbinding/tstCAPIGlue.c
@@ -0,0 +1,1145 @@
+/* $Id: tstCAPIGlue.c $ */
+/** @file tstCAPIGlue.c
+ * Demonstrator program to illustrate use of C bindings of Main API.
+ *
+ * It has sample code showing how to retrieve all available error information,
+ * and how to handle active (event delivery through callbacks) or passive
+ * (event delivery through a polling mechanism) event listeners.
+ */
+
+/*
+ * Copyright (C) 2009-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+
+/** @todo
+ * Our appologies for the 256+ missing return code checks in this sample file.
+ *
+ * We strongly recomment users of the VBoxCAPI to check all return codes!
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#include "VBoxCAPIGlue.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#ifndef WIN32
+# include <signal.h>
+# include <unistd.h>
+# include <sys/poll.h>
+#endif
+#ifdef IPRT_INCLUDED_cdefs_h
+# error "not supposed to involve any IPRT or VBox headers here."
+#endif
+
+/**
+ * Select between active event listener (defined) and passive event listener
+ * (undefined). The active event listener case needs much more code, and
+ * additionally requires a lot more platform dependent code.
+ */
+#undef USE_ACTIVE_EVENT_LISTENER
+
+
+/*********************************************************************************************************************************
+* Global Variables *
+*********************************************************************************************************************************/
+/** Set by Ctrl+C handler. */
+static volatile int g_fStop = 0;
+
+#ifdef USE_ACTIVE_EVENT_LISTENER
+# ifdef WIN32
+/** The COM type information for IEventListener, for implementing IDispatch. */
+static ITypeInfo *g_pTInfoIEventListener = NULL;
+# endif /* WIN32 */
+#endif /* USE_ACTIVE_EVENT_LISTENER */
+
+static const char *GetStateName(MachineState_T machineState)
+{
+ switch (machineState)
+ {
+ case MachineState_Null: return "<null>";
+ case MachineState_PoweredOff: return "PoweredOff";
+ case MachineState_Saved: return "Saved";
+ case MachineState_Teleported: return "Teleported";
+ case MachineState_Aborted: return "Aborted";
+ case MachineState_AbortedSaved: return "Aborted-Saved";
+ case MachineState_Running: return "Running";
+ case MachineState_Paused: return "Paused";
+ case MachineState_Stuck: return "Stuck";
+ case MachineState_Teleporting: return "Teleporting";
+ case MachineState_LiveSnapshotting: return "LiveSnapshotting";
+ case MachineState_Starting: return "Starting";
+ case MachineState_Stopping: return "Stopping";
+ case MachineState_Saving: return "Saving";
+ case MachineState_Restoring: return "Restoring";
+ case MachineState_TeleportingPausedVM: return "TeleportingPausedVM";
+ case MachineState_TeleportingIn: return "TeleportingIn";
+ case MachineState_DeletingSnapshotOnline: return "DeletingSnapshotOnline";
+ case MachineState_DeletingSnapshotPaused: return "DeletingSnapshotPaused";
+ case MachineState_RestoringSnapshot: return "RestoringSnapshot";
+ case MachineState_DeletingSnapshot: return "DeletingSnapshot";
+ case MachineState_SettingUp: return "SettingUp";
+ default: return "no idea";
+ }
+}
+
+/**
+ * Ctrl+C handler, terminate event listener.
+ *
+ * Remember that most function calls are not allowed in this context (including
+ * printf!), so make sure that this does as little as possible.
+ *
+ * @param iInfo Platform dependent detail info (ignored).
+ */
+#ifdef WIN32
+static BOOL VBOX_WINAPI ctrlCHandler(DWORD iInfo)
+{
+ (void)iInfo;
+ g_fStop = 1;
+ return TRUE;
+}
+#else
+static void ctrlCHandler(int iInfo)
+{
+ (void)iInfo;
+ g_fStop = 1;
+}
+#endif
+
+/**
+ * Sample event processing function, dumping some event information.
+ * Shared between active and passive event demo, to highlight that this part
+ * is identical between the two.
+ */
+static HRESULT EventListenerDemoProcessEvent(IEvent *event)
+{
+ VBoxEventType_T evType;
+ HRESULT hrc;
+
+ if (!event)
+ {
+ printf("event null\n");
+ return S_OK;
+ }
+
+ evType = VBoxEventType_Invalid;
+ hrc = IEvent_get_Type(event, &evType);
+ if (FAILED(hrc))
+ {
+ printf("cannot get event type, hrc=%#x\n", (unsigned)hrc);
+ return S_OK;
+ }
+
+ switch (evType)
+ {
+ case VBoxEventType_OnMousePointerShapeChanged:
+ printf("OnMousePointerShapeChanged\n");
+ break;
+
+ case VBoxEventType_OnMouseCapabilityChanged:
+ printf("OnMouseCapabilityChanged\n");
+ break;
+
+ case VBoxEventType_OnKeyboardLedsChanged:
+ printf("OnMouseCapabilityChanged\n");
+ break;
+
+ case VBoxEventType_OnStateChanged:
+ {
+ IStateChangedEvent *ev = NULL;
+ enum MachineState state;
+ hrc = IEvent_QueryInterface(event, &IID_IStateChangedEvent, (void **)&ev);
+ if (FAILED(hrc))
+ {
+ printf("cannot get StateChangedEvent interface, hrc=%#x\n", (unsigned)hrc);
+ return S_OK;
+ }
+ if (!ev)
+ {
+ printf("StateChangedEvent reference null\n");
+ return S_OK;
+ }
+ hrc = IStateChangedEvent_get_State(ev, &state);
+ if (FAILED(hrc))
+ printf("warning: cannot get state, hrc=%#x\n", (unsigned)hrc);
+ IStateChangedEvent_Release(ev);
+ printf("OnStateChanged: %s\n", GetStateName(state));
+
+ fflush(stdout);
+ if ( state == MachineState_PoweredOff
+ || state == MachineState_Saved
+ || state == MachineState_Teleported
+ || state == MachineState_Aborted
+ || state == MachineState_AbortedSaved
+ )
+ g_fStop = 1;
+ break;
+ }
+
+ case VBoxEventType_OnAdditionsStateChanged:
+ printf("OnAdditionsStateChanged\n");
+ break;
+
+ case VBoxEventType_OnNetworkAdapterChanged:
+ printf("OnNetworkAdapterChanged\n");
+ break;
+
+ case VBoxEventType_OnSerialPortChanged:
+ printf("OnSerialPortChanged\n");
+ break;
+
+ case VBoxEventType_OnParallelPortChanged:
+ printf("OnParallelPortChanged\n");
+ break;
+
+ case VBoxEventType_OnStorageControllerChanged:
+ printf("OnStorageControllerChanged\n");
+ break;
+
+ case VBoxEventType_OnMediumChanged:
+ printf("OnMediumChanged\n");
+ break;
+
+ case VBoxEventType_OnVRDEServerChanged:
+ printf("OnVRDEServerChanged\n");
+ break;
+
+ case VBoxEventType_OnUSBControllerChanged:
+ printf("OnUSBControllerChanged\n");
+ break;
+
+ case VBoxEventType_OnUSBDeviceStateChanged:
+ printf("OnUSBDeviceStateChanged\n");
+ break;
+
+ case VBoxEventType_OnSharedFolderChanged:
+ printf("OnSharedFolderChanged\n");
+ break;
+
+ case VBoxEventType_OnRuntimeError:
+ printf("OnRuntimeError\n");
+ break;
+
+ case VBoxEventType_OnCanShowWindow:
+ printf("OnCanShowWindow\n");
+ break;
+ case VBoxEventType_OnShowWindow:
+ printf("OnShowWindow\n");
+ break;
+
+ default:
+ printf("unknown event: %d\n", evType);
+ }
+
+ return S_OK;
+}
+
+#ifdef USE_ACTIVE_EVENT_LISTENER
+
+struct IEventListenerDemo;
+typedef struct IEventListenerDemo IEventListenerDemo;
+
+typedef struct IEventListenerDemoVtbl
+{
+ HRESULT (*QueryInterface)(IEventListenerDemo *pThis, REFIID riid, void **ppvObject);
+ ULONG (*AddRef)(IEventListenerDemo *pThis);
+ ULONG (*Release)(IEventListenerDemo *pThis);
+#ifdef WIN32
+ HRESULT (*GetTypeInfoCount)(IEventListenerDemo *pThis, UINT *pctinfo);
+ HRESULT (*GetTypeInfo)(IEventListenerDemo *pThis, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo);
+ HRESULT (*GetIDsOfNames)(IEventListenerDemo *pThis, REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId);
+ HRESULT (*Invoke)(IEventListenerDemo *pThis, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr);
+#endif
+ HRESULT (*HandleEvent)(IEventListenerDemo *pThis, IEvent *aEvent);
+} IEventListenerDemoVtbl;
+
+typedef struct IEventListenerDemo
+{
+ struct IEventListenerDemoVtbl *lpVtbl;
+
+ int cRef;
+
+#ifdef WIN32
+ /* Active event delivery needs a free threaded marshaler, as the default
+ * proxy marshaling cannot deal correctly with this case. */
+ IUnknown *pUnkMarshaler;
+#endif
+} IEventListenerDemo;
+
+/* Defines for easily calling IEventListenerDemo functions. */
+
+/* IUnknown functions. */
+#define IEventListenerDemo_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl->QueryInterface(This,riid,ppvObject) )
+
+#define IEventListenerDemo_AddRef(This) \
+ ( (This)->lpVtbl->AddRef(This) )
+
+#define IEventListenerDemo_Release(This) \
+ ( (This)->lpVtbl->Release(This) )
+
+#ifdef WIN32
+/* IDispatch functions. */
+#define IEventListenerDemo_GetTypeInfoCount(This,pctinfo) \
+ ( (This)->lpVtbl->GetTypeInfoCount(This,pctinfo) )
+
+#define IEventListenerDemo_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \
+ ( (This)->lpVtbl->GetTypeInfo(This,iTInfo,lcid,ppTInfo) )
+
+#define IEventListenerDemo_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \
+ ( (This)->lpVtbl->GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) )
+
+#define IEventListenerDemo_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \
+ ( (This)->lpVtbl->Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) )
+#endif
+
+/* IEventListener functions. */
+#define IEventListenerDemo_HandleEvent(This,aEvent) \
+ ( (This)->lpVtbl->HandleEvent(This,aEvent) )
+
+
+/**
+ * Event handler function, for active event processing.
+ */
+static HRESULT IEventListenerDemoImpl_HandleEvent(IEventListenerDemo *pThis, IEvent *event)
+{
+ return EventListenerDemoProcessEvent(event);
+}
+
+static HRESULT IEventListenerDemoImpl_QueryInterface(IEventListenerDemo *pThis, const IID *iid, void **resultp)
+{
+ /* match iid */
+ if ( !memcmp(iid, &IID_IEventListener, sizeof(IID))
+ || !memcmp(iid, &IID_IDispatch, sizeof(IID))
+ || !memcmp(iid, &IID_IUnknown, sizeof(IID)))
+ {
+ IEventListenerDemo_AddRef(pThis);
+ *resultp = pThis;
+ return S_OK;
+ }
+#ifdef WIN32
+ if (!memcmp(iid, &IID_IMarshal, sizeof(IID)))
+ return IUnknown_QueryInterface(pThis->pUnkMarshaler, iid, resultp);
+#endif
+
+ return E_NOINTERFACE;
+}
+
+static HRESULT IEventListenerDemoImpl_AddRef(IEventListenerDemo *pThis)
+{
+ return ++(pThis->cRef);
+}
+
+static HRESULT IEventListenerDemoImpl_Release(IEventListenerDemo *pThis)
+{
+ HRESULT c;
+
+ c = --(pThis->cRef);
+ if (!c)
+ free(pThis);
+ return c;
+}
+
+#ifdef WIN32
+static HRESULT IEventListenerDemoImpl_GetTypeInfoCount(IEventListenerDemo *pThis, UINT *pctinfo)
+{
+ if (!pctinfo)
+ return E_POINTER;
+ *pctinfo = 1;
+ return S_OK;
+}
+
+static HRESULT IEventListenerDemoImpl_GetTypeInfo(IEventListenerDemo *pThis, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
+{
+ if (!ppTInfo)
+ return E_POINTER;
+ ITypeInfo_AddRef(g_pTInfoIEventListener);
+ *ppTInfo = g_pTInfoIEventListener;
+ return S_OK;
+}
+
+static HRESULT IEventListenerDemoImpl_GetIDsOfNames(IEventListenerDemo *pThis, REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
+{
+ return ITypeInfo_GetIDsOfNames(g_pTInfoIEventListener, rgszNames, cNames, rgDispId);
+}
+
+static HRESULT IEventListenerDemoImpl_Invoke(IEventListenerDemo *pThis, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
+{
+ return ITypeInfo_Invoke(g_pTInfoIEventListener, (IDispatch *)pThis, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
+}
+
+static HRESULT LoadTypeInfo(REFIID riid, ITypeInfo **pTInfo)
+{
+ HRESULT hrc;
+ ITypeLib *pTypeLib;
+ hrc = LoadRegTypeLib(&LIBID_VirtualBox, 1 /* major */, 0 /* minor */, 0 /* lcid */, &pTypeLib);
+ if (FAILED(hrc))
+ return hrc;
+ hrc = ITypeLib_GetTypeInfoOfGuid(pTypeLib, riid, pTInfo);
+
+ /* No longer need access to the type lib, release it. */
+ ITypeLib_Release(pTypeLib);
+
+ return hrc;
+}
+#endif
+
+#ifdef __GNUC__
+typedef struct IEventListenerDemoVtblInt
+{
+ ptrdiff_t offset_to_top;
+ void *typeinfo;
+ IEventListenerDemoVtbl lpVtbl;
+} IEventListenerDemoVtblInt;
+
+static IEventListenerDemoVtblInt g_IEventListenerDemoVtblInt =
+{
+ 0, /* offset_to_top */
+ NULL, /* typeinfo, not vital */
+ {
+ IEventListenerDemoImpl_QueryInterface,
+ IEventListenerDemoImpl_AddRef,
+ IEventListenerDemoImpl_Release,
+#ifdef WIN32
+ IEventListenerDemoImpl_GetTypeInfoCount,
+ IEventListenerDemoImpl_GetTypeInfo,
+ IEventListenerDemoImpl_GetIDsOfNames,
+ IEventListenerDemoImpl_Invoke,
+#endif
+ IEventListenerDemoImpl_HandleEvent
+ }
+};
+#elif defined(_MSC_VER)
+typedef struct IEventListenerDemoVtblInt
+{
+ IEventListenerDemoVtbl lpVtbl;
+} IEventListenerDemoVtblInt;
+
+static IEventListenerDemoVtblInt g_IEventListenerDemoVtblInt =
+{
+ {
+ IEventListenerDemoImpl_QueryInterface,
+ IEventListenerDemoImpl_AddRef,
+ IEventListenerDemoImpl_Release,
+#ifdef WIN32
+ IEventListenerDemoImpl_GetTypeInfoCount,
+ IEventListenerDemoImpl_GetTypeInfo,
+ IEventListenerDemoImpl_GetIDsOfNames,
+ IEventListenerDemoImpl_Invoke,
+#endif
+ IEventListenerDemoImpl_HandleEvent
+ }
+};
+#else
+# error Port me!
+#endif
+
+/**
+ * Register active event listener for the selected VM.
+ *
+ * @param virtualBox ptr to IVirtualBox object
+ * @param session ptr to ISession object
+ */
+static void registerActiveEventListener(IVirtualBox *virtualBox, ISession *session)
+{
+ IConsole *console = NULL;
+ HRESULT hrc;
+
+ hrc = ISession_get_Console(session, &console);
+ if (SUCCEEDED(hrc) && console)
+ {
+ IEventSource *es = NULL;
+ hrc = IConsole_get_EventSource(console, &es);
+ if (SUCCEEDED(hrc) && es)
+ {
+ static const ULONG s_auInterestingEvents[] =
+ {
+ VBoxEventType_OnMousePointerShapeChanged,
+ VBoxEventType_OnMouseCapabilityChanged,
+ VBoxEventType_OnKeyboardLedsChanged,
+ VBoxEventType_OnStateChanged,
+ VBoxEventType_OnAdditionsStateChanged,
+ VBoxEventType_OnNetworkAdapterChanged,
+ VBoxEventType_OnSerialPortChanged,
+ VBoxEventType_OnParallelPortChanged,
+ VBoxEventType_OnStorageControllerChanged,
+ VBoxEventType_OnMediumChanged,
+ VBoxEventType_OnVRDEServerChanged,
+ VBoxEventType_OnUSBControllerChanged,
+ VBoxEventType_OnUSBDeviceStateChanged,
+ VBoxEventType_OnSharedFolderChanged,
+ VBoxEventType_OnRuntimeError,
+ VBoxEventType_OnCanShowWindow,
+ VBoxEventType_OnShowWindow
+ };
+ SAFEARRAY *interestingEventsSA = NULL;
+ IEventListenerDemo *consoleListener = NULL;
+
+ /* The VirtualBox API expects enum values as VT_I4, which in the
+ * future can be hopefully relaxed. */
+ interestingEventsSA = g_pVBoxFuncs->pfnSafeArrayCreateVector(VT_I4, 0,
+ sizeof(s_auInterestingEvents)
+ / sizeof(s_auInterestingEvents[0]));
+ g_pVBoxFuncs->pfnSafeArrayCopyInParamHelper(interestingEventsSA, &s_auInterestingEvents,
+ sizeof(s_auInterestingEvents));
+
+ consoleListener = calloc(1, sizeof(IEventListenerDemo));
+ if (consoleListener)
+ {
+ consoleListener->lpVtbl = &(g_IEventListenerDemoVtblInt.lpVtbl);
+#ifdef WIN32
+ CoCreateFreeThreadedMarshaler((IUnknown *)consoleListener, &consoleListener->pUnkMarshaler);
+#endif
+ IEventListenerDemo_AddRef(consoleListener);
+
+ hrc = IEventSource_RegisterListener(es, (IEventListener *)consoleListener,
+ ComSafeArrayAsInParam(interestingEventsSA),
+ 1 /* active */);
+ if (SUCCEEDED(hrc))
+ {
+ /* Just wait here for events, no easy way to do this better
+ * as there's not much to do after this completes. */
+ printf("Entering event loop, PowerOff the machine to exit or press Ctrl-C to terminate\n");
+ fflush(stdout);
+#ifdef WIN32
+ SetConsoleCtrlHandler(ctrlCHandler, TRUE);
+#else
+ signal(SIGINT, (void (*)(int))ctrlCHandler);
+#endif
+
+ while (!g_fStop)
+ g_pVBoxFuncs->pfnProcessEventQueue(250);
+
+#ifdef WIN32
+ SetConsoleCtrlHandler(ctrlCHandler, FALSE);
+#else
+ signal(SIGINT, SIG_DFL);
+#endif
+ }
+ else
+ printf("Failed to register event listener.\n");
+ IEventSource_UnregisterListener(es, (IEventListener *)consoleListener);
+#ifdef WIN32
+ if (consoleListener->pUnkMarshaler)
+ IUnknown_Release(consoleListener->pUnkMarshaler);
+#endif
+ IEventListenerDemo_Release(consoleListener);
+ }
+ else
+ printf("Failed while allocating memory for console event listener.\n");
+ g_pVBoxFuncs->pfnSafeArrayDestroy(interestingEventsSA);
+ IEventSource_Release(es);
+ }
+ else
+ printf("Failed to get the event source instance.\n");
+ IConsole_Release(console);
+ }
+}
+
+#else /* !USE_ACTIVE_EVENT_LISTENER */
+
+/**
+ * Register passive event listener for the selected VM.
+ *
+ * @param virtualBox ptr to IVirtualBox object
+ * @param session ptr to ISession object
+ */
+static void registerPassiveEventListener(ISession *session)
+{
+ IConsole *console = NULL;
+ HRESULT hrc;
+
+ hrc = ISession_get_Console(session, &console);
+ if (SUCCEEDED(hrc) && console)
+ {
+ IEventSource *es = NULL;
+ hrc = IConsole_get_EventSource(console, &es);
+ if (SUCCEEDED(hrc) && es)
+ {
+ static const ULONG s_auInterestingEvents[] =
+ {
+ VBoxEventType_OnMousePointerShapeChanged,
+ VBoxEventType_OnMouseCapabilityChanged,
+ VBoxEventType_OnKeyboardLedsChanged,
+ VBoxEventType_OnStateChanged,
+ VBoxEventType_OnAdditionsStateChanged,
+ VBoxEventType_OnNetworkAdapterChanged,
+ VBoxEventType_OnSerialPortChanged,
+ VBoxEventType_OnParallelPortChanged,
+ VBoxEventType_OnStorageControllerChanged,
+ VBoxEventType_OnMediumChanged,
+ VBoxEventType_OnVRDEServerChanged,
+ VBoxEventType_OnUSBControllerChanged,
+ VBoxEventType_OnUSBDeviceStateChanged,
+ VBoxEventType_OnSharedFolderChanged,
+ VBoxEventType_OnRuntimeError,
+ VBoxEventType_OnCanShowWindow,
+ VBoxEventType_OnShowWindow
+ };
+ SAFEARRAY *interestingEventsSA = NULL;
+ IEventListener *consoleListener = NULL;
+
+ /* The VirtualBox API expects enum values as VT_I4, which in the
+ * future can be hopefully relaxed. */
+ interestingEventsSA = g_pVBoxFuncs->pfnSafeArrayCreateVector(VT_I4, 0,
+ sizeof(s_auInterestingEvents)
+ / sizeof(s_auInterestingEvents[0]));
+ g_pVBoxFuncs->pfnSafeArrayCopyInParamHelper(interestingEventsSA, &s_auInterestingEvents,
+ sizeof(s_auInterestingEvents));
+
+ hrc = IEventSource_CreateListener(es, &consoleListener);
+ if (SUCCEEDED(hrc) && consoleListener)
+ {
+ hrc = IEventSource_RegisterListener(es, consoleListener,
+ ComSafeArrayAsInParam(interestingEventsSA),
+ 0 /* passive */);
+ if (SUCCEEDED(hrc))
+ {
+ /* Just wait here for events, no easy way to do this better
+ * as there's not much to do after this completes. */
+ printf("Entering event loop, PowerOff the machine to exit or press Ctrl-C to terminate\n");
+ fflush(stdout);
+#ifdef WIN32
+ SetConsoleCtrlHandler(ctrlCHandler, TRUE);
+#else
+ signal(SIGINT, ctrlCHandler);
+#endif
+
+ while (!g_fStop)
+ {
+ IEvent *ev = NULL;
+ hrc = IEventSource_GetEvent(es, consoleListener, 250, &ev);
+ if (FAILED(hrc))
+ {
+ printf("Failed getting event: %#x\n", (unsigned)hrc);
+ g_fStop = 1;
+ continue;
+ }
+ /* handle timeouts, resulting in NULL events */
+ if (!ev)
+ continue;
+ hrc = EventListenerDemoProcessEvent(ev);
+ if (FAILED(hrc))
+ {
+ printf("Failed processing event: %#x\n", (unsigned)hrc);
+ g_fStop = 1;
+ /* finish processing the event */
+ }
+ hrc = IEventSource_EventProcessed(es, consoleListener, ev);
+ if (FAILED(hrc))
+ {
+ printf("Failed to mark event as processed: %#x\n", (unsigned)hrc);
+ g_fStop = 1;
+ /* continue with event release */
+ }
+ if (ev)
+ {
+ IEvent_Release(ev);
+ ev = NULL;
+ }
+ }
+
+#ifdef WIN32
+ SetConsoleCtrlHandler(ctrlCHandler, FALSE);
+#else
+ signal(SIGINT, SIG_DFL);
+#endif
+ }
+ else
+ printf("Failed to register event listener.\n");
+ IEventSource_UnregisterListener(es, (IEventListener *)consoleListener);
+ IEventListener_Release(consoleListener);
+ }
+ else
+ printf("Failed to create an event listener instance.\n");
+ g_pVBoxFuncs->pfnSafeArrayDestroy(interestingEventsSA);
+ IEventSource_Release(es);
+ }
+ else
+ printf("Failed to get the event source instance.\n");
+ IConsole_Release(console);
+ }
+}
+
+#endif /* !USE_ACTIVE_EVENT_LISTENER */
+
+/**
+ * Print detailed error information if available.
+ * @param pszExecutable string with the executable name
+ * @param pszErrorMsg string containing the code location specific error message
+ * @param hrc COM/XPCOM result code
+ */
+static void PrintErrorInfo(const char *pszExecutable, const char *pszErrorMsg, HRESULT hrc)
+{
+ IErrorInfo *ex;
+ HRESULT hrc2;
+ fprintf(stderr, "%s: %s (hrc=%#010x)\n", pszExecutable, pszErrorMsg, (unsigned)hrc);
+ hrc2 = g_pVBoxFuncs->pfnGetException(&ex);
+ if (SUCCEEDED(hrc2) && ex)
+ {
+ IVirtualBoxErrorInfo *ei;
+ hrc2 = IErrorInfo_QueryInterface(ex, &IID_IVirtualBoxErrorInfo, (void **)&ei);
+ if (SUCCEEDED(hrc2) && ei != NULL)
+ {
+ /* got extended error info, maybe multiple infos */
+ do
+ {
+ LONG resultCode = S_OK;
+ BSTR componentUtf16 = NULL;
+ char *component = NULL;
+ BSTR textUtf16 = NULL;
+ char *text = NULL;
+ IVirtualBoxErrorInfo *ei_next = NULL;
+ fprintf(stderr, "Extended error info (IVirtualBoxErrorInfo):\n");
+
+ IVirtualBoxErrorInfo_get_ResultCode(ei, &resultCode);
+ fprintf(stderr, " resultCode=%#010x\n", (unsigned)resultCode);
+
+ IVirtualBoxErrorInfo_get_Component(ei, &componentUtf16);
+ g_pVBoxFuncs->pfnUtf16ToUtf8(componentUtf16, &component);
+ g_pVBoxFuncs->pfnComUnallocString(componentUtf16);
+ fprintf(stderr, " component=%s\n", component);
+ g_pVBoxFuncs->pfnUtf8Free(component);
+
+ IVirtualBoxErrorInfo_get_Text(ei, &textUtf16);
+ g_pVBoxFuncs->pfnUtf16ToUtf8(textUtf16, &text);
+ g_pVBoxFuncs->pfnComUnallocString(textUtf16);
+ fprintf(stderr, " text=%s\n", text);
+ g_pVBoxFuncs->pfnUtf8Free(text);
+
+ hrc2 = IVirtualBoxErrorInfo_get_Next(ei, &ei_next);
+ if (FAILED(hrc2))
+ ei_next = NULL;
+ IVirtualBoxErrorInfo_Release(ei);
+ ei = ei_next;
+ } while (ei);
+ }
+
+ IErrorInfo_Release(ex);
+ g_pVBoxFuncs->pfnClearException();
+ }
+}
+
+/**
+ * Start a VM.
+ *
+ * @param argv0 executable name
+ * @param virtualBox ptr to IVirtualBox object
+ * @param session ptr to ISession object
+ * @param id identifies the machine to start
+ */
+static void startVM(const char *argv0, IVirtualBox *virtualBox, ISession *session, BSTR id)
+{
+ HRESULT hrc;
+ IMachine *machine = NULL;
+ IProgress *progress = NULL;
+ SAFEARRAY *env = NULL;
+ BSTR sessionType;
+ SAFEARRAY *groupsSA = g_pVBoxFuncs->pfnSafeArrayOutParamAlloc();
+
+ hrc = IVirtualBox_FindMachine(virtualBox, id, &machine);
+ if (FAILED(hrc) || !machine)
+ {
+ PrintErrorInfo(argv0, "Error: Couldn't get the Machine reference", hrc);
+ return;
+ }
+
+ hrc = IMachine_get_Groups(machine, ComSafeArrayAsOutTypeParam(groupsSA, BSTR));
+ if (SUCCEEDED(hrc))
+ {
+ BSTR *groups = NULL;
+ ULONG cbGroups = 0;
+ ULONG i, cGroups;
+ g_pVBoxFuncs->pfnSafeArrayCopyOutParamHelper((void **)&groups, &cbGroups, VT_BSTR, groupsSA);
+ g_pVBoxFuncs->pfnSafeArrayDestroy(groupsSA);
+ cGroups = cbGroups / sizeof(groups[0]);
+ for (i = 0; i < cGroups; ++i)
+ {
+ /* Note that the use of %S might be tempting, but it is not
+ * available on all platforms, and even where it is usable it
+ * may depend on correct compiler options to make wchar_t a
+ * 16 bit number. So better play safe and use UTF-8. */
+ char *group;
+ g_pVBoxFuncs->pfnUtf16ToUtf8(groups[i], &group);
+ printf("Groups[%u]: %s\n", (unsigned)i, group);
+ g_pVBoxFuncs->pfnUtf8Free(group);
+ }
+ for (i = 0; i < cGroups; ++i)
+ g_pVBoxFuncs->pfnComUnallocString(groups[i]);
+ g_pVBoxFuncs->pfnArrayOutFree(groups);
+ }
+
+ g_pVBoxFuncs->pfnUtf8ToUtf16("gui", &sessionType);
+ hrc = IMachine_LaunchVMProcess(machine, session, sessionType, ComSafeArrayAsInParam(env), &progress);
+ g_pVBoxFuncs->pfnUtf16Free(sessionType);
+ if (SUCCEEDED(hrc))
+ {
+ BOOL completed;
+ LONG resultCode;
+
+ printf("Waiting for the remote session to open...\n");
+ IProgress_WaitForCompletion(progress, -1);
+
+ hrc = IProgress_get_Completed(progress, &completed);
+ if (FAILED(hrc))
+ fprintf(stderr, "Error: GetCompleted status failed\n");
+
+ IProgress_get_ResultCode(progress, &resultCode);
+ if (FAILED(resultCode))
+ {
+ IVirtualBoxErrorInfo *errorInfo;
+ BSTR textUtf16;
+ char *text;
+
+ IProgress_get_ErrorInfo(progress, &errorInfo);
+ IVirtualBoxErrorInfo_get_Text(errorInfo, &textUtf16);
+ g_pVBoxFuncs->pfnUtf16ToUtf8(textUtf16, &text);
+ printf("Error: %s\n", text);
+
+ g_pVBoxFuncs->pfnComUnallocString(textUtf16);
+ g_pVBoxFuncs->pfnUtf8Free(text);
+ IVirtualBoxErrorInfo_Release(errorInfo);
+ }
+ else
+ {
+ fprintf(stderr, "VM process has been successfully started\n");
+
+ /* Kick off the event listener demo part, which is quite separate.
+ * Ignore it if you need a more basic sample. */
+#ifdef USE_ACTIVE_EVENT_LISTENER
+ registerActiveEventListener(virtualBox, session);
+#else
+ registerPassiveEventListener(session);
+#endif
+ }
+ IProgress_Release(progress);
+ }
+ else
+ PrintErrorInfo(argv0, "Error: LaunchVMProcess failed", hrc);
+
+ /* It's important to always release resources. */
+ IMachine_Release(machine);
+}
+
+/**
+ * List the registered VMs.
+ *
+ * @param argv0 executable name
+ * @param virtualBox ptr to IVirtualBox object
+ * @param session ptr to ISession object
+ */
+static void listVMs(const char *argv0, IVirtualBox *virtualBox, ISession *session)
+{
+ HRESULT hrc;
+ SAFEARRAY *machinesSA = g_pVBoxFuncs->pfnSafeArrayOutParamAlloc();
+ IMachine **machines = NULL;
+ ULONG machineCnt = 0;
+ ULONG i;
+ unsigned start_id;
+
+ /*
+ * Get the list of all registered VMs.
+ */
+ hrc = IVirtualBox_get_Machines(virtualBox, ComSafeArrayAsOutIfaceParam(machinesSA, IMachine *));
+ if (FAILED(hrc))
+ {
+ PrintErrorInfo(argv0, "could not get list of machines", hrc);
+ return;
+ }
+
+ /*
+ * Extract interface pointers from machinesSA, and update the reference
+ * counter of each object, as destroying machinesSA would call Release.
+ */
+ g_pVBoxFuncs->pfnSafeArrayCopyOutIfaceParamHelper((IUnknown ***)&machines, &machineCnt, machinesSA);
+ g_pVBoxFuncs->pfnSafeArrayDestroy(machinesSA);
+
+ if (!machineCnt)
+ {
+ g_pVBoxFuncs->pfnArrayOutFree(machines);
+ printf("\tNo VMs\n");
+ return;
+ }
+
+ printf("VM List:\n\n");
+
+ /*
+ * Iterate through the collection.
+ */
+ for (i = 0; i < machineCnt; ++i)
+ {
+ IMachine *machine = machines[i];
+ BOOL isAccessible = FALSE;
+
+ printf("\tMachine #%u\n", (unsigned)i);
+
+ if (!machine)
+ {
+ printf("\t(skipped, NULL)\n");
+ continue;
+ }
+
+ IMachine_get_Accessible(machine, &isAccessible);
+
+ if (isAccessible)
+ {
+ BSTR machineNameUtf16;
+ char *machineName;
+
+ IMachine_get_Name(machine, &machineNameUtf16);
+ g_pVBoxFuncs->pfnUtf16ToUtf8(machineNameUtf16,&machineName);
+ g_pVBoxFuncs->pfnComUnallocString(machineNameUtf16);
+ printf("\tName: %s\n", machineName);
+ g_pVBoxFuncs->pfnUtf8Free(machineName);
+ }
+ else
+ printf("\tName: <inaccessible>\n");
+
+ {
+ BSTR uuidUtf16;
+ char *uuidUtf8;
+
+ IMachine_get_Id(machine, &uuidUtf16);
+ g_pVBoxFuncs->pfnUtf16ToUtf8(uuidUtf16, &uuidUtf8);
+ g_pVBoxFuncs->pfnComUnallocString(uuidUtf16);
+ printf("\tUUID: %s\n", uuidUtf8);
+ g_pVBoxFuncs->pfnUtf8Free(uuidUtf8);
+ }
+
+ if (isAccessible)
+ {
+ {
+ BSTR configFileUtf16;
+ char *configFileUtf8;
+
+ IMachine_get_SettingsFilePath(machine, &configFileUtf16);
+ g_pVBoxFuncs->pfnUtf16ToUtf8(configFileUtf16, &configFileUtf8);
+ g_pVBoxFuncs->pfnComUnallocString(configFileUtf16);
+ printf("\tConfig file: %s\n", configFileUtf8);
+ g_pVBoxFuncs->pfnUtf8Free(configFileUtf8);
+ }
+
+ {
+ ULONG memorySize;
+
+ IMachine_get_MemorySize(machine, &memorySize);
+ printf("\tMemory size: %uMB\n", (unsigned)memorySize);
+ }
+
+ {
+ BSTR typeId;
+ BSTR osNameUtf16;
+ char *osName;
+ IGuestOSType *osType = NULL;
+
+ IMachine_get_OSTypeId(machine, &typeId);
+ IVirtualBox_GetGuestOSType(virtualBox, typeId, &osType);
+ g_pVBoxFuncs->pfnComUnallocString(typeId);
+ IGuestOSType_get_Description(osType, &osNameUtf16);
+ g_pVBoxFuncs->pfnUtf16ToUtf8(osNameUtf16,&osName);
+ g_pVBoxFuncs->pfnComUnallocString(osNameUtf16);
+ printf("\tGuest OS: %s\n\n", osName);
+ g_pVBoxFuncs->pfnUtf8Free(osName);
+
+ IGuestOSType_Release(osType);
+ }
+ }
+ }
+
+ /*
+ * Let the user chose a machine to start.
+ */
+ printf("Type Machine# to start (0 - %u) or 'quit' to do nothing: ",
+ (unsigned)(machineCnt - 1));
+ fflush(stdout);
+
+ if (scanf("%u", &start_id) == 1 && start_id < machineCnt)
+ {
+ IMachine *machine = machines[start_id];
+
+ if (machine)
+ {
+ BSTR uuidUtf16 = NULL;
+
+ IMachine_get_Id(machine, &uuidUtf16);
+ startVM(argv0, virtualBox, session, uuidUtf16);
+ g_pVBoxFuncs->pfnComUnallocString(uuidUtf16);
+ }
+ }
+
+ /*
+ * Don't forget to release the objects in the array.
+ */
+ for (i = 0; i < machineCnt; ++i)
+ {
+ IMachine *machine = machines[i];
+
+ if (machine)
+ IMachine_Release(machine);
+ }
+ g_pVBoxFuncs->pfnArrayOutFree(machines);
+}
+
+/* Main - Start the ball rolling. */
+
+int main(int argc, char **argv)
+{
+ IVirtualBoxClient *vboxclient = NULL;
+ IVirtualBox *vbox = NULL;
+ ISession *session = NULL;
+ ULONG revision = 0;
+ BSTR versionUtf16 = NULL;
+ BSTR homefolderUtf16 = NULL;
+ HRESULT hrc; /* Result code of various function (method) calls. */
+ (void)argc;
+
+ printf("Starting main()\n");
+
+ if (VBoxCGlueInit())
+ {
+ fprintf(stderr, "%s: FATAL: VBoxCGlueInit failed: %s\n",
+ argv[0], g_szVBoxErrMsg);
+ return EXIT_FAILURE;
+ }
+
+ {
+ unsigned ver = g_pVBoxFuncs->pfnGetVersion();
+ printf("VirtualBox version: %u.%u.%u\n", ver / 1000000, ver / 1000 % 1000, ver % 1000);
+ ver = g_pVBoxFuncs->pfnGetAPIVersion();
+ printf("VirtualBox API version: %u.%u\n", ver / 1000, ver % 1000);
+ }
+
+ g_pVBoxFuncs->pfnClientInitialize(NULL, &vboxclient);
+ if (!vboxclient)
+ {
+ fprintf(stderr, "%s: FATAL: could not get VirtualBoxClient reference\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ printf("----------------------------------------------------\n");
+
+ hrc = IVirtualBoxClient_get_VirtualBox(vboxclient, &vbox);
+ if (FAILED(hrc) || !vbox)
+ {
+ PrintErrorInfo(argv[0], "FATAL: could not get VirtualBox reference", hrc);
+ return EXIT_FAILURE;
+ }
+ hrc = IVirtualBoxClient_get_Session(vboxclient, &session);
+ if (FAILED(hrc) || !session)
+ {
+ PrintErrorInfo(argv[0], "FATAL: could not get Session reference", hrc);
+ return EXIT_FAILURE;
+ }
+
+#ifdef USE_ACTIVE_EVENT_LISTENER
+# ifdef WIN32
+ hrc = LoadTypeInfo(&IID_IEventListener, &g_pTInfoIEventListener);
+ if (FAILED(hrc) || !g_pTInfoIEventListener)
+ {
+ PrintErrorInfo(argv[0], "FATAL: could not get type information for IEventListener", hrc);
+ return EXIT_FAILURE;
+ }
+# endif /* WIN32 */
+#endif /* USE_ACTIVE_EVENT_LISTENER */
+
+ /*
+ * Now ask for revision, version and home folder information of
+ * this vbox. Were not using fancy macros here so it
+ * remains easy to see how we access C++'s vtable.
+ */
+
+ /* 1. Revision */
+ hrc = IVirtualBox_get_Revision(vbox, &revision);
+ if (SUCCEEDED(hrc))
+ printf("\tRevision: %u\n", (unsigned)revision);
+ else
+ PrintErrorInfo(argv[0], "GetRevision() failed", hrc);
+
+ /* 2. Version */
+ hrc = IVirtualBox_get_Version(vbox, &versionUtf16);
+ if (SUCCEEDED(hrc))
+ {
+ char *version = NULL;
+ g_pVBoxFuncs->pfnUtf16ToUtf8(versionUtf16, &version);
+ printf("\tVersion: %s\n", version);
+ g_pVBoxFuncs->pfnUtf8Free(version);
+ g_pVBoxFuncs->pfnComUnallocString(versionUtf16);
+ }
+ else
+ PrintErrorInfo(argv[0], "GetVersion() failed", hrc);
+
+ /* 3. Home Folder */
+ hrc = IVirtualBox_get_HomeFolder(vbox, &homefolderUtf16);
+ if (SUCCEEDED(hrc))
+ {
+ char *homefolder = NULL;
+ g_pVBoxFuncs->pfnUtf16ToUtf8(homefolderUtf16, &homefolder);
+ printf("\tHomeFolder: %s\n", homefolder);
+ g_pVBoxFuncs->pfnUtf8Free(homefolder);
+ g_pVBoxFuncs->pfnComUnallocString(homefolderUtf16);
+ }
+ else
+ PrintErrorInfo(argv[0], "GetHomeFolder() failed", hrc);
+
+ listVMs(argv[0], vbox, session);
+ ISession_UnlockMachine(session);
+
+ printf("----------------------------------------------------\n");
+
+ /*
+ * Do as mom told us: always clean up after yourself.
+ */
+#ifdef USE_ACTIVE_EVENT_LISTENER
+# ifdef WIN32
+ if (g_pTInfoIEventListener)
+ {
+ ITypeInfo_Release(g_pTInfoIEventListener);
+ g_pTInfoIEventListener = NULL;
+ }
+# endif /* WIN32 */
+#endif /* USE_ACTIVE_EVENT_LISTENER */
+
+ if (session)
+ {
+ ISession_Release(session);
+ session = NULL;
+ }
+ if (vbox)
+ {
+ IVirtualBox_Release(vbox);
+ vbox = NULL;
+ }
+ if (vboxclient)
+ {
+ IVirtualBoxClient_Release(vboxclient);
+ vboxclient = NULL;
+ }
+
+ g_pVBoxFuncs->pfnClientUninitialize();
+ VBoxCGlueTerm();
+ printf("Finished main()\n");
+
+ return 0;
+}
+/* vim: set ts=4 sw=4 et: */