VirtualBox

source: vbox/trunk/src/VBox/Main/cbinding/VBoxXPCOMCGlue.c@ 38791

Last change on this file since 38791 was 33396, checked in by vboxsync, 14 years ago

Main: Some OS/2 build fixes.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.4 KB
Line 
1/* $Revision: 33396 $ */
2/** @file
3 * Glue code for dynamically linking to VBoxXPCOMC.
4 */
5
6/*
7 * Copyright (C) 2008-2010 Oracle Corporation
8 *
9 * Permission is hereby granted, free of charge, to any person
10 * obtaining a copy of this software and associated documentation
11 * files (the "Software"), to deal in the Software without
12 * restriction, including without limitation the rights to use,
13 * copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following
16 * conditions:
17 *
18 * The above copyright notice and this permission notice shall be
19 * included in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 * OTHER DEALINGS IN THE SOFTWARE.
29 */
30
31/*******************************************************************************
32* Header Files *
33*******************************************************************************/
34#include <stdio.h>
35#include <string.h>
36#include <stdlib.h>
37#include <stdarg.h>
38#include <stdint.h>
39#include <dlfcn.h>
40
41#include "VBoxXPCOMCGlue.h"
42
43
44/*******************************************************************************
45* Defined Constants And Macros *
46*******************************************************************************/
47#if defined(__linux__) || defined(__linux_gnu__) || defined(__sun__) || defined(__FreeBSD__)
48# define DYNLIB_NAME "VBoxXPCOMC.so"
49#elif defined(__APPLE__)
50# define DYNLIB_NAME "VBoxXPCOMC.dylib"
51#elif defined(_MSC_VER) || defined(__OS2__)
52# define DYNLIB_NAME "VBoxXPCOMC.dll"
53#else
54# error "Port me"
55#endif
56
57
58/*******************************************************************************
59* Global Variables *
60*******************************************************************************/
61/** The dlopen handle for VBoxXPCOMC. */
62void *g_hVBoxXPCOMC = NULL;
63/** The last load error. */
64char g_szVBoxErrMsg[256];
65/** Pointer to the VBoxXPCOMC function table. */
66PCVBOXXPCOM g_pVBoxFuncs = NULL;
67/** Pointer to VBoxGetXPCOMCFunctions for the loaded VBoxXPCOMC so/dylib/dll. */
68PFNVBOXGETXPCOMCFUNCTIONS g_pfnGetFunctions = NULL;
69
70
71/**
72 * Wrapper for setting g_szVBoxErrMsg. Can be an empty stub.
73 *
74 * @param fAlways When 0 the g_szVBoxErrMsg is only set if empty.
75 * @param pszFormat The format string.
76 * @param ... The arguments.
77 */
78static void setErrMsg(int fAlways, const char *pszFormat, ...)
79{
80 if ( fAlways
81 || !g_szVBoxErrMsg[0])
82 {
83 va_list va;
84 va_start(va, pszFormat);
85 vsnprintf(g_szVBoxErrMsg, sizeof(g_szVBoxErrMsg), pszFormat, va);
86 va_end(va);
87 }
88}
89
90
91/**
92 * Try load VBoxXPCOMC.so/dylib/dll from the specified location and resolve all
93 * the symbols we need.
94 *
95 * @returns 0 on success, -1 on failure.
96 * @param pszHome The director where to try load VBoxXPCOMC from. Can
97 * be NULL.
98 * @param fSetAppHome Whether to set the VBOX_APP_HOME env.var. or not
99 * (boolean).
100 */
101static int tryLoadOne(const char *pszHome, int fSetAppHome)
102{
103 size_t cchHome = pszHome ? strlen(pszHome) : 0;
104 size_t cbBufNeeded;
105 char szName[4096];
106 int rc = -1;
107
108 /*
109 * Construct the full name.
110 */
111 cbBufNeeded = cchHome + sizeof("/" DYNLIB_NAME);
112 if (cbBufNeeded > sizeof(szName))
113 {
114 setErrMsg(1, "path buffer too small: %u bytes needed",
115 (unsigned)cbBufNeeded);
116 return -1;
117 }
118 if (cchHome)
119 {
120 memcpy(szName, pszHome, cchHome);
121 szName[cchHome] = '/';
122 cchHome++;
123 }
124 memcpy(&szName[cchHome], DYNLIB_NAME, sizeof(DYNLIB_NAME));
125
126 /*
127 * Try load it by that name, setting the VBOX_APP_HOME first (for now).
128 * Then resolve and call the function table getter.
129 */
130 if (fSetAppHome)
131 {
132 if (pszHome)
133 setenv("VBOX_APP_HOME", pszHome, 1 /* always override */);
134 else
135 unsetenv("VBOX_APP_HOME");
136 }
137 g_hVBoxXPCOMC = dlopen(szName, RTLD_NOW | RTLD_LOCAL);
138 if (g_hVBoxXPCOMC)
139 {
140 PFNVBOXGETXPCOMCFUNCTIONS pfnGetFunctions;
141 pfnGetFunctions = (PFNVBOXGETXPCOMCFUNCTIONS)(uintptr_t)
142 dlsym(g_hVBoxXPCOMC, VBOX_GET_XPCOMC_FUNCTIONS_SYMBOL_NAME);
143 if (pfnGetFunctions)
144 {
145 g_pVBoxFuncs = pfnGetFunctions(VBOX_XPCOMC_VERSION);
146 if (g_pVBoxFuncs)
147 {
148 g_pfnGetFunctions = pfnGetFunctions;
149 return 0;
150 }
151
152 /* bail out */
153 setErrMsg(1, "%.80s: pfnGetFunctions(%#x) failed",
154 szName, VBOX_XPCOMC_VERSION);
155 }
156 else
157 setErrMsg(1, "dlsym(%.80s/%.32s): %.128s",
158 szName, VBOX_GET_XPCOMC_FUNCTIONS_SYMBOL_NAME, dlerror());
159 dlclose(g_hVBoxXPCOMC);
160 g_hVBoxXPCOMC = NULL;
161 }
162 else
163 setErrMsg(0, "dlopen(%.80s): %.160s", szName, dlerror());
164 return rc;
165}
166
167
168/**
169 * Tries to locate and load VBoxXPCOMC.so/dylib/dll, resolving all the related
170 * function pointers.
171 *
172 * @returns 0 on success, -1 on failure.
173 *
174 * @remark This should be considered moved into a separate glue library since
175 * its its going to be pretty much the same for any user of VBoxXPCOMC
176 * and it will just cause trouble to have duplicate versions of this
177 * source code all around the place.
178 */
179int VBoxCGlueInit(void)
180{
181 /*
182 * If the user specifies the location, try only that.
183 */
184 const char *pszHome = getenv("VBOX_APP_HOME");
185 if (pszHome)
186 return tryLoadOne(pszHome, 0);
187
188 /*
189 * Try the known standard locations.
190 */
191 g_szVBoxErrMsg[0] = '\0';
192#if defined(__gnu__linux__) || defined(__linux__)
193 if (tryLoadOne("/opt/VirtualBox", 1) == 0)
194 return 0;
195 if (tryLoadOne("/usr/lib/virtualbox", 1) == 0)
196 return 0;
197#elif defined(__sun__)
198 if (tryLoadOne("/opt/VirtualBox/amd64", 1) == 0)
199 return 0;
200 if (tryLoadOne("/opt/VirtualBox/i386", 1) == 0)
201 return 0;
202#elif defined(__APPLE__)
203 if (tryLoadOne("/Application/VirtualBox.app/Contents/MacOS", 1) == 0)
204 return 0;
205#elif defined(__FreeBSD__)
206 if (tryLoadOne("/usr/local/lib/virtualbox", 1) == 0)
207 return 0;
208#elif defined(__OS2__)
209 if (tryLoadOne("C:/Apps/VirtualBox", 1) == 0)
210 return 0;
211#else
212# error "port me"
213#endif
214
215 /*
216 * Finally try the dynamic linker search path.
217 */
218 if (tryLoadOne(NULL, 1) == 0)
219 return 0;
220
221 /* No luck, return failure. */
222 return -1;
223}
224
225
226/**
227 * Terminate the C glue library.
228 */
229void VBoxCGlueTerm(void)
230{
231 if (g_hVBoxXPCOMC)
232 {
233#if 0 /* VBoxRT.so doesn't like being reloaded. See @bugref{3725}. */
234 dlclose(g_hVBoxXPCOMC);
235#endif
236 g_hVBoxXPCOMC = NULL;
237 }
238 g_pVBoxFuncs = NULL;
239 g_pfnGetFunctions = NULL;
240 memset(g_szVBoxErrMsg, 0, sizeof(g_szVBoxErrMsg));
241}
242
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette