VirtualBox

source: vbox/trunk/src/VBox/GuestHost/OpenGL/util/dll.c@ 49216

最後變更 在這個檔案從49216是 46805,由 vboxsync 提交於 11 年 前

crOpenGL: fail if GetModuleFileName or GetSystemDirectory fail, and switch to unicode

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Id
檔案大小: 9.9 KB
 
1/* Copyright (c) 2001, Stanford University
2 * All rights reserved
3 *
4 * See the file LICENSE.txt for information on redistributing this software.
5 */
6
7#include "cr_mem.h"
8#include "cr_error.h"
9#include "cr_dll.h"
10#include "cr_string.h"
11#include "stdio.h"
12
13#ifndef IN_GUEST
14#include <string.h>
15#endif
16
17#if defined(IRIX) || defined(IRIX64) || defined(Linux) || defined(FreeBSD) || defined(AIX) || defined(DARWIN) || defined(SunOS) || defined(OSF1)
18#include <dlfcn.h>
19#endif
20
21#ifdef WINDOWS
22#include <Shlwapi.h>
23#endif
24
25#ifdef DARWIN
26
27#include <Carbon/Carbon.h>
28#include <mach-o/dyld.h>
29
30char *__frameworkErr=NULL;
31
32CFBundleRef LoadFramework( const char *frameworkName ) {
33 CFBundleRef bundle;
34 CFURLRef bundleURL;
35 char fullfile[8096];
36
37 if( frameworkName[0] != '/' ) {
38 /* load a system framework */
39 /* XXX \todo should this folder be retrieved from somewhere else? */
40 crStrcpy( fullfile, "/System/Library/Frameworks/" );
41 crStrcat( fullfile, frameworkName );
42 } else {
43 /* load any framework */
44 crStrcpy( fullfile, frameworkName );
45 }
46
47 bundleURL = CFURLCreateWithString( NULL, CFStringCreateWithCStringNoCopy(NULL, fullfile, CFStringGetSystemEncoding(), NULL), NULL );
48 if( !bundleURL ) {
49 __frameworkErr = "Could not create OpenGL Framework bundle URL";
50 return NULL;
51 }
52
53 bundle = CFBundleCreate( kCFAllocatorDefault, bundleURL );
54 CFRelease( bundleURL );
55
56 if( !bundle ) {
57 __frameworkErr = "Could not create OpenGL Framework bundle";
58 return NULL;
59 }
60
61 if( !CFBundleLoadExecutable(bundle) ) {
62 __frameworkErr = "Could not load MachO executable";
63 return NULL;
64 }
65
66 return bundle;
67}
68
69char *__bundleErr=NULL;
70
71void *LoadBundle( const char *filename ) {
72 NSObjectFileImage fileImage;
73 NSModule handle = NULL;
74 char _filename[PATH_MAX];
75
76 __bundleErr = NULL;
77
78 if( filename[0] != '/' ) {
79 /* default to a chromium bundle */
80 crStrcpy( _filename, "/cr/lib/Darwin/" );
81 crStrcat( _filename, filename );
82 } else {
83 crStrcpy( _filename, filename );
84 }
85
86 switch( NSCreateObjectFileImageFromFile(_filename, &fileImage) ) {
87 default:
88 case NSObjectFileImageFailure:
89 __bundleErr = "NSObjectFileImageFailure: Failure.";
90 break;
91
92 case NSObjectFileImageInappropriateFile:
93 __bundleErr = "NSObjectFileImageInappropriateFile: The specified file is not of a valid type.";
94 break;
95
96 case NSObjectFileImageArch:
97 __bundleErr = "NSObjectFileImageArch: The specified file is for a different CPU architecture.";
98 break;
99
100 case NSObjectFileImageFormat:
101 __bundleErr = "NSObjectFileImageFormat: The specified file does not appear to be a Mach-O file";
102 break;
103
104 case NSObjectFileImageAccess:
105 __bundleErr = "NSObjectFileImageAccess: Permission to create image denied.";
106 break;
107
108 case NSObjectFileImageSuccess:
109 handle = NSLinkModule( fileImage, _filename,
110 NSLINKMODULE_OPTION_RETURN_ON_ERROR |
111 NSLINKMODULE_OPTION_PRIVATE );
112 NSDestroyObjectFileImage( fileImage );
113 if( !handle ) {
114 NSLinkEditErrors c;
115 int n;
116 const char *name;
117 NSLinkEditError(&c, &n, &name, (const char**)&__bundleErr);
118 }
119 break;
120 }
121
122 return handle;
123}
124
125int check_extension( const char *name, const char *extension ) {
126 int nam_len = crStrlen( name );
127 int ext_len = crStrlen( extension );
128 char *pos = crStrstr( name, extension );
129 return ( pos == &(name[nam_len-ext_len]) );
130}
131
132enum {
133 CR_DLL_NONE,
134 CR_DLL_FRAMEWORK,
135 CR_DLL_DYLIB,
136 CR_DLL_BUNDLE,
137 CR_DLL_UNKNOWN
138};
139
140#define NS_ADD 0
141
142int get_dll_type( const char *name ) {
143 if( check_extension(name, ".framework") )
144 return CR_DLL_FRAMEWORK;
145 if( check_extension(name, ".bundle") )
146 return CR_DLL_BUNDLE;
147 if( check_extension(name, ".dylib") )
148 return CR_DLL_DYLIB;
149 return CR_DLL_DYLIB;
150}
151
152#endif
153
154/*
155 * Open the named shared library.
156 * If resolveGlobal is non-zero, unresolved symbols can be satisfied by
157 * any matching symbol already defined globally. Otherwise, if resolveGlobal
158 * is zero, unresolved symbols should be resolved using symbols in that
159 * object (in preference to global symbols).
160 * NOTE: this came about because we found that for libGL, we need the
161 * global-resolve option but for SPU's we need the non-global option (consider
162 * the state tracker duplicated in the array, tilesort, etc. SPUs).
163 */
164CRDLL *crDLLOpen( const char *dllname, int resolveGlobal )
165{
166 CRDLL *dll;
167 char *dll_err;
168#if defined(WINDOWS)
169 WCHAR szwPath[MAX_PATH];
170 UINT cwcPath = 0;
171
172 (void) resolveGlobal;
173
174# ifndef CR_NO_GL_SYSTEM_PATH
175 if (PathIsRelative(dllname))
176 {
177 size_t cName = strlen(dllname) + 1;
178# ifdef IN_GUEST
179 cwcPath = GetSystemDirectoryW(szwPath, RT_ELEMENTS(szwPath));
180 if (!cwcPath || cwcPath >= MAX_PATH)
181 {
182 DWORD winEr = GetLastError();
183 crError("GetSystemDirectoryW failed err %d", winEr);
184 SetLastError(winEr);
185 return NULL;
186 }
187# else
188 WCHAR * pszwSlashFile;
189 cwcPath = GetModuleFileNameW(NULL, szwPath, RT_ELEMENTS(szwPath));
190 if (!cwcPath || cwcPath >= MAX_PATH)
191 {
192 DWORD winEr = GetLastError();
193 crError("GetModuleFileNameW failed err %d", winEr);
194 SetLastError(winEr);
195 return NULL;
196 }
197
198 pszwSlashFile = wcsrchr(szwPath, L'\\');
199 if (!pszwSlashFile)
200 {
201 crError("failed to match file name");
202 SetLastError(ERROR_PATH_NOT_FOUND);
203 return NULL;
204 }
205
206 cwcPath = pszwSlashFile - szwPath;
207# endif
208
209 if (cwcPath + 1 + cName > MAX_PATH)
210 {
211 crError("invalid path specified");
212 SetLastError(ERROR_FILENAME_EXCED_RANGE);
213 return NULL;
214 }
215 szwPath[cwcPath] = '\\';
216 ++cwcPath;
217 }
218
219 if (!MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, dllname, -1, &szwPath[cwcPath], MAX_PATH - cwcPath))
220 {
221 DWORD winEr = GetLastError();
222 crError("MultiByteToWideChar failed err %d", winEr);
223 SetLastError(winEr);
224 return NULL;
225 }
226# endif // CR_NO_GL_SYSTEM_PATH
227#endif
228
229 dll = (CRDLL *) crAlloc( sizeof( CRDLL ) );
230 dll->name = crStrdup( dllname );
231
232#if defined(WINDOWS)
233 dll->hinstLib = LoadLibraryW( szwPath );
234 if (!dll->hinstLib)
235 {
236 crError("failed to load dll %s", dllname);
237 }
238 dll_err = NULL;
239#elif defined(DARWIN)
240 /* XXX \todo Get better error handling in here */
241 dll->type = get_dll_type( dllname );
242 dll_err = NULL;
243
244 switch( dll->type ) {
245 case CR_DLL_FRAMEWORK:
246 dll->hinstLib = LoadFramework( dllname );
247 dll_err = __frameworkErr;
248 break;
249
250 case CR_DLL_BUNDLE:
251 dll->hinstLib = LoadBundle( dllname );
252 dll_err = __bundleErr;
253 break;
254
255 case CR_DLL_DYLIB:
256#if NS_ADD
257 dll->hinstLib = (void*)NSAddImage( dllname, NSADDIMAGE_OPTION_RETURN_ON_ERROR );
258#else
259 if( resolveGlobal )
260 dll->hinstLib = dlopen( dllname, RTLD_LAZY | RTLD_GLOBAL );
261 else
262 dll->hinstLib = dlopen( dllname, RTLD_LAZY | RTLD_LOCAL );
263 dll_err = (char*) dlerror();
264#endif
265 break;
266
267 default:
268 dll->hinstLib = NULL;
269 dll_err = "Unknown DLL type";
270 break;
271 };
272#elif defined(IRIX) || defined(IRIX64) || defined(Linux) || defined(FreeBSD) || defined(AIX) || defined(SunOS) || defined(OSF1)
273 if (resolveGlobal)
274 dll->hinstLib = dlopen( dllname, RTLD_LAZY | RTLD_GLOBAL );
275 else
276 dll->hinstLib = dlopen( dllname, RTLD_LAZY );
277 dll_err = (char*) dlerror();
278#else
279#error DSO
280#endif
281
282 if (!dll->hinstLib)
283 {
284 if (dll_err)
285 {
286 crDebug( "DLL_ERROR(%s): %s", dllname, dll_err );
287 }
288 crError( "DLL Loader couldn't find/open %s", dllname );
289 }
290 return dll;
291}
292
293CRDLLFunc crDLLGetNoError( CRDLL *dll, const char *symname )
294{
295#if defined(WINDOWS)
296 return (CRDLLFunc) GetProcAddress( dll->hinstLib, symname );
297#elif defined(DARWIN)
298 NSSymbol nssym;
299
300 if( dll->type == CR_DLL_FRAMEWORK )
301 return (CRDLLFunc) CFBundleGetFunctionPointerForName( (CFBundleRef) dll->hinstLib, CFStringCreateWithCStringNoCopy(NULL, symname, CFStringGetSystemEncoding(), NULL) );
302
303 if( dll->type == CR_DLL_DYLIB )
304#if NS_ADD
305 nssym = NSLookupSymbolInImage( dll->hinstLib, symname, NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR );
306#else
307 return (CRDLLFunc) dlsym( dll->hinstLib, symname );
308#endif
309 else
310 nssym = NSLookupSymbolInModule( dll->hinstLib, symname );
311
312 if( !nssym ) {
313 char name[PATH_MAX];
314 crStrcpy( name, "_" );
315 crStrcat( name, symname );
316
317 if( dll->type == CR_DLL_DYLIB )
318 nssym = NSLookupSymbolInImage( dll->hinstLib, name, NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR );
319 else
320 nssym = NSLookupSymbolInModule( dll->hinstLib, name );
321 }
322
323 return (CRDLLFunc) NSAddressOfSymbol( nssym );
324
325#elif defined(IRIX) || defined(IRIX64) || defined(Linux) || defined(FreeBSD) || defined(AIX) || defined(SunOS) || defined(OSF1)
326 return (CRDLLFunc) dlsym( dll->hinstLib, symname );
327#else
328#error CR DLL ARCHITETECTURE
329#endif
330}
331
332CRDLLFunc crDLLGet( CRDLL *dll, const char *symname )
333{
334 CRDLLFunc data = crDLLGetNoError( dll, symname );
335 if (!data)
336 {
337 /* Are you sure there isn't some C++ mangling messing you up? */
338 crWarning( "Couldn't get symbol \"%s\" in \"%s\"", symname, dll->name );
339 }
340 return data;
341}
342
343void crDLLClose( CRDLL *dll )
344{
345 int dll_err = 0;
346
347 if (!dll) return;
348
349#if defined(WINDOWS)
350 FreeLibrary( dll->hinstLib );
351#elif defined(DARWIN)
352 switch( dll->type ) {
353 case CR_DLL_FRAMEWORK:
354 CFBundleUnloadExecutable( dll->hinstLib );
355 CFRelease(dll->hinstLib);
356 dll->hinstLib = NULL;
357 break;
358
359 case CR_DLL_DYLIB:
360#if !NS_ADD
361 dlclose( dll->hinstLib );
362#endif
363 break;
364
365 case CR_DLL_BUNDLE:
366 NSUnLinkModule( (NSModule) dll->hinstLib, 0L );
367 break;
368 }
369#elif defined(IRIX) || defined(IRIX64) || defined(Linux) || defined(FreeBSD) || defined(AIX) || defined(SunOS) || defined(OSF1)
370 /*
371 * Unloading Nvidia's libGL will crash VirtualBox later during shutdown.
372 * Therefore we will skip unloading it. It will be unloaded later anway
373 * because we are already freeing all resources and VirtualBox will terminate
374 * soon.
375 */
376#ifndef IN_GUEST
377 if (strncmp(dll->name, "libGL", 5))
378#endif
379 dll_err = dlclose( dll->hinstLib );
380#else
381#error DSO
382#endif
383
384 if (dll_err)
385 crWarning("Error closing DLL %s\n",dll->name);
386
387 crFree( dll->name );
388 crFree( dll );
389}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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