winedbg: Get rid of unused mode command.
[wine/multimedia.git] / libs / wine / loader.c
blob5f82c007754694975fa4ed429f3374a6a9c40542
1 /*
2 * Win32 builtin dlls support
4 * Copyright 2000 Alexandre Julliard
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.
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.
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
21 #include "config.h"
22 #include "wine/port.h"
24 #include <assert.h>
25 #include <ctype.h>
26 #include <fcntl.h>
27 #include <stdarg.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <sys/types.h>
31 #ifdef HAVE_SYS_MMAN_H
32 #include <sys/mman.h>
33 #endif
34 #ifdef HAVE_UNISTD_H
35 # include <unistd.h>
36 #endif
38 #define NONAMELESSUNION
39 #define NONAMELESSSTRUCT
40 #include "windef.h"
41 #include "winbase.h"
42 #include "wine/library.h"
44 #ifdef __APPLE__
45 #include <crt_externs.h>
46 #define environ (*_NSGetEnviron())
47 #else
48 extern char **environ;
49 #endif
51 /* argc/argv for the Windows application */
52 int __wine_main_argc = 0;
53 char **__wine_main_argv = NULL;
54 WCHAR **__wine_main_wargv = NULL;
55 char **__wine_main_environ = NULL;
57 struct dll_path_context
59 int index; /* current index in the dll path list */
60 char *buffer; /* buffer used for storing path names */
61 char *name; /* start of file name part in buffer (including leading slash) */
62 int namelen; /* length of file name without .so extension */
65 #define MAX_DLLS 100
67 static struct
69 const IMAGE_NT_HEADERS *nt; /* NT header */
70 const char *filename; /* DLL file name */
71 } builtin_dlls[MAX_DLLS];
73 static int nb_dlls;
75 static const IMAGE_NT_HEADERS *main_exe;
77 static load_dll_callback_t load_dll_callback;
79 static const char *build_dir;
80 static const char *default_dlldir;
81 static const char **dll_paths;
82 static int nb_dll_paths;
83 static int dll_path_maxlen;
85 extern void mmap_init(void);
86 extern void debug_init(void);
87 extern const char *get_dlldir( const char **default_dlldir );
89 /* build the dll load path from the WINEDLLPATH variable */
90 static void build_dll_path(void)
92 int len, count = 0;
93 char *p, *path = getenv( "WINEDLLPATH" );
94 const char *dlldir = get_dlldir( &default_dlldir );
96 if (path)
98 /* count how many path elements we need */
99 path = strdup(path);
100 p = path;
101 while (*p)
103 while (*p == ':') p++;
104 if (!*p) break;
105 count++;
106 while (*p && *p != ':') p++;
110 dll_paths = malloc( (count+2) * sizeof(*dll_paths) );
111 nb_dll_paths = 0;
113 if (dlldir)
115 dll_path_maxlen = strlen(dlldir);
116 dll_paths[nb_dll_paths++] = dlldir;
118 else if ((build_dir = wine_get_build_dir()))
120 dll_path_maxlen = strlen(build_dir) + sizeof("/programs");
123 if (count)
125 p = path;
126 while (*p)
128 while (*p == ':') *p++ = 0;
129 if (!*p) break;
130 dll_paths[nb_dll_paths] = p;
131 while (*p && *p != ':') p++;
132 if (p - dll_paths[nb_dll_paths] > dll_path_maxlen)
133 dll_path_maxlen = p - dll_paths[nb_dll_paths];
134 nb_dll_paths++;
138 /* append default dll dir (if not empty) to path */
139 if ((len = strlen(default_dlldir)) > 0)
141 if (len > dll_path_maxlen) dll_path_maxlen = len;
142 dll_paths[nb_dll_paths++] = default_dlldir;
146 /* check if a given file can be opened */
147 inline static int file_exists( const char *name )
149 int fd = open( name, O_RDONLY );
150 if (fd != -1) close( fd );
151 return (fd != -1);
154 inline static char *prepend( char *buffer, const char *str, size_t len )
156 return memcpy( buffer - len, str, len );
159 /* get a filename from the next entry in the dll path */
160 static char *next_dll_path( struct dll_path_context *context )
162 int index = context->index++;
163 int namelen = context->namelen;
164 char *path = context->name;
166 switch(index)
168 case 0: /* try programs dir for .exe files */
169 if (namelen > 4 && !memcmp( context->name + namelen - 4, ".exe", 4 ))
171 path = prepend( path, context->name, namelen - 4 );
172 path = prepend( path, "/programs", sizeof("/programs") - 1 );
173 path = prepend( path, build_dir, strlen(build_dir) );
174 return path;
176 context->index++;
177 /* fall through */
178 case 1: /* try dlls dir with subdir prefix */
179 if (namelen > 4 && !memcmp( context->name + namelen - 4, ".dll", 4 )) namelen -= 4;
180 path = prepend( path, context->name, namelen );
181 /* fall through */
182 case 2: /* try dlls dir without prefix */
183 path = prepend( path, "/dlls", sizeof("/dlls") - 1 );
184 path = prepend( path, build_dir, strlen(build_dir) );
185 return path;
186 default:
187 index -= 3;
188 if (index < nb_dll_paths)
189 return prepend( context->name, dll_paths[index], strlen( dll_paths[index] ));
190 break;
192 return NULL;
196 /* get a filename from the first entry in the dll path */
197 static char *first_dll_path( const char *name, const char *ext, struct dll_path_context *context )
199 char *p;
200 int namelen = strlen( name );
202 context->buffer = malloc( dll_path_maxlen + 2 * namelen + strlen(ext) + 3 );
203 context->index = build_dir ? 0 : 3; /* if no build dir skip all the build dir magic cases */
204 context->name = context->buffer + dll_path_maxlen + namelen + 1;
205 context->namelen = namelen + 1;
207 /* store the name at the end of the buffer, followed by extension */
208 p = context->name;
209 *p++ = '/';
210 memcpy( p, name, namelen );
211 strcpy( p + namelen, ext );
212 return next_dll_path( context );
216 /* free the dll path context created by first_dll_path */
217 inline static void free_dll_path( struct dll_path_context *context )
219 free( context->buffer );
223 /* open a library for a given dll, searching in the dll path
224 * 'name' must be the Windows dll name (e.g. "kernel32.dll") */
225 static void *dlopen_dll( const char *name, char *error, int errorsize,
226 int test_only, int *exists )
228 struct dll_path_context context;
229 char *path;
230 void *ret = NULL;
232 *exists = 0;
233 for (path = first_dll_path( name, ".so", &context ); path; path = next_dll_path( &context ))
235 if (!test_only && (ret = wine_dlopen( path, RTLD_NOW, error, errorsize ))) break;
236 if ((*exists = file_exists( path ))) break; /* exists but cannot be loaded, return the error */
238 free_dll_path( &context );
239 return ret;
243 /* adjust an array of pointers to make them into RVAs */
244 static inline void fixup_rva_ptrs( void *array, BYTE *base, unsigned int count )
246 void **src = (void **)array;
247 DWORD *dst = (DWORD *)array;
248 while (count--)
250 *dst++ = *src ? (BYTE *)*src - base : 0;
251 src++;
255 /* fixup an array of RVAs by adding the specified delta */
256 static inline void fixup_rva_dwords( DWORD *ptr, int delta, unsigned int count )
258 while (count--)
260 if (*ptr) *ptr += delta;
261 ptr++;
266 /* fixup RVAs in the import directory */
267 static void fixup_imports( IMAGE_IMPORT_DESCRIPTOR *dir, BYTE *base, int delta )
269 UINT_PTR *ptr;
271 while (dir->Name)
273 fixup_rva_dwords( &dir->u.OriginalFirstThunk, delta, 1 );
274 fixup_rva_dwords( &dir->Name, delta, 1 );
275 fixup_rva_dwords( &dir->FirstThunk, delta, 1 );
276 ptr = (UINT_PTR *)(base + dir->FirstThunk);
277 while (*ptr)
279 if (!(*ptr & IMAGE_ORDINAL_FLAG)) *ptr += delta;
280 ptr++;
282 dir++;
287 /* fixup RVAs in the export directory */
288 static void fixup_exports( IMAGE_EXPORT_DIRECTORY *dir, BYTE *base, int delta )
290 fixup_rva_dwords( &dir->Name, delta, 1 );
291 fixup_rva_dwords( &dir->AddressOfFunctions, delta, 1 );
292 fixup_rva_dwords( &dir->AddressOfNames, delta, 1 );
293 fixup_rva_dwords( &dir->AddressOfNameOrdinals, delta, 1 );
294 fixup_rva_dwords( (DWORD *)(base + dir->AddressOfNames), delta, dir->NumberOfNames );
295 fixup_rva_ptrs( (base + dir->AddressOfFunctions), base, dir->NumberOfFunctions );
299 /* fixup RVAs in the resource directory */
300 static void fixup_resources( IMAGE_RESOURCE_DIRECTORY *dir, BYTE *root, int delta )
302 IMAGE_RESOURCE_DIRECTORY_ENTRY *entry;
303 int i;
305 entry = (IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1);
306 for (i = 0; i < dir->NumberOfNamedEntries + dir->NumberOfIdEntries; i++, entry++)
308 void *ptr = root + entry->u2.s3.OffsetToDirectory;
309 if (entry->u2.s3.DataIsDirectory) fixup_resources( ptr, root, delta );
310 else
312 IMAGE_RESOURCE_DATA_ENTRY *data = ptr;
313 fixup_rva_dwords( &data->OffsetToData, delta, 1 );
319 /* map a builtin dll in memory and fixup RVAs */
320 static void *map_dll( const IMAGE_NT_HEADERS *nt_descr )
322 #ifdef HAVE_MMAP
323 IMAGE_DATA_DIRECTORY *dir;
324 IMAGE_DOS_HEADER *dos;
325 IMAGE_NT_HEADERS *nt;
326 IMAGE_SECTION_HEADER *sec;
327 BYTE *addr;
328 DWORD code_start, data_start, data_end;
329 const size_t page_size = getpagesize();
330 const size_t page_mask = page_size - 1;
331 int i, delta, nb_sections = 2; /* code + data */
333 size_t size = (sizeof(IMAGE_DOS_HEADER)
334 + sizeof(IMAGE_NT_HEADERS)
335 + nb_sections * sizeof(IMAGE_SECTION_HEADER));
337 assert( size <= page_size );
339 /* module address must be aligned on 64K boundary */
340 addr = (BYTE *)((nt_descr->OptionalHeader.ImageBase + 0xffff) & ~0xffff);
341 if (wine_anon_mmap( addr, page_size, PROT_READ|PROT_WRITE, MAP_FIXED ) != addr) return NULL;
343 dos = (IMAGE_DOS_HEADER *)addr;
344 nt = (IMAGE_NT_HEADERS *)(dos + 1);
345 sec = (IMAGE_SECTION_HEADER *)(nt + 1);
347 /* Build the DOS and NT headers */
349 dos->e_magic = IMAGE_DOS_SIGNATURE;
350 dos->e_cblp = sizeof(*dos);
351 dos->e_cp = 1;
352 dos->e_cparhdr = (sizeof(*dos)+0xf)/0x10;
353 dos->e_minalloc = 0;
354 dos->e_maxalloc = 0xffff;
355 dos->e_ss = 0x0000;
356 dos->e_sp = 0x00b8;
357 dos->e_lfarlc = sizeof(*dos);
358 dos->e_lfanew = sizeof(*dos);
360 *nt = *nt_descr;
362 delta = (BYTE *)nt_descr - addr;
363 code_start = page_size;
364 data_start = delta & ~page_mask;
365 data_end = (nt->OptionalHeader.SizeOfImage + delta + page_mask) & ~page_mask;
367 fixup_rva_ptrs( &nt->OptionalHeader.AddressOfEntryPoint, addr, 1 );
369 nt->FileHeader.NumberOfSections = nb_sections;
370 nt->OptionalHeader.BaseOfCode = code_start;
371 #ifndef _WIN64
372 nt->OptionalHeader.BaseOfData = data_start;
373 #endif
374 nt->OptionalHeader.SizeOfCode = data_start - code_start;
375 nt->OptionalHeader.SizeOfInitializedData = data_end - data_start;
376 nt->OptionalHeader.SizeOfUninitializedData = 0;
377 nt->OptionalHeader.SizeOfImage = data_end;
378 nt->OptionalHeader.ImageBase = (ULONG_PTR)addr;
380 /* Build the code section */
382 memcpy( sec->Name, ".text", sizeof(".text") );
383 sec->SizeOfRawData = data_start - code_start;
384 sec->Misc.VirtualSize = sec->SizeOfRawData;
385 sec->VirtualAddress = code_start;
386 sec->PointerToRawData = code_start;
387 sec->Characteristics = (IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ);
388 sec++;
390 /* Build the data section */
392 memcpy( sec->Name, ".data", sizeof(".data") );
393 sec->SizeOfRawData = data_end - data_start;
394 sec->Misc.VirtualSize = sec->SizeOfRawData;
395 sec->VirtualAddress = data_start;
396 sec->PointerToRawData = data_start;
397 sec->Characteristics = (IMAGE_SCN_CNT_INITIALIZED_DATA |
398 IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ);
399 sec++;
401 for (i = 0; i < nt->OptionalHeader.NumberOfRvaAndSizes; i++)
402 fixup_rva_dwords( &nt->OptionalHeader.DataDirectory[i].VirtualAddress, delta, 1 );
404 /* Build the import directory */
406 dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_IMPORT_DIRECTORY];
407 if (dir->Size)
409 IMAGE_IMPORT_DESCRIPTOR *imports = (void *)(addr + dir->VirtualAddress);
410 fixup_imports( imports, addr, delta );
413 /* Build the resource directory */
415 dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_RESOURCE_DIRECTORY];
416 if (dir->Size)
418 void *ptr = (void *)(addr + dir->VirtualAddress);
419 fixup_resources( ptr, ptr, delta );
422 /* Build the export directory */
424 dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_EXPORT_DIRECTORY];
425 if (dir->Size)
427 IMAGE_EXPORT_DIRECTORY *exports = (void *)(addr + dir->VirtualAddress);
428 fixup_exports( exports, addr, delta );
430 return addr;
431 #else /* HAVE_MMAP */
432 return NULL;
433 #endif /* HAVE_MMAP */
437 /***********************************************************************
438 * __wine_dll_register
440 * Register a built-in DLL descriptor.
442 void __wine_dll_register( const IMAGE_NT_HEADERS *header, const char *filename )
444 if (load_dll_callback) load_dll_callback( map_dll(header), filename );
445 else
447 if (!(header->FileHeader.Characteristics & IMAGE_FILE_DLL))
448 main_exe = header;
449 else
451 assert( nb_dlls < MAX_DLLS );
452 builtin_dlls[nb_dlls].nt = header;
453 builtin_dlls[nb_dlls].filename = filename;
454 nb_dlls++;
460 /***********************************************************************
461 * wine_dll_set_callback
463 * Set the callback function for dll loading, and call it
464 * for all dlls that were implicitly loaded already.
466 void wine_dll_set_callback( load_dll_callback_t load )
468 int i;
469 load_dll_callback = load;
470 for (i = 0; i < nb_dlls; i++)
472 const IMAGE_NT_HEADERS *nt = builtin_dlls[i].nt;
473 if (!nt) continue;
474 builtin_dlls[i].nt = NULL;
475 load_dll_callback( map_dll(nt), builtin_dlls[i].filename );
477 nb_dlls = 0;
478 if (main_exe) load_dll_callback( map_dll(main_exe), "" );
482 /***********************************************************************
483 * wine_dll_load
485 * Load a builtin dll.
487 void *wine_dll_load( const char *filename, char *error, int errorsize, int *file_exists )
489 int i;
491 /* callback must have been set already */
492 assert( load_dll_callback );
494 /* check if we have it in the list */
495 /* this can happen when initializing pre-loaded dlls in wine_dll_set_callback */
496 for (i = 0; i < nb_dlls; i++)
498 if (!builtin_dlls[i].nt) continue;
499 if (!strcmp( builtin_dlls[i].filename, filename ))
501 const IMAGE_NT_HEADERS *nt = builtin_dlls[i].nt;
502 builtin_dlls[i].nt = NULL;
503 load_dll_callback( map_dll(nt), builtin_dlls[i].filename );
504 *file_exists = 1;
505 return (void *)1;
508 return dlopen_dll( filename, error, errorsize, 0, file_exists );
512 /***********************************************************************
513 * wine_dll_unload
515 * Unload a builtin dll.
517 void wine_dll_unload( void *handle )
519 if (handle != (void *)1)
520 wine_dlclose( handle, NULL, 0 );
524 /***********************************************************************
525 * wine_dll_load_main_exe
527 * Try to load the .so for the main exe.
529 void *wine_dll_load_main_exe( const char *name, char *error, int errorsize,
530 int test_only, int *file_exists )
532 return dlopen_dll( name, error, errorsize, test_only, file_exists );
536 /***********************************************************************
537 * wine_dll_enum_load_path
539 * Enumerate the dll load path.
541 const char *wine_dll_enum_load_path( unsigned int index )
543 if (index >= nb_dll_paths) return NULL;
544 return dll_paths[index];
548 /***********************************************************************
549 * wine_dll_get_owner
551 * Retrieve the name of the 32-bit owner dll for a 16-bit dll.
552 * Return 0 if OK, -1 on error.
554 int wine_dll_get_owner( const char *name, char *buffer, int size, int *exists )
556 int ret = -1;
557 char *path;
558 struct dll_path_context context;
560 *exists = 0;
562 for (path = first_dll_path( name, "16", &context ); path; path = next_dll_path( &context ))
564 int fd = open( path, O_RDONLY );
565 if (fd != -1)
567 int res = read( fd, buffer, size - 1 );
568 while (res > 0 && (buffer[res-1] == '\n' || buffer[res-1] == '\r')) res--;
569 buffer[res] = 0;
570 close( fd );
571 *exists = 1;
572 ret = 0;
573 break;
576 free_dll_path( &context );
577 if (ret != -1) return ret;
579 /* try old method too for backwards compatibility; will be removed later on */
580 for (path = first_dll_path( name, ".so", &context ); path; path = next_dll_path( &context ))
582 int res = readlink( path, buffer, size );
583 if (res != -1) /* got a symlink */
585 *exists = 1;
586 if (res < 4 || res >= size) break;
587 buffer[res] = 0;
588 if (strchr( buffer, '/' )) break; /* contains a path, not valid */
589 if (strcmp( buffer + res - 3, ".so" )) break; /* does not end in .so, not valid */
590 buffer[res - 3] = 0; /* remove .so */
591 ret = 0;
592 break;
594 if ((*exists = file_exists( path ))) break; /* exists but not a symlink, return the error */
596 free_dll_path( &context );
597 return ret;
601 /***********************************************************************
602 * wine_init
604 * Main Wine initialisation.
606 void wine_init( int argc, char *argv[], char *error, int error_size )
608 struct dll_path_context context;
609 char *path;
610 void *ntdll = NULL;
611 void (*init_func)(void);
613 wine_init_argv0_path( argv[0] );
614 build_dll_path();
615 __wine_main_argc = argc;
616 __wine_main_argv = argv;
617 __wine_main_environ = environ;
618 mmap_init();
619 debug_init();
621 for (path = first_dll_path( "ntdll.dll", ".so", &context ); path; path = next_dll_path( &context ))
623 if ((ntdll = wine_dlopen( path, RTLD_NOW, error, error_size )))
625 /* if we didn't use the default dll dir, remove it from the search path */
626 if (default_dlldir[0] && context.index < nb_dll_paths) nb_dll_paths--;
627 break;
630 free_dll_path( &context );
632 if (!ntdll) return;
633 if (!(init_func = wine_dlsym( ntdll, "__wine_process_init", error, error_size ))) return;
634 init_func();
639 * These functions provide wrappers around dlopen() and associated
640 * functions. They work around a bug in glibc 2.1.x where calling
641 * a dl*() function after a previous dl*() function has failed
642 * without a dlerror() call between the two will cause a crash.
643 * They all take a pointer to a buffer that
644 * will receive the error description (from dlerror()). This
645 * parameter may be NULL if the error description is not required.
648 #ifndef RTLD_FIRST
649 #define RTLD_FIRST 0
650 #endif
652 /***********************************************************************
653 * wine_dlopen
655 void *wine_dlopen( const char *filename, int flag, char *error, size_t errorsize )
657 #ifdef HAVE_DLOPEN
658 void *ret;
659 const char *s;
660 dlerror(); dlerror();
661 ret = dlopen( filename, flag | RTLD_FIRST );
662 s = dlerror();
663 if (error && errorsize)
665 if (s)
667 size_t len = strlen(s);
668 if (len >= errorsize) len = errorsize - 1;
669 memcpy( error, s, len );
670 error[len] = 0;
672 else error[0] = 0;
674 dlerror();
675 return ret;
676 #else
677 if (error)
679 static const char msg[] = "dlopen interface not detected by configure";
680 size_t len = min( errorsize, sizeof(msg) );
681 memcpy( error, msg, len );
682 error[len - 1] = 0;
684 return NULL;
685 #endif
688 /***********************************************************************
689 * wine_dlsym
691 void *wine_dlsym( void *handle, const char *symbol, char *error, size_t errorsize )
693 #ifdef HAVE_DLOPEN
694 void *ret;
695 const char *s;
696 dlerror(); dlerror();
697 ret = dlsym( handle, symbol );
698 s = dlerror();
699 if (error && errorsize)
701 if (s)
703 size_t len = strlen(s);
704 if (len >= errorsize) len = errorsize - 1;
705 memcpy( error, s, len );
706 error[len] = 0;
708 else error[0] = 0;
710 dlerror();
711 return ret;
712 #else
713 if (error)
715 static const char msg[] = "dlopen interface not detected by configure";
716 size_t len = min( errorsize, sizeof(msg) );
717 memcpy( error, msg, len );
718 error[len - 1] = 0;
720 return NULL;
721 #endif
724 /***********************************************************************
725 * wine_dlclose
727 int wine_dlclose( void *handle, char *error, size_t errorsize )
729 #ifdef HAVE_DLOPEN
730 int ret;
731 const char *s;
732 dlerror(); dlerror();
733 ret = dlclose( handle );
734 s = dlerror();
735 if (error && errorsize)
737 if (s)
739 size_t len = strlen(s);
740 if (len >= errorsize) len = errorsize - 1;
741 memcpy( error, s, len );
742 error[len] = 0;
744 else error[0] = 0;
746 dlerror();
747 return ret;
748 #else
749 if (error)
751 static const char msg[] = "dlopen interface not detected by configure";
752 size_t len = min( errorsize, sizeof(msg) );
753 memcpy( error, msg, len );
754 error[len - 1] = 0;
756 return 1;
757 #endif