VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Wine/libWine/loader.c@ 20227

Last change on this file since 20227 was 19678, checked in by vboxsync, 16 years ago

opengl: update wine to 1.1.21, add d3d9.dll to build list

  • Property svn:eol-style set to native
File size: 23.7 KB
Line 
1/*
2 * Win32 builtin dlls support
3 *
4 * Copyright 2000 Alexandre Julliard
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21/*
22 * Sun LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
23 * other than GPL or LGPL is available it will apply instead, Sun elects to use only
24 * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
25 * a choice of LGPL license versions is made available with the language indicating
26 * that LGPLv2 or any later version may be used, or where a choice of which version
27 * of the LGPL is applied is otherwise unspecified.
28 */
29
30#include "config.h"
31#include "wine/port.h"
32
33#include <assert.h>
34#include <ctype.h>
35#include <fcntl.h>
36#include <limits.h>
37#include <stdarg.h>
38#include <stdlib.h>
39#include <string.h>
40#include <sys/types.h>
41#ifdef HAVE_SYS_MMAN_H
42#include <sys/mman.h>
43#endif
44#ifdef HAVE_SYS_RESOURCE_H
45# include <sys/resource.h>
46#endif
47#ifdef HAVE_UNISTD_H
48# include <unistd.h>
49#endif
50
51#define NONAMELESSUNION
52#define NONAMELESSSTRUCT
53#include "windef.h"
54#include "winbase.h"
55#include "wine/library.h"
56
57#ifdef __APPLE__
58#include <crt_externs.h>
59#define environ (*_NSGetEnviron())
60#else
61extern char **environ;
62#endif
63
64/* argc/argv for the Windows application */
65int __wine_main_argc = 0;
66char **__wine_main_argv = NULL;
67WCHAR **__wine_main_wargv = NULL;
68char **__wine_main_environ = NULL;
69
70struct dll_path_context
71{
72 unsigned int index; /* current index in the dll path list */
73 char *buffer; /* buffer used for storing path names */
74 char *name; /* start of file name part in buffer (including leading slash) */
75 int namelen; /* length of file name without .so extension */
76 int win16; /* 16-bit dll search */
77};
78
79#define MAX_DLLS 100
80
81static struct
82{
83 const IMAGE_NT_HEADERS *nt; /* NT header */
84 const char *filename; /* DLL file name */
85} builtin_dlls[MAX_DLLS];
86
87static int nb_dlls;
88
89static const IMAGE_NT_HEADERS *main_exe;
90
91static load_dll_callback_t load_dll_callback;
92
93static const char *build_dir;
94static const char *default_dlldir;
95static const char **dll_paths;
96static unsigned int nb_dll_paths;
97static int dll_path_maxlen;
98
99extern void mmap_init(void);
100extern const char *get_dlldir( const char **default_dlldir );
101
102/* build the dll load path from the WINEDLLPATH variable */
103static void build_dll_path(void)
104{
105 int len, count = 0;
106 char *p, *path = getenv( "WINEDLLPATH" );
107 const char *dlldir = get_dlldir( &default_dlldir );
108
109 if (path)
110 {
111 /* count how many path elements we need */
112 path = strdup(path);
113 p = path;
114 while (*p)
115 {
116 while (*p == ':') p++;
117 if (!*p) break;
118 count++;
119 while (*p && *p != ':') p++;
120 }
121 }
122
123 dll_paths = malloc( (count+2) * sizeof(*dll_paths) );
124 nb_dll_paths = 0;
125
126 if (dlldir)
127 {
128 dll_path_maxlen = strlen(dlldir);
129 dll_paths[nb_dll_paths++] = dlldir;
130 }
131 else if ((build_dir = wine_get_build_dir()))
132 {
133 dll_path_maxlen = strlen(build_dir) + sizeof("/programs");
134 }
135
136 if (count)
137 {
138 p = path;
139 while (*p)
140 {
141 while (*p == ':') *p++ = 0;
142 if (!*p) break;
143 dll_paths[nb_dll_paths] = p;
144 while (*p && *p != ':') p++;
145 if (p - dll_paths[nb_dll_paths] > dll_path_maxlen)
146 dll_path_maxlen = p - dll_paths[nb_dll_paths];
147 nb_dll_paths++;
148 }
149 }
150
151 /* append default dll dir (if not empty) to path */
152 if ((len = strlen(default_dlldir)) > 0)
153 {
154 if (len > dll_path_maxlen) dll_path_maxlen = len;
155 dll_paths[nb_dll_paths++] = default_dlldir;
156 }
157}
158
159/* check if a given file can be opened */
160static inline int file_exists( const char *name )
161{
162 int fd = open( name, O_RDONLY );
163 if (fd != -1) close( fd );
164 return (fd != -1);
165}
166
167static inline char *prepend( char *buffer, const char *str, size_t len )
168{
169 return memcpy( buffer - len, str, len );
170}
171
172/* get a filename from the next entry in the dll path */
173static char *next_dll_path( struct dll_path_context *context )
174{
175 unsigned int index = context->index++;
176 int namelen = context->namelen;
177 char *path = context->name;
178
179 switch(index)
180 {
181 case 0: /* try dlls dir with subdir prefix */
182 if (namelen > 4 && !memcmp( context->name + namelen - 4, ".dll", 4 )) namelen -= 4;
183 if (!context->win16) path = prepend( path, context->name, namelen );
184 path = prepend( path, "/dlls", sizeof("/dlls") - 1 );
185 path = prepend( path, build_dir, strlen(build_dir) );
186 return path;
187 case 1: /* try programs dir with subdir prefix */
188 if (!context->win16)
189 {
190 if (namelen > 4 && !memcmp( context->name + namelen - 4, ".exe", 4 )) namelen -= 4;
191 path = prepend( path, context->name, namelen );
192 path = prepend( path, "/programs", sizeof("/programs") - 1 );
193 path = prepend( path, build_dir, strlen(build_dir) );
194 return path;
195 }
196 context->index++;
197 /* fall through */
198 default:
199 index -= 2;
200 if (index < nb_dll_paths)
201 return prepend( context->name, dll_paths[index], strlen( dll_paths[index] ));
202 break;
203 }
204 return NULL;
205}
206
207
208/* get a filename from the first entry in the dll path */
209static char *first_dll_path( const char *name, int win16, struct dll_path_context *context )
210{
211 char *p;
212 int namelen = strlen( name );
213 const char *ext = win16 ? "16" : ".so";
214
215 context->buffer = malloc( dll_path_maxlen + 2 * namelen + strlen(ext) + 3 );
216 context->index = build_dir ? 0 : 2; /* if no build dir skip all the build dir magic cases */
217 context->name = context->buffer + dll_path_maxlen + namelen + 1;
218 context->namelen = namelen + 1;
219 context->win16 = win16;
220
221 /* store the name at the end of the buffer, followed by extension */
222 p = context->name;
223 *p++ = '/';
224 memcpy( p, name, namelen );
225 strcpy( p + namelen, ext );
226 return next_dll_path( context );
227}
228
229
230/* free the dll path context created by first_dll_path */
231static inline void free_dll_path( struct dll_path_context *context )
232{
233 free( context->buffer );
234}
235
236
237/* open a library for a given dll, searching in the dll path
238 * 'name' must be the Windows dll name (e.g. "kernel32.dll") */
239static void *dlopen_dll( const char *name, char *error, int errorsize,
240 int test_only, int *exists )
241{
242 struct dll_path_context context;
243 char *path;
244 void *ret = NULL;
245
246 *exists = 0;
247 for (path = first_dll_path( name, 0, &context ); path; path = next_dll_path( &context ))
248 {
249 if (!test_only && (ret = wine_dlopen( path, RTLD_NOW, error, errorsize ))) break;
250 if ((*exists = file_exists( path ))) break; /* exists but cannot be loaded, return the error */
251 }
252 free_dll_path( &context );
253 return ret;
254}
255
256
257/* adjust an array of pointers to make them into RVAs */
258static inline void fixup_rva_ptrs( void *array, BYTE *base, unsigned int count )
259{
260 void **src = (void **)array;
261 DWORD *dst = (DWORD *)array;
262 while (count--)
263 {
264 *dst++ = *src ? (BYTE *)*src - base : 0;
265 src++;
266 }
267}
268
269/* fixup an array of RVAs by adding the specified delta */
270static inline void fixup_rva_dwords( DWORD *ptr, int delta, unsigned int count )
271{
272 while (count--)
273 {
274 if (*ptr) *ptr += delta;
275 ptr++;
276 }
277}
278
279
280/* fixup RVAs in the import directory */
281static void fixup_imports( IMAGE_IMPORT_DESCRIPTOR *dir, BYTE *base, int delta )
282{
283 UINT_PTR *ptr;
284
285 while (dir->Name)
286 {
287 fixup_rva_dwords( &dir->u.OriginalFirstThunk, delta, 1 );
288 fixup_rva_dwords( &dir->Name, delta, 1 );
289 fixup_rva_dwords( &dir->FirstThunk, delta, 1 );
290 ptr = (UINT_PTR *)(base + (dir->u.OriginalFirstThunk ? dir->u.OriginalFirstThunk : dir->FirstThunk));
291 while (*ptr)
292 {
293 if (!(*ptr & IMAGE_ORDINAL_FLAG)) *ptr += delta;
294 ptr++;
295 }
296 dir++;
297 }
298}
299
300
301/* fixup RVAs in the export directory */
302static void fixup_exports( IMAGE_EXPORT_DIRECTORY *dir, BYTE *base, int delta )
303{
304 fixup_rva_dwords( &dir->Name, delta, 1 );
305 fixup_rva_dwords( &dir->AddressOfFunctions, delta, 1 );
306 fixup_rva_dwords( &dir->AddressOfNames, delta, 1 );
307 fixup_rva_dwords( &dir->AddressOfNameOrdinals, delta, 1 );
308 fixup_rva_dwords( (DWORD *)(base + dir->AddressOfNames), delta, dir->NumberOfNames );
309 fixup_rva_ptrs( (base + dir->AddressOfFunctions), base, dir->NumberOfFunctions );
310}
311
312
313/* fixup RVAs in the resource directory */
314static void fixup_resources( IMAGE_RESOURCE_DIRECTORY *dir, BYTE *root, int delta )
315{
316 IMAGE_RESOURCE_DIRECTORY_ENTRY *entry;
317 int i;
318
319 entry = (IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1);
320 for (i = 0; i < dir->NumberOfNamedEntries + dir->NumberOfIdEntries; i++, entry++)
321 {
322 void *ptr = root + entry->u2.s3.OffsetToDirectory;
323 if (entry->u2.s3.DataIsDirectory) fixup_resources( ptr, root, delta );
324 else
325 {
326 IMAGE_RESOURCE_DATA_ENTRY *data = ptr;
327 fixup_rva_dwords( &data->OffsetToData, delta, 1 );
328 }
329 }
330}
331
332
333/* map a builtin dll in memory and fixup RVAs */
334static void *map_dll( const IMAGE_NT_HEADERS *nt_descr )
335{
336#ifdef HAVE_MMAP
337 IMAGE_DATA_DIRECTORY *dir;
338 IMAGE_DOS_HEADER *dos;
339 IMAGE_NT_HEADERS *nt;
340 IMAGE_SECTION_HEADER *sec;
341 BYTE *addr;
342 DWORD code_start, data_start, data_end;
343 const size_t page_size = getpagesize();
344 const size_t page_mask = page_size - 1;
345 int delta, nb_sections = 2; /* code + data */
346 unsigned int i;
347
348 size_t size = (sizeof(IMAGE_DOS_HEADER)
349 + sizeof(IMAGE_NT_HEADERS)
350 + nb_sections * sizeof(IMAGE_SECTION_HEADER));
351
352 assert( size <= page_size );
353
354 /* module address must be aligned on 64K boundary */
355 addr = (BYTE *)((nt_descr->OptionalHeader.ImageBase + 0xffff) & ~0xffff);
356 if (wine_anon_mmap( addr, page_size, PROT_READ|PROT_WRITE, MAP_FIXED ) != addr) return NULL;
357
358 dos = (IMAGE_DOS_HEADER *)addr;
359 nt = (IMAGE_NT_HEADERS *)(dos + 1);
360 sec = (IMAGE_SECTION_HEADER *)(nt + 1);
361
362 /* Build the DOS and NT headers */
363
364 dos->e_magic = IMAGE_DOS_SIGNATURE;
365 dos->e_cblp = 0x90;
366 dos->e_cp = 3;
367 dos->e_cparhdr = (sizeof(*dos)+0xf)/0x10;
368 dos->e_minalloc = 0;
369 dos->e_maxalloc = 0xffff;
370 dos->e_ss = 0x0000;
371 dos->e_sp = 0x00b8;
372 dos->e_lfarlc = sizeof(*dos);
373 dos->e_lfanew = sizeof(*dos);
374
375 *nt = *nt_descr;
376
377 delta = (const BYTE *)nt_descr - addr;
378 code_start = page_size;
379 data_start = delta & ~page_mask;
380 data_end = (nt->OptionalHeader.SizeOfImage + delta + page_mask) & ~page_mask;
381
382 fixup_rva_ptrs( &nt->OptionalHeader.AddressOfEntryPoint, addr, 1 );
383
384 nt->FileHeader.NumberOfSections = nb_sections;
385 nt->OptionalHeader.BaseOfCode = code_start;
386#ifndef _WIN64
387 nt->OptionalHeader.BaseOfData = data_start;
388#endif
389 nt->OptionalHeader.SizeOfCode = data_start - code_start;
390 nt->OptionalHeader.SizeOfInitializedData = data_end - data_start;
391 nt->OptionalHeader.SizeOfUninitializedData = 0;
392 nt->OptionalHeader.SizeOfImage = data_end;
393 nt->OptionalHeader.ImageBase = (ULONG_PTR)addr;
394
395 /* Build the code section */
396
397 memcpy( sec->Name, ".text", sizeof(".text") );
398 sec->SizeOfRawData = data_start - code_start;
399 sec->Misc.VirtualSize = sec->SizeOfRawData;
400 sec->VirtualAddress = code_start;
401 sec->PointerToRawData = code_start;
402 sec->Characteristics = (IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ);
403 sec++;
404
405 /* Build the data section */
406
407 memcpy( sec->Name, ".data", sizeof(".data") );
408 sec->SizeOfRawData = data_end - data_start;
409 sec->Misc.VirtualSize = sec->SizeOfRawData;
410 sec->VirtualAddress = data_start;
411 sec->PointerToRawData = data_start;
412 sec->Characteristics = (IMAGE_SCN_CNT_INITIALIZED_DATA |
413 IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ);
414 sec++;
415
416 for (i = 0; i < nt->OptionalHeader.NumberOfRvaAndSizes; i++)
417 fixup_rva_dwords( &nt->OptionalHeader.DataDirectory[i].VirtualAddress, delta, 1 );
418
419 /* Build the import directory */
420
421 dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_IMPORT_DIRECTORY];
422 if (dir->Size)
423 {
424 IMAGE_IMPORT_DESCRIPTOR *imports = (void *)(addr + dir->VirtualAddress);
425 fixup_imports( imports, addr, delta );
426 }
427
428 /* Build the resource directory */
429
430 dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_RESOURCE_DIRECTORY];
431 if (dir->Size)
432 {
433 void *ptr = (void *)(addr + dir->VirtualAddress);
434 fixup_resources( ptr, ptr, delta );
435 }
436
437 /* Build the export directory */
438
439 dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_EXPORT_DIRECTORY];
440 if (dir->Size)
441 {
442 IMAGE_EXPORT_DIRECTORY *exports = (void *)(addr + dir->VirtualAddress);
443 fixup_exports( exports, addr, delta );
444 }
445 return addr;
446#else /* HAVE_MMAP */
447 return NULL;
448#endif /* HAVE_MMAP */
449}
450
451
452/***********************************************************************
453 * __wine_get_main_environment
454 *
455 * Return an environment pointer to work around lack of environ variable.
456 * Only exported on Mac OS.
457 */
458char **__wine_get_main_environment(void)
459{
460 return environ;
461}
462
463
464/***********************************************************************
465 * __wine_dll_register
466 *
467 * Register a built-in DLL descriptor.
468 */
469void __wine_dll_register( const IMAGE_NT_HEADERS *header, const char *filename )
470{
471 if (load_dll_callback) load_dll_callback( map_dll(header), filename );
472 else
473 {
474 if (!(header->FileHeader.Characteristics & IMAGE_FILE_DLL))
475 main_exe = header;
476 else
477 {
478 assert( nb_dlls < MAX_DLLS );
479 builtin_dlls[nb_dlls].nt = header;
480 builtin_dlls[nb_dlls].filename = filename;
481 nb_dlls++;
482 }
483 }
484}
485
486
487/***********************************************************************
488 * wine_dll_set_callback
489 *
490 * Set the callback function for dll loading, and call it
491 * for all dlls that were implicitly loaded already.
492 */
493void wine_dll_set_callback( load_dll_callback_t load )
494{
495 int i;
496 load_dll_callback = load;
497 for (i = 0; i < nb_dlls; i++)
498 {
499 const IMAGE_NT_HEADERS *nt = builtin_dlls[i].nt;
500 if (!nt) continue;
501 builtin_dlls[i].nt = NULL;
502 load_dll_callback( map_dll(nt), builtin_dlls[i].filename );
503 }
504 nb_dlls = 0;
505 if (main_exe) load_dll_callback( map_dll(main_exe), "" );
506}
507
508
509/***********************************************************************
510 * wine_dll_load
511 *
512 * Load a builtin dll.
513 */
514void *wine_dll_load( const char *filename, char *error, int errorsize, int *file_exists )
515{
516 int i;
517
518 /* callback must have been set already */
519 assert( load_dll_callback );
520
521 /* check if we have it in the list */
522 /* this can happen when initializing pre-loaded dlls in wine_dll_set_callback */
523 for (i = 0; i < nb_dlls; i++)
524 {
525 if (!builtin_dlls[i].nt) continue;
526 if (!strcmp( builtin_dlls[i].filename, filename ))
527 {
528 const IMAGE_NT_HEADERS *nt = builtin_dlls[i].nt;
529 builtin_dlls[i].nt = NULL;
530 load_dll_callback( map_dll(nt), builtin_dlls[i].filename );
531 *file_exists = 1;
532 return (void *)1;
533 }
534 }
535 return dlopen_dll( filename, error, errorsize, 0, file_exists );
536}
537
538
539/***********************************************************************
540 * wine_dll_unload
541 *
542 * Unload a builtin dll.
543 */
544void wine_dll_unload( void *handle )
545{
546 if (handle != (void *)1)
547 wine_dlclose( handle, NULL, 0 );
548}
549
550
551/***********************************************************************
552 * wine_dll_load_main_exe
553 *
554 * Try to load the .so for the main exe.
555 */
556void *wine_dll_load_main_exe( const char *name, char *error, int errorsize,
557 int test_only, int *file_exists )
558{
559 return dlopen_dll( name, error, errorsize, test_only, file_exists );
560}
561
562
563/***********************************************************************
564 * wine_dll_enum_load_path
565 *
566 * Enumerate the dll load path.
567 */
568const char *wine_dll_enum_load_path( unsigned int index )
569{
570 if (index >= nb_dll_paths) return NULL;
571 return dll_paths[index];
572}
573
574
575/***********************************************************************
576 * wine_dll_get_owner
577 *
578 * Retrieve the name of the 32-bit owner dll for a 16-bit dll.
579 * Return 0 if OK, -1 on error.
580 */
581int wine_dll_get_owner( const char *name, char *buffer, int size, int *exists )
582{
583 int ret = -1;
584 char *path;
585 struct dll_path_context context;
586
587 *exists = 0;
588
589 for (path = first_dll_path( name, 1, &context ); path; path = next_dll_path( &context ))
590 {
591 int fd = open( path, O_RDONLY );
592 if (fd != -1)
593 {
594 int res = read( fd, buffer, size - 1 );
595 while (res > 0 && (buffer[res-1] == '\n' || buffer[res-1] == '\r')) res--;
596 buffer[res] = 0;
597 close( fd );
598 *exists = 1;
599 ret = 0;
600 break;
601 }
602 }
603 free_dll_path( &context );
604 return ret;
605}
606
607
608/***********************************************************************
609 * set_max_limit
610 *
611 * Set a user limit to the maximum allowed value.
612 */
613static void set_max_limit( int limit )
614{
615#ifdef HAVE_SETRLIMIT
616 struct rlimit rlimit;
617
618 if (!getrlimit( limit, &rlimit ))
619 {
620 rlimit.rlim_cur = rlimit.rlim_max;
621 if (setrlimit( limit, &rlimit ) != 0)
622 {
623#if defined(__APPLE__) && defined(RLIMIT_NOFILE) && defined(OPEN_MAX)
624 /* On Leopard, setrlimit(RLIMIT_NOFILE, ...) fails on attempts to set
625 * rlim_cur above OPEN_MAX (even if rlim_max > OPEN_MAX). */
626 if (limit == RLIMIT_NOFILE && rlimit.rlim_cur > OPEN_MAX)
627 {
628 rlimit.rlim_cur = OPEN_MAX;
629 setrlimit( limit, &rlimit );
630 }
631#endif
632 }
633 }
634#endif
635}
636
637
638/***********************************************************************
639 * wine_init
640 *
641 * Main Wine initialisation.
642 */
643void wine_init( int argc, char *argv[], char *error, int error_size )
644{
645 struct dll_path_context context;
646 char *path;
647 void *ntdll = NULL;
648 void (*init_func)(void);
649
650 /* force a few limits that are set too low on some platforms */
651#ifdef RLIMIT_NOFILE
652 set_max_limit( RLIMIT_NOFILE );
653#endif
654#ifdef RLIMIT_AS
655 set_max_limit( RLIMIT_AS );
656#endif
657
658 wine_init_argv0_path( argv[0] );
659 build_dll_path();
660 __wine_main_argc = argc;
661 __wine_main_argv = argv;
662 __wine_main_environ = __wine_get_main_environment();
663 mmap_init();
664
665 for (path = first_dll_path( "ntdll.dll", 0, &context ); path; path = next_dll_path( &context ))
666 {
667 if ((ntdll = wine_dlopen( path, RTLD_NOW, error, error_size )))
668 {
669 /* if we didn't use the default dll dir, remove it from the search path */
670 if (default_dlldir[0] && context.index < nb_dll_paths + 2) nb_dll_paths--;
671 break;
672 }
673 }
674 free_dll_path( &context );
675
676 if (!ntdll) return;
677 if (!(init_func = wine_dlsym( ntdll, "__wine_process_init", error, error_size ))) return;
678 init_func();
679}
680
681
682/*
683 * These functions provide wrappers around dlopen() and associated
684 * functions. They work around a bug in glibc 2.1.x where calling
685 * a dl*() function after a previous dl*() function has failed
686 * without a dlerror() call between the two will cause a crash.
687 * They all take a pointer to a buffer that
688 * will receive the error description (from dlerror()). This
689 * parameter may be NULL if the error description is not required.
690 */
691
692#ifndef RTLD_FIRST
693#define RTLD_FIRST 0
694#endif
695
696/***********************************************************************
697 * wine_dlopen
698 */
699void *wine_dlopen( const char *filename, int flag, char *error, size_t errorsize )
700{
701#ifdef HAVE_DLOPEN
702 void *ret;
703 const char *s;
704
705#ifdef __APPLE__
706 /* the Mac OS loader pretends to be able to load PE files, so avoid them here */
707 unsigned char magic[2];
708 int fd = open( filename, O_RDONLY );
709 if (fd != -1)
710 {
711 if (pread( fd, magic, 2, 0 ) == 2 && magic[0] == 'M' && magic[1] == 'Z')
712 {
713 static const char msg[] = "MZ format";
714 size_t len = min( errorsize, sizeof(msg) );
715 memcpy( error, msg, len );
716 error[len - 1] = 0;
717 close( fd );
718 return NULL;
719 }
720 close( fd );
721 }
722#endif
723 dlerror(); dlerror();
724#ifdef __sun
725 if (strchr( filename, ':' ))
726 {
727 char path[PATH_MAX];
728 /* Solaris' brain damaged dlopen() treats ':' as a path separator */
729 realpath( filename, path );
730 ret = dlopen( path, flag | RTLD_FIRST );
731 }
732 else
733#endif
734 ret = dlopen( filename, flag | RTLD_FIRST );
735 s = dlerror();
736 if (error && errorsize)
737 {
738 if (s)
739 {
740 size_t len = strlen(s);
741 if (len >= errorsize) len = errorsize - 1;
742 memcpy( error, s, len );
743 error[len] = 0;
744 }
745 else error[0] = 0;
746 }
747 dlerror();
748 return ret;
749#else
750 if (error)
751 {
752 static const char msg[] = "dlopen interface not detected by configure";
753 size_t len = min( errorsize, sizeof(msg) );
754 memcpy( error, msg, len );
755 error[len - 1] = 0;
756 }
757 return NULL;
758#endif
759}
760
761/***********************************************************************
762 * wine_dlsym
763 */
764void *wine_dlsym( void *handle, const char *symbol, char *error, size_t errorsize )
765{
766#ifdef HAVE_DLOPEN
767 void *ret;
768 const char *s;
769 dlerror(); dlerror();
770 ret = dlsym( handle, symbol );
771 s = dlerror();
772 if (error && errorsize)
773 {
774 if (s)
775 {
776 size_t len = strlen(s);
777 if (len >= errorsize) len = errorsize - 1;
778 memcpy( error, s, len );
779 error[len] = 0;
780 }
781 else error[0] = 0;
782 }
783 dlerror();
784 return ret;
785#else
786 if (error)
787 {
788 static const char msg[] = "dlopen interface not detected by configure";
789 size_t len = min( errorsize, sizeof(msg) );
790 memcpy( error, msg, len );
791 error[len - 1] = 0;
792 }
793 return NULL;
794#endif
795}
796
797/***********************************************************************
798 * wine_dlclose
799 */
800int wine_dlclose( void *handle, char *error, size_t errorsize )
801{
802#ifdef HAVE_DLOPEN
803 int ret;
804 const char *s;
805 dlerror(); dlerror();
806 ret = dlclose( handle );
807 s = dlerror();
808 if (error && errorsize)
809 {
810 if (s)
811 {
812 size_t len = strlen(s);
813 if (len >= errorsize) len = errorsize - 1;
814 memcpy( error, s, len );
815 error[len] = 0;
816 }
817 else error[0] = 0;
818 }
819 dlerror();
820 return ret;
821#else
822 if (error)
823 {
824 static const char msg[] = "dlopen interface not detected by configure";
825 size_t len = min( errorsize, sizeof(msg) );
826 memcpy( error, msg, len );
827 error[len - 1] = 0;
828 }
829 return 1;
830#endif
831}
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