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