VirtualBox

source: vbox/trunk/src/VBox/Main/cbinding/VBoxCAPIGlue.c@ 56841

最後變更 在這個檔案從56841是 55400,由 vboxsync 提交於 10 年 前

Id

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 10.3 KB
 
1/* $Id: VBoxCAPIGlue.c 55400 2015-04-23 09:54:00Z vboxsync $ */
2/** @file
3 * Glue code for dynamically linking to VBoxCAPI.
4 */
5
6/*
7 * Copyright (C) 2008-2015 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 "VBoxCAPIGlue.h"
35
36#include <stdio.h>
37#include <string.h>
38#include <stdlib.h>
39#include <stdarg.h>
40#include <stdint.h>
41#ifndef WIN32
42# include <dlfcn.h>
43# include <pthread.h>
44#else /* WIN32 */
45# include <Windows.h>
46#endif /* WIN32 */
47
48
49/*******************************************************************************
50* Defined Constants And Macros *
51*******************************************************************************/
52#if defined(__linux__) || defined(__linux_gnu__) || defined(__sun__) || defined(__FreeBSD__)
53# define DYNLIB_NAME "VBoxXPCOMC.so"
54#elif defined(__APPLE__)
55# define DYNLIB_NAME "VBoxXPCOMC.dylib"
56#elif defined(__OS2__)
57# define DYNLIB_NAME "VBoxXPCOMC.dll"
58#elif defined(WIN32)
59# define DYNLIB_NAME "VBoxCAPI.dll"
60#else
61# error "Port me"
62#endif
63
64
65/*******************************************************************************
66* Global Variables *
67*******************************************************************************/
68/** The so/dynsym/dll handle for VBoxCAPI. */
69#ifndef WIN32
70void *g_hVBoxCAPI = NULL;
71#else /* WIN32 */
72HMODULE g_hVBoxCAPI = NULL;
73#endif /* WIN32 */
74/** The last load error. */
75char g_szVBoxErrMsg[256] = "";
76/** Pointer to the VBOXCAPI function table. */
77PCVBOXCAPI g_pVBoxFuncs = NULL;
78/** Pointer to VBoxGetCAPIFunctions for the loaded VBoxCAPI so/dylib/dll. */
79PFNVBOXGETCAPIFUNCTIONS g_pfnGetFunctions = NULL;
80
81typedef void FNDUMMY(void);
82typedef FNDUMMY *PFNDUMMY;
83/** Just a dummy global structure containing a bunch of
84 * function pointers to code which is wanted in the link. */
85PFNDUMMY g_apfnVBoxCAPIGlue[] =
86{
87#ifndef WIN32
88 /* The following link dependency is for helping gdb as it gets hideously
89 * confused if the application doesn't drag in pthreads, but uses it. */
90 (PFNDUMMY)pthread_create,
91#endif /* !WIN32 */
92 NULL
93};
94
95
96/**
97 * Wrapper for setting g_szVBoxErrMsg. Can be an empty stub.
98 *
99 * @param fAlways When 0 the g_szVBoxErrMsg is only set if empty.
100 * @param pszFormat The format string.
101 * @param ... The arguments.
102 */
103static void setErrMsg(int fAlways, const char *pszFormat, ...)
104{
105 if ( fAlways
106 || !g_szVBoxErrMsg[0])
107 {
108 va_list va;
109 va_start(va, pszFormat);
110 vsnprintf(g_szVBoxErrMsg, sizeof(g_szVBoxErrMsg), pszFormat, va);
111 va_end(va);
112 }
113}
114
115
116/**
117 * Try load C API .so/dylib/dll from the specified location and resolve all
118 * the symbols we need. Tries both the new style and legacy name.
119 *
120 * @returns 0 on success, -1 on failure.
121 * @param pszHome The directory where to try load VBoxCAPI/VBoxXPCOMC
122 * from. Can be NULL.
123 * @param fSetAppHome Whether to set the VBOX_APP_HOME env.var. or not
124 * (boolean).
125 */
126static int tryLoadLibrary(const char *pszHome, int fSetAppHome)
127{
128 size_t cchHome = pszHome ? strlen(pszHome) : 0;
129 size_t cbBufNeeded;
130 char szName[4096];
131
132 /*
133 * Construct the full name.
134 */
135 cbBufNeeded = cchHome + sizeof("/" DYNLIB_NAME);
136 if (cbBufNeeded > sizeof(szName))
137 {
138 setErrMsg(1, "path buffer too small: %u bytes needed",
139 (unsigned)cbBufNeeded);
140 return -1;
141 }
142 if (cchHome)
143 {
144 memcpy(szName, pszHome, cchHome);
145 szName[cchHome] = '/';
146 cchHome++;
147 }
148 memcpy(&szName[cchHome], DYNLIB_NAME, sizeof(DYNLIB_NAME));
149
150 /*
151 * Try load it by that name, setting the VBOX_APP_HOME first (for now).
152 * Then resolve and call the function table getter.
153 */
154 if (fSetAppHome)
155 {
156#ifndef WIN32
157 if (pszHome)
158 setenv("VBOX_APP_HOME", pszHome, 1 /* always override */);
159 else
160 unsetenv("VBOX_APP_HOME");
161#endif /* !WIN32 */
162 }
163
164#ifndef WIN32
165 g_hVBoxCAPI = dlopen(szName, RTLD_NOW | RTLD_LOCAL);
166#else /* WIN32 */
167 g_hVBoxCAPI = LoadLibraryExA(szName, NULL /* hFile */, 0 /* dwFlags */);
168#endif /* WIN32 */
169 if (g_hVBoxCAPI)
170 {
171 PFNVBOXGETCAPIFUNCTIONS pfnGetFunctions;
172#ifndef WIN32
173 pfnGetFunctions = (PFNVBOXGETCAPIFUNCTIONS)(uintptr_t)
174 dlsym(g_hVBoxCAPI, VBOX_GET_CAPI_FUNCTIONS_SYMBOL_NAME);
175# ifdef VBOX_GET_XPCOM_FUNCTIONS_SYMBOL_NAME
176 if (!pfnGetFunctions)
177 pfnGetFunctions = (PFNVBOXGETCAPIFUNCTIONS)(uintptr_t)
178 dlsym(g_hVBoxCAPI, VBOX_GET_XPCOM_FUNCTIONS_SYMBOL_NAME);
179# endif /* VBOX_GET_XPCOM_FUNCTIONS_SYMBOL_NAME */
180#else /* WIN32 */
181 pfnGetFunctions = (PFNVBOXGETCAPIFUNCTIONS)
182 GetProcAddress(g_hVBoxCAPI, VBOX_GET_CAPI_FUNCTIONS_SYMBOL_NAME);
183#endif /* WIN32 */
184 if (pfnGetFunctions)
185 {
186 g_pVBoxFuncs = pfnGetFunctions(VBOX_CAPI_VERSION);
187 if (g_pVBoxFuncs)
188 {
189 if ( ( VBOX_CAPI_MAJOR(g_pVBoxFuncs->uVersion)
190 == VBOX_CAPI_MAJOR(VBOX_CAPI_VERSION))
191 && ( VBOX_CAPI_MINOR(g_pVBoxFuncs->uVersion)
192 >= VBOX_CAPI_MINOR(VBOX_CAPI_VERSION)))
193 {
194 g_pfnGetFunctions = pfnGetFunctions;
195 return 0;
196 }
197 setErrMsg(1, "%.80s: pfnGetFunctions(%#x) returned incompatible version %#x",
198 szName, VBOX_CAPI_VERSION, g_pVBoxFuncs->uVersion);
199 g_pVBoxFuncs = NULL;
200 }
201 else
202 {
203 /* bail out */
204 setErrMsg(1, "%.80s: pfnGetFunctions(%#x) failed",
205 szName, VBOX_CAPI_VERSION);
206 }
207 }
208 else
209 {
210#ifndef WIN32
211 setErrMsg(1, "dlsym(%.80s/%.32s): %.128s",
212 szName, VBOX_GET_CAPI_FUNCTIONS_SYMBOL_NAME, dlerror());
213#else /* WIN32 */
214 setErrMsg(1, "GetProcAddress(%.80s/%.32s): %d",
215 szName, VBOX_GET_CAPI_FUNCTIONS_SYMBOL_NAME, GetLastError());
216#endif /* WIN32 */
217 }
218
219#ifndef WIN32
220 dlclose(g_hVBoxCAPI);
221#else /* WIN32 */
222 FreeLibrary(g_hVBoxCAPI);
223#endif /* WIN32 */
224 g_hVBoxCAPI = NULL;
225 }
226 else
227 {
228#ifndef WIN32
229 setErrMsg(0, "dlopen(%.80s): %.160s", szName, dlerror());
230#else /* WIN32 */
231 setErrMsg(0, "LoadLibraryEx(%.80s): %d", szName, GetLastError());
232#endif /* WIN32 */
233 }
234
235 return -1;
236}
237
238
239/**
240 * Tries to locate and load VBoxCAPI.so/dylib/dll, resolving all the related
241 * function pointers.
242 *
243 * @returns 0 on success, -1 on failure.
244 *
245 * @remark This should be considered moved into a separate glue library since
246 * its its going to be pretty much the same for any user of VBoxCAPI
247 * and it will just cause trouble to have duplicate versions of this
248 * source code all around the place.
249 */
250int VBoxCGlueInit(void)
251{
252 const char *pszHome;
253
254 memset(g_szVBoxErrMsg, 0, sizeof(g_szVBoxErrMsg));
255
256 /*
257 * If the user specifies the location, try only that.
258 */
259 pszHome = getenv("VBOX_APP_HOME");
260 if (pszHome)
261 return tryLoadLibrary(pszHome, 0);
262
263 /*
264 * Try the known standard locations.
265 */
266#if defined(__gnu__linux__) || defined(__linux__)
267 if (tryLoadLibrary("/opt/VirtualBox", 1) == 0)
268 return 0;
269 if (tryLoadLibrary("/usr/lib/virtualbox", 1) == 0)
270 return 0;
271#elif defined(__sun__)
272 if (tryLoadLibrary("/opt/VirtualBox/amd64", 1) == 0)
273 return 0;
274 if (tryLoadLibrary("/opt/VirtualBox/i386", 1) == 0)
275 return 0;
276#elif defined(__APPLE__)
277 if (tryLoadLibrary("/Applications/VirtualBox.app/Contents/MacOS", 1) == 0)
278 return 0;
279#elif defined(__FreeBSD__)
280 if (tryLoadLibrary("/usr/local/lib/virtualbox", 1) == 0)
281 return 0;
282#elif defined(__OS2__)
283 if (tryLoadLibrary("C:/Apps/VirtualBox", 1) == 0)
284 return 0;
285#elif defined(WIN32)
286 pszHome = getenv("ProgramFiles");
287 if (pszHome)
288 {
289 char szPath[4096];
290 size_t cb = sizeof(szPath);
291 char *tmp = szPath;
292 strncpy(tmp, pszHome, cb);
293 tmp[cb - 1] = '\0';
294 cb -= strlen(tmp);
295 tmp += strlen(tmp);
296 strncpy(tmp, "/Oracle/VirtualBox", cb);
297 tmp[cb - 1] = '\0';
298 if (tryLoadLibrary(szPath, 1) == 0)
299 return 0;
300 }
301 if (tryLoadLibrary("C:/Program Files/Oracle/VirtualBox", 1) == 0)
302 return 0;
303#else
304# error "port me"
305#endif
306
307 /*
308 * Finally try the dynamic linker search path.
309 */
310 if (tryLoadLibrary(NULL, 1) == 0)
311 return 0;
312
313 /* No luck, return failure. */
314 return -1;
315}
316
317
318/**
319 * Terminate the C glue library.
320 */
321void VBoxCGlueTerm(void)
322{
323 if (g_hVBoxCAPI)
324 {
325#if 0 /* VBoxRT.so doesn't like being reloaded. See @bugref{3725}. */
326#ifndef WIN32
327 dlclose(g_hVBoxCAPI);
328#else
329 FreeLibrary(g_hVBoxCAPI);
330#endif
331#endif
332 g_hVBoxCAPI = NULL;
333 }
334 g_pVBoxFuncs = NULL;
335 g_pfnGetFunctions = NULL;
336 memset(g_szVBoxErrMsg, 0, sizeof(g_szVBoxErrMsg));
337}
338
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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