ntdll: Move the keyed event functions to the Unix library.
[wine.git] / dlls / ntdll / unix / loader.c
blob0e93978993f31583e39dbc63f12001c87d08e16b
1 /*
2 * Unix interface for loader functions
4 * Copyright (C) 2020 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 #if 0
22 #pragma makedep unix
23 #endif
25 #include "config.h"
26 #include "wine/port.h"
28 #include <assert.h>
29 #include <errno.h>
30 #include <locale.h>
31 #include <langinfo.h>
32 #include <stdarg.h>
33 #include <stdio.h>
34 #include <signal.h>
35 #ifdef HAVE_PWD_H
36 # include <pwd.h>
37 #endif
38 #ifdef HAVE_SYS_MMAN_H
39 # include <sys/mman.h>
40 #endif
41 #ifdef HAVE_SYS_PRCTL_H
42 # include <sys/prctl.h>
43 #endif
44 #ifdef HAVE_SYS_RESOURCE_H
45 # include <sys/resource.h>
46 #endif
47 #ifdef HAVE_SYS_UTSNAME_H
48 #include <sys/utsname.h>
49 #endif
50 #ifdef HAVE_SYS_WAIT_H
51 #include <sys/wait.h>
52 #endif
53 #ifdef __APPLE__
54 # include <CoreFoundation/CoreFoundation.h>
55 # define LoadResource MacLoadResource
56 # define GetCurrentThread MacGetCurrentThread
57 # include <CoreServices/CoreServices.h>
58 # undef LoadResource
59 # undef GetCurrentThread
60 # include <pthread.h>
61 # include <mach-o/getsect.h>
62 # include <crt_externs.h>
63 # include <spawn.h>
64 # ifndef _POSIX_SPAWN_DISABLE_ASLR
65 # define _POSIX_SPAWN_DISABLE_ASLR 0x0100
66 # endif
67 #endif
69 #include "ntstatus.h"
70 #define WIN32_NO_STATUS
71 #define NONAMELESSUNION
72 #define NONAMELESSSTRUCT
73 #include "windef.h"
74 #include "winnt.h"
75 #include "winbase.h"
76 #include "winnls.h"
77 #include "winternl.h"
78 #include "unix_private.h"
79 #include "wine/library.h"
80 #include "wine/debug.h"
82 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
84 extern IMAGE_NT_HEADERS __wine_spec_nt_header;
85 extern void CDECL __wine_set_unix_funcs( int version, const struct unix_funcs *funcs );
87 #ifdef __GNUC__
88 static void fatal_error( const char *err, ... ) __attribute__((noreturn, format(printf,1,2)));
89 #endif
91 extern int __wine_main_argc;
92 extern char **__wine_main_argv;
93 extern char **__wine_main_environ;
95 #if defined(linux) || defined(__APPLE__)
96 static const BOOL use_preloader = TRUE;
97 #else
98 static const BOOL use_preloader = FALSE;
99 #endif
101 static const BOOL is_win64 = (sizeof(void *) > sizeof(int));
103 static int main_argc;
104 static char **main_argv;
105 static char **main_envp;
106 static char *argv0;
107 static const char *bin_dir;
108 static const char *dll_dir;
109 static const char **dll_paths;
110 static SIZE_T dll_path_maxlen;
112 const char *data_dir = NULL;
113 const char *build_dir = NULL;
114 const char *config_dir = NULL;
116 static CPTABLEINFO unix_table;
118 static inline void *get_rva( const IMAGE_NT_HEADERS *nt, ULONG_PTR addr )
120 return (BYTE *)nt + addr;
123 /* adjust an array of pointers to make them into RVAs */
124 static inline void fixup_rva_ptrs( void *array, BYTE *base, unsigned int count )
126 BYTE **src = array;
127 DWORD *dst = array;
129 for ( ; count; count--, src++, dst++) *dst = *src ? *src - base : 0;
132 /* fixup an array of RVAs by adding the specified delta */
133 static inline void fixup_rva_dwords( DWORD *ptr, int delta, unsigned int count )
135 for ( ; count; count--, ptr++) if (*ptr) *ptr += delta;
139 /* fixup an array of name/ordinal RVAs by adding the specified delta */
140 static inline void fixup_rva_names( UINT_PTR *ptr, int delta )
142 for ( ; *ptr; ptr++) if (!(*ptr & IMAGE_ORDINAL_FLAG)) *ptr += delta;
146 /* fixup RVAs in the resource directory */
147 static void fixup_so_resources( IMAGE_RESOURCE_DIRECTORY *dir, BYTE *root, int delta )
149 IMAGE_RESOURCE_DIRECTORY_ENTRY *entry = (IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1);
150 unsigned int i;
152 for (i = 0; i < dir->NumberOfNamedEntries + dir->NumberOfIdEntries; i++, entry++)
154 void *ptr = root + entry->u2.s2.OffsetToDirectory;
155 if (entry->u2.s2.DataIsDirectory) fixup_so_resources( ptr, root, delta );
156 else fixup_rva_dwords( &((IMAGE_RESOURCE_DATA_ENTRY *)ptr)->OffsetToData, delta, 1 );
160 /* die on a fatal error; use only during initialization */
161 static void fatal_error( const char *err, ... )
163 va_list args;
165 va_start( args, err );
166 fprintf( stderr, "wine: " );
167 vfprintf( stderr, err, args );
168 va_end( args );
169 exit(1);
172 static void set_max_limit( int limit )
174 struct rlimit rlimit;
176 if (!getrlimit( limit, &rlimit ))
178 rlimit.rlim_cur = rlimit.rlim_max;
179 setrlimit( limit, &rlimit );
183 /* canonicalize path and return its directory name */
184 static char *realpath_dirname( const char *name )
186 char *p, *fullpath = realpath( name, NULL );
188 if (fullpath)
190 p = strrchr( fullpath, '/' );
191 if (p == fullpath) p++;
192 if (p) *p = 0;
194 return fullpath;
197 /* if string ends with tail, remove it */
198 static char *remove_tail( const char *str, const char *tail )
200 size_t len = strlen( str );
201 size_t tail_len = strlen( tail );
202 char *ret;
204 if (len < tail_len) return NULL;
205 if (strcmp( str + len - tail_len, tail )) return NULL;
206 ret = malloc( len - tail_len + 1 );
207 memcpy( ret, str, len - tail_len );
208 ret[len - tail_len] = 0;
209 return ret;
212 /* build a path from the specified dir and name */
213 static char *build_path( const char *dir, const char *name )
215 size_t len = strlen( dir );
216 char *ret = malloc( len + strlen( name ) + 2 );
218 memcpy( ret, dir, len );
219 if (len && ret[len - 1] != '/') ret[len++] = '/';
220 strcpy( ret + len, name );
221 return ret;
224 static void set_dll_path(void)
226 char *p, *path = getenv( "WINEDLLPATH" );
227 int i, count = 0;
229 if (path) for (p = path, count = 1; *p; p++) if (*p == ':') count++;
231 dll_paths = malloc( (count + 2) * sizeof(*dll_paths) );
232 count = 0;
234 if (!build_dir) dll_paths[count++] = dll_dir;
236 if (path)
238 path = strdup(path);
239 for (p = strtok( path, ":" ); p; p = strtok( NULL, ":" )) dll_paths[count++] = strdup( p );
240 free( path );
243 for (i = 0; i < count; i++) dll_path_maxlen = max( dll_path_maxlen, strlen(dll_paths[i]) );
244 dll_paths[count] = NULL;
248 static void set_config_dir(void)
250 char *p, *dir;
251 const char *prefix = getenv( "WINEPREFIX" );
253 if (prefix)
255 if (prefix[0] != '/')
256 fatal_error( "invalid directory %s in WINEPREFIX: not an absolute path\n", prefix );
257 config_dir = dir = strdup( prefix );
258 for (p = dir + strlen(dir) - 1; p > dir && *p == '/'; p--) *p = 0;
260 else
262 const char *home = getenv( "HOME" );
263 if (!home)
265 struct passwd *pwd = getpwuid( getuid() );
266 if (pwd) home = pwd->pw_dir;
268 if (!home) fatal_error( "could not determine your home directory\n" );
269 if (home[0] != '/') fatal_error( "your home directory %s is not an absolute path\n", home );
270 config_dir = build_path( home, ".wine" );
274 static void init_paths( int argc, char *argv[], char *envp[] )
276 Dl_info info;
278 __wine_main_argc = main_argc = argc;
279 __wine_main_argv = main_argv = argv;
280 __wine_main_environ = main_envp = envp;
281 argv0 = strdup( argv[0] );
283 if (!dladdr( init_paths, &info ) || !(dll_dir = realpath_dirname( info.dli_fname )))
284 fatal_error( "cannot get path to ntdll.so\n" );
286 if (!(build_dir = remove_tail( dll_dir, "/dlls/ntdll" )))
288 #if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__)
289 bin_dir = realpath_dirname( "/proc/self/exe" );
290 #elif defined (__FreeBSD__) || defined(__DragonFly__)
291 bin_dir = realpath_dirname( "/proc/curproc/file" );
292 #else
293 bin_dir = realpath_dirname( argv0 );
294 #endif
295 if (!bin_dir) bin_dir = build_path( dll_dir, DLL_TO_BINDIR );
296 data_dir = build_path( bin_dir, BIN_TO_DATADIR );
299 set_dll_path();
300 set_config_dir();
303 #if !defined(__APPLE__) && !defined(__ANDROID__) /* these platforms always use UTF-8 */
305 /* charset to codepage map, sorted by name */
306 static const struct { const char *name; UINT cp; } charset_names[] =
308 { "ANSIX341968", 20127 },
309 { "BIG5", 950 },
310 { "BIG5HKSCS", 950 },
311 { "CP1250", 1250 },
312 { "CP1251", 1251 },
313 { "CP1252", 1252 },
314 { "CP1253", 1253 },
315 { "CP1254", 1254 },
316 { "CP1255", 1255 },
317 { "CP1256", 1256 },
318 { "CP1257", 1257 },
319 { "CP1258", 1258 },
320 { "CP932", 932 },
321 { "CP936", 936 },
322 { "CP949", 949 },
323 { "CP950", 950 },
324 { "EUCJP", 20932 },
325 { "EUCKR", 949 },
326 { "GB18030", 936 /* 54936 */ },
327 { "GB2312", 936 },
328 { "GBK", 936 },
329 { "IBM037", 37 },
330 { "IBM1026", 1026 },
331 { "IBM424", 20424 },
332 { "IBM437", 437 },
333 { "IBM500", 500 },
334 { "IBM850", 850 },
335 { "IBM852", 852 },
336 { "IBM855", 855 },
337 { "IBM857", 857 },
338 { "IBM860", 860 },
339 { "IBM861", 861 },
340 { "IBM862", 862 },
341 { "IBM863", 863 },
342 { "IBM864", 864 },
343 { "IBM865", 865 },
344 { "IBM866", 866 },
345 { "IBM869", 869 },
346 { "IBM874", 874 },
347 { "IBM875", 875 },
348 { "ISO88591", 28591 },
349 { "ISO885913", 28603 },
350 { "ISO885915", 28605 },
351 { "ISO88592", 28592 },
352 { "ISO88593", 28593 },
353 { "ISO88594", 28594 },
354 { "ISO88595", 28595 },
355 { "ISO88596", 28596 },
356 { "ISO88597", 28597 },
357 { "ISO88598", 28598 },
358 { "ISO88599", 28599 },
359 { "KOI8R", 20866 },
360 { "KOI8U", 21866 },
361 { "TIS620", 28601 },
362 { "UTF8", CP_UTF8 }
365 static void load_unix_cptable( unsigned int cp )
367 const char *dir = build_dir ? build_dir : data_dir;
368 struct stat st;
369 char *name;
370 void *data;
371 int fd;
373 if (!(name = malloc( strlen(dir) + 22 ))) return;
374 sprintf( name, "%s/nls/c_%03u.nls", dir, cp );
375 if ((fd = open( name, O_RDONLY )) != -1)
377 fstat( fd, &st );
378 if ((data = malloc( st.st_size )) && st.st_size > 0x10000 &&
379 read( fd, data, st.st_size ) == st.st_size)
381 RtlInitCodePageTable( data, &unix_table );
383 else
385 free( data );
387 close( fd );
389 else ERR( "failed to load %s\n", name );
390 free( name );
393 static void init_unix_codepage(void)
395 char charset_name[16];
396 const char *name;
397 size_t i, j;
398 int min = 0, max = ARRAY_SIZE(charset_names) - 1;
400 setlocale( LC_CTYPE, "" );
401 if (!(name = nl_langinfo( CODESET ))) return;
403 /* remove punctuation characters from charset name */
404 for (i = j = 0; name[i] && j < sizeof(charset_name)-1; i++)
406 if (name[i] >= '0' && name[i] <= '9') charset_name[j++] = name[i];
407 else if (name[i] >= 'A' && name[i] <= 'Z') charset_name[j++] = name[i];
408 else if (name[i] >= 'a' && name[i] <= 'z') charset_name[j++] = name[i] + ('A' - 'a');
410 charset_name[j] = 0;
412 while (min <= max)
414 int pos = (min + max) / 2;
415 int res = strcmp( charset_names[pos].name, charset_name );
416 if (!res)
418 if (charset_names[pos].cp != CP_UTF8) load_unix_cptable( charset_names[pos].cp );
419 return;
421 if (res > 0) max = pos - 1;
422 else min = pos + 1;
424 ERR( "unrecognized charset '%s'\n", name );
427 #else /* __APPLE__ || __ANDROID__ */
429 static void init_unix_codepage(void) { }
431 #endif /* __APPLE__ || __ANDROID__ */
434 /*********************************************************************
435 * get_version
437 const char * CDECL get_version(void)
439 return PACKAGE_VERSION;
443 /*********************************************************************
444 * get_build_id
446 const char * CDECL get_build_id(void)
448 extern const char wine_build[];
449 return wine_build;
453 /*********************************************************************
454 * get_host_version
456 void CDECL get_host_version( const char **sysname, const char **release )
458 #ifdef HAVE_SYS_UTSNAME_H
459 static struct utsname buf;
460 static BOOL init_done;
462 if (!init_done)
464 uname( &buf );
465 init_done = TRUE;
467 if (sysname) *sysname = buf.sysname;
468 if (release) *release = buf.release;
469 #else
470 if (sysname) *sysname = "";
471 if (release) *release = "";
472 #endif
476 /*************************************************************************
477 * get_main_args
479 * Return the initial arguments.
481 static void CDECL get_main_args( int *argc, char **argv[], char **envp[] )
483 *argc = main_argc;
484 *argv = main_argv;
485 *envp = main_envp;
489 /*************************************************************************
490 * get_paths
492 * Return the various configuration paths.
494 static void CDECL get_paths( const char **builddir, const char **datadir, const char **configdir )
496 *builddir = build_dir;
497 *datadir = data_dir;
498 *configdir = config_dir;
502 /*************************************************************************
503 * get_dll_path
505 * Return the various configuration paths.
507 static void CDECL get_dll_path( const char ***paths, SIZE_T *maxlen )
509 *paths = dll_paths;
510 *maxlen = dll_path_maxlen;
514 /*************************************************************************
515 * get_unix_codepage
517 * Return the Unix codepage data.
519 static void CDECL get_unix_codepage( CPTABLEINFO *table )
521 *table = unix_table;
525 static void preloader_exec( char **argv )
527 if (use_preloader)
529 static const char *preloader = "wine-preloader";
530 char *p;
532 if (!(p = strrchr( argv[1], '/' ))) p = argv[1];
533 else p++;
535 if (strlen(p) > 2 && !strcmp( p + strlen(p) - 2, "64" )) preloader = "wine64-preloader";
536 argv[0] = malloc( p - argv[1] + strlen(preloader) + 1 );
537 memcpy( argv[0], argv[1], p - argv[1] );
538 strcpy( argv[0] + (p - argv[1]), preloader );
540 #ifdef __APPLE__
542 posix_spawnattr_t attr;
543 posix_spawnattr_init( &attr );
544 posix_spawnattr_setflags( &attr, POSIX_SPAWN_SETEXEC | _POSIX_SPAWN_DISABLE_ASLR );
545 posix_spawn( NULL, argv[0], NULL, &attr, argv, *_NSGetEnviron() );
546 posix_spawnattr_destroy( &attr );
548 #endif
549 execv( argv[0], argv );
550 free( argv[0] );
552 execv( argv[1], argv + 1 );
555 static NTSTATUS loader_exec( const char *loader, char **argv, int is_child_64bit )
557 char *p, *path;
559 if (build_dir)
561 argv[1] = build_path( build_dir, is_child_64bit ? "loader/wine64" : "loader/wine" );
562 preloader_exec( argv );
563 return STATUS_INVALID_IMAGE_FORMAT;
566 if ((p = strrchr( loader, '/' ))) loader = p + 1;
568 argv[1] = build_path( bin_dir, loader );
569 preloader_exec( argv );
571 argv[1] = getenv( "WINELOADER" );
572 if (argv[1]) preloader_exec( argv );
574 if ((path = getenv( "PATH" )))
576 for (p = strtok( strdup( path ), ":" ); p; p = strtok( NULL, ":" ))
578 argv[1] = build_path( p, loader );
579 preloader_exec( argv );
583 argv[1] = build_path( BINDIR, loader );
584 preloader_exec( argv );
585 return STATUS_INVALID_IMAGE_FORMAT;
589 /***********************************************************************
590 * exec_wineloader
592 * argv[0] and argv[1] must be reserved for the preloader and loader respectively.
594 static NTSTATUS CDECL exec_wineloader( char **argv, int socketfd, int is_child_64bit,
595 ULONGLONG res_start, ULONGLONG res_end )
597 const char *loader = argv0;
598 const char *loader_env = getenv( "WINELOADER" );
599 char preloader_reserve[64], socket_env[64];
601 if (!is_win64 ^ !is_child_64bit)
603 /* remap WINELOADER to the alternate 32/64-bit version if necessary */
604 if (loader_env)
606 int len = strlen( loader_env );
607 char *env = malloc( sizeof("WINELOADER=") + len + 2 );
609 if (!env) return STATUS_NO_MEMORY;
610 strcpy( env, "WINELOADER=" );
611 strcat( env, loader_env );
612 if (is_child_64bit)
614 strcat( env, "64" );
616 else
618 len += sizeof("WINELOADER=") - 1;
619 if (!strcmp( env + len - 2, "64" )) env[len - 2] = 0;
621 loader = env;
622 putenv( env );
624 else loader = is_child_64bit ? "wine64" : "wine";
627 signal( SIGPIPE, SIG_DFL );
629 sprintf( socket_env, "WINESERVERSOCKET=%u", socketfd );
630 sprintf( preloader_reserve, "WINEPRELOADRESERVE=%x%08x-%x%08x",
631 (ULONG)(res_start >> 32), (ULONG)res_start, (ULONG)(res_end >> 32), (ULONG)res_end );
633 putenv( preloader_reserve );
634 putenv( socket_env );
636 return loader_exec( loader, argv, is_child_64bit );
640 /***********************************************************************
641 * exec_wineserver
643 * Exec a new wine server.
645 static void exec_wineserver( char **argv )
647 char *path;
649 if (build_dir)
651 if (!is_win64) /* look for 64-bit server */
653 char *loader = realpath_dirname( build_path( build_dir, "loader/wine64" ));
654 if (loader)
656 argv[0] = build_path( loader, "../server/wineserver" );
657 execv( argv[0], argv );
660 argv[0] = build_path( build_dir, "server/wineserver" );
661 execv( argv[0], argv );
662 return;
665 argv[0] = build_path( bin_dir, "wineserver" );
666 execv( argv[0], argv );
668 argv[0] = getenv( "WINESERVER" );
669 if (argv[0]) execv( argv[0], argv );
671 if ((path = getenv( "PATH" )))
673 for (path = strtok( strdup( path ), ":" ); path; path = strtok( NULL, ":" ))
675 argv[0] = build_path( path, "wineserver" );
676 execvp( argv[0], argv );
680 argv[0] = build_path( BINDIR, "wineserver" );
681 execv( argv[0], argv );
685 /***********************************************************************
686 * start_server
688 * Start a new wine server.
690 void start_server( BOOL debug )
692 static BOOL started; /* we only try once */
693 char *argv[3];
694 static char debug_flag[] = "-d";
696 if (!started)
698 int status;
699 int pid = fork();
700 if (pid == -1) fatal_error( "fork: %s", strerror(errno) );
701 if (!pid)
703 argv[1] = debug ? debug_flag : NULL;
704 argv[2] = NULL;
705 exec_wineserver( argv );
706 fatal_error( "could not exec wineserver\n" );
708 waitpid( pid, &status, 0 );
709 status = WIFEXITED(status) ? WEXITSTATUS(status) : 1;
710 if (status == 2) return; /* server lock held by someone else, will retry later */
711 if (status) exit(status); /* server failed */
712 started = TRUE;
717 /*************************************************************************
718 * map_so_dll
720 * Map a builtin dll in memory and fixup RVAs.
722 static NTSTATUS CDECL map_so_dll( const IMAGE_NT_HEADERS *nt_descr, HMODULE module )
724 static const char builtin_signature[32] = "Wine builtin DLL";
725 IMAGE_DATA_DIRECTORY *dir;
726 IMAGE_DOS_HEADER *dos;
727 IMAGE_NT_HEADERS *nt;
728 IMAGE_SECTION_HEADER *sec;
729 BYTE *addr = (BYTE *)module;
730 DWORD code_start, code_end, data_start, data_end, align_mask;
731 int delta, nb_sections = 2; /* code + data */
732 unsigned int i;
733 DWORD size = (sizeof(IMAGE_DOS_HEADER)
734 + sizeof(builtin_signature)
735 + sizeof(IMAGE_NT_HEADERS)
736 + nb_sections * sizeof(IMAGE_SECTION_HEADER));
738 if (wine_anon_mmap( addr, size, PROT_READ | PROT_WRITE, MAP_FIXED ) != addr) return STATUS_NO_MEMORY;
740 dos = (IMAGE_DOS_HEADER *)addr;
741 nt = (IMAGE_NT_HEADERS *)((BYTE *)(dos + 1) + sizeof(builtin_signature));
742 sec = (IMAGE_SECTION_HEADER *)(nt + 1);
744 /* build the DOS and NT headers */
746 dos->e_magic = IMAGE_DOS_SIGNATURE;
747 dos->e_cblp = 0x90;
748 dos->e_cp = 3;
749 dos->e_cparhdr = (sizeof(*dos) + 0xf) / 0x10;
750 dos->e_minalloc = 0;
751 dos->e_maxalloc = 0xffff;
752 dos->e_ss = 0x0000;
753 dos->e_sp = 0x00b8;
754 dos->e_lfanew = sizeof(*dos) + sizeof(builtin_signature);
756 *nt = *nt_descr;
758 delta = (const BYTE *)nt_descr - addr;
759 align_mask = nt->OptionalHeader.SectionAlignment - 1;
760 code_start = (size + align_mask) & ~align_mask;
761 data_start = delta & ~align_mask;
762 #ifdef __APPLE__
764 Dl_info dli;
765 unsigned long data_size;
766 /* need the mach_header, not the PE header, to give to getsegmentdata(3) */
767 dladdr(addr, &dli);
768 code_end = getsegmentdata(dli.dli_fbase, "__DATA", &data_size) - addr;
769 data_end = (code_end + data_size + align_mask) & ~align_mask;
771 #else
772 code_end = data_start;
773 data_end = (nt->OptionalHeader.SizeOfImage + delta + align_mask) & ~align_mask;
774 #endif
776 fixup_rva_ptrs( &nt->OptionalHeader.AddressOfEntryPoint, addr, 1 );
778 nt->FileHeader.NumberOfSections = nb_sections;
779 nt->OptionalHeader.BaseOfCode = code_start;
780 #ifndef _WIN64
781 nt->OptionalHeader.BaseOfData = data_start;
782 #endif
783 nt->OptionalHeader.SizeOfCode = code_end - code_start;
784 nt->OptionalHeader.SizeOfInitializedData = data_end - data_start;
785 nt->OptionalHeader.SizeOfUninitializedData = 0;
786 nt->OptionalHeader.SizeOfImage = data_end;
787 nt->OptionalHeader.ImageBase = (ULONG_PTR)addr;
789 /* build the code section */
791 memcpy( sec->Name, ".text", sizeof(".text") );
792 sec->SizeOfRawData = code_end - code_start;
793 sec->Misc.VirtualSize = sec->SizeOfRawData;
794 sec->VirtualAddress = code_start;
795 sec->PointerToRawData = code_start;
796 sec->Characteristics = (IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ);
797 sec++;
799 /* build the data section */
801 memcpy( sec->Name, ".data", sizeof(".data") );
802 sec->SizeOfRawData = data_end - data_start;
803 sec->Misc.VirtualSize = sec->SizeOfRawData;
804 sec->VirtualAddress = data_start;
805 sec->PointerToRawData = data_start;
806 sec->Characteristics = (IMAGE_SCN_CNT_INITIALIZED_DATA |
807 IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ);
808 sec++;
810 for (i = 0; i < nt->OptionalHeader.NumberOfRvaAndSizes; i++)
811 fixup_rva_dwords( &nt->OptionalHeader.DataDirectory[i].VirtualAddress, delta, 1 );
813 /* build the import directory */
815 dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_IMPORT_DIRECTORY];
816 if (dir->Size)
818 IMAGE_IMPORT_DESCRIPTOR *imports = (IMAGE_IMPORT_DESCRIPTOR *)(addr + dir->VirtualAddress);
820 while (imports->Name)
822 fixup_rva_dwords( &imports->u.OriginalFirstThunk, delta, 1 );
823 fixup_rva_dwords( &imports->Name, delta, 1 );
824 fixup_rva_dwords( &imports->FirstThunk, delta, 1 );
825 if (imports->u.OriginalFirstThunk)
826 fixup_rva_names( (UINT_PTR *)(addr + imports->u.OriginalFirstThunk), delta );
827 if (imports->FirstThunk)
828 fixup_rva_names( (UINT_PTR *)(addr + imports->FirstThunk), delta );
829 imports++;
833 /* build the resource directory */
835 dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_RESOURCE_DIRECTORY];
836 if (dir->Size)
838 void *ptr = addr + dir->VirtualAddress;
839 fixup_so_resources( ptr, ptr, delta );
842 /* build the export directory */
844 dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_EXPORT_DIRECTORY];
845 if (dir->Size)
847 IMAGE_EXPORT_DIRECTORY *exports = (IMAGE_EXPORT_DIRECTORY *)(addr + dir->VirtualAddress);
849 fixup_rva_dwords( &exports->Name, delta, 1 );
850 fixup_rva_dwords( &exports->AddressOfFunctions, delta, 1 );
851 fixup_rva_dwords( &exports->AddressOfNames, delta, 1 );
852 fixup_rva_dwords( &exports->AddressOfNameOrdinals, delta, 1 );
853 fixup_rva_dwords( (DWORD *)(addr + exports->AddressOfNames), delta, exports->NumberOfNames );
854 fixup_rva_ptrs( addr + exports->AddressOfFunctions, addr, exports->NumberOfFunctions );
856 return STATUS_SUCCESS;
859 static const IMAGE_EXPORT_DIRECTORY *get_export_dir( HMODULE module )
861 const IMAGE_DOS_HEADER *dos = (const IMAGE_DOS_HEADER *)module;
862 const IMAGE_NT_HEADERS *nt;
863 DWORD addr;
865 if (dos->e_magic != IMAGE_DOS_SIGNATURE) return NULL;
866 nt = (IMAGE_NT_HEADERS *)((const BYTE *)dos + dos->e_lfanew);
867 if (nt->Signature != IMAGE_NT_SIGNATURE) return NULL;
868 addr = nt->OptionalHeader.DataDirectory[IMAGE_FILE_EXPORT_DIRECTORY].VirtualAddress;
869 if (!addr) return NULL;
870 return (IMAGE_EXPORT_DIRECTORY *)((BYTE *)module + addr);
873 static ULONG_PTR find_ordinal_export( HMODULE module, const IMAGE_EXPORT_DIRECTORY *exports, DWORD ordinal )
875 const DWORD *functions = (const DWORD *)((BYTE *)module + exports->AddressOfFunctions);
877 if (ordinal >= exports->NumberOfFunctions) return 0;
878 if (!functions[ordinal]) return 0;
879 return (ULONG_PTR)module + functions[ordinal];
882 static ULONG_PTR find_named_export( HMODULE module, const IMAGE_EXPORT_DIRECTORY *exports,
883 const IMAGE_IMPORT_BY_NAME *name )
885 const WORD *ordinals = (const WORD *)((BYTE *)module + exports->AddressOfNameOrdinals);
886 const DWORD *names = (const DWORD *)((BYTE *)module + exports->AddressOfNames);
887 int min = 0, max = exports->NumberOfNames - 1;
889 /* first check the hint */
890 if (name->Hint <= max)
892 char *ename = (char *)module + names[name->Hint];
893 if (!strcmp( ename, (char *)name->Name ))
894 return find_ordinal_export( module, exports, ordinals[name->Hint] );
897 /* then do a binary search */
898 while (min <= max)
900 int res, pos = (min + max) / 2;
901 char *ename = (char *)module + names[pos];
902 if (!(res = strcmp( ename, (char *)name->Name )))
903 return find_ordinal_export( module, exports, ordinals[pos] );
904 if (res > 0) max = pos - 1;
905 else min = pos + 1;
907 return 0;
910 static void fixup_ntdll_imports( const IMAGE_NT_HEADERS *nt, HMODULE ntdll_module )
912 const IMAGE_EXPORT_DIRECTORY *ntdll_exports = get_export_dir( ntdll_module );
913 const IMAGE_IMPORT_DESCRIPTOR *descr;
914 const IMAGE_THUNK_DATA *import_list;
915 IMAGE_THUNK_DATA *thunk_list;
917 assert( ntdll_exports );
919 descr = get_rva( nt, nt->OptionalHeader.DataDirectory[IMAGE_FILE_IMPORT_DIRECTORY].VirtualAddress );
920 while (descr->Name)
922 /* ntdll must be the only import */
923 assert( !strcmp( get_rva( nt, descr->Name ), "ntdll.dll" ));
925 thunk_list = get_rva( nt, (DWORD)descr->FirstThunk );
926 if (descr->u.OriginalFirstThunk)
927 import_list = get_rva( nt, (DWORD)descr->u.OriginalFirstThunk );
928 else
929 import_list = thunk_list;
932 while (import_list->u1.Ordinal)
934 if (IMAGE_SNAP_BY_ORDINAL( import_list->u1.Ordinal ))
936 int ordinal = IMAGE_ORDINAL( import_list->u1.Ordinal ) - ntdll_exports->Base;
937 thunk_list->u1.Function = find_ordinal_export( ntdll_module, ntdll_exports, ordinal );
938 if (!thunk_list->u1.Function) ERR( "ordinal %u not found\n", ordinal );
940 else /* import by name */
942 IMAGE_IMPORT_BY_NAME *pe_name = get_rva( nt, import_list->u1.AddressOfData );
943 thunk_list->u1.Function = find_named_export( ntdll_module, ntdll_exports, pe_name );
944 if (!thunk_list->u1.Function) ERR( "%s not found\n", pe_name->Name );
946 import_list++;
947 thunk_list++;
950 descr++;
954 /***********************************************************************
955 * load_ntdll
957 static HMODULE load_ntdll(void)
959 const IMAGE_NT_HEADERS *nt;
960 HMODULE module;
961 Dl_info info;
962 char *name;
963 void *handle;
965 name = build_path( dll_dir, "ntdll.dll.so" );
966 if (!dladdr( load_ntdll, &info )) fatal_error( "cannot get path to ntdll.so\n" );
967 name = malloc( strlen(info.dli_fname) + 5 );
968 strcpy( name, info.dli_fname );
969 strcpy( name + strlen(info.dli_fname) - 3, ".dll.so" );
970 if (!(handle = dlopen( name, RTLD_NOW ))) fatal_error( "failed to load %s: %s\n", name, dlerror() );
971 if (!(nt = dlsym( handle, "__wine_spec_nt_header" )))
972 fatal_error( "NT header not found in %s (too old?)\n", name );
973 dll_dir = realpath_dirname( name );
974 free( name );
975 module = (HMODULE)((nt->OptionalHeader.ImageBase + 0xffff) & ~0xffff);
976 map_so_dll( nt, module );
977 return module;
981 /***********************************************************************
982 * unix_funcs
984 static struct unix_funcs unix_funcs =
986 NtAllocateVirtualMemory,
987 NtAreMappedFilesTheSame,
988 NtCancelTimer,
989 NtClearEvent,
990 NtClose,
991 NtCreateEvent,
992 NtCreateKeyedEvent,
993 NtCreateMutant,
994 NtCreateSemaphore,
995 NtCreateTimer,
996 NtCurrentTeb,
997 NtDelayExecution,
998 NtDuplicateObject,
999 NtFlushVirtualMemory,
1000 NtFreeVirtualMemory,
1001 NtGetContextThread,
1002 NtGetWriteWatch,
1003 NtLockVirtualMemory,
1004 NtMapViewOfSection,
1005 NtOpenEvent,
1006 NtOpenKeyedEvent,
1007 NtOpenMutant,
1008 NtOpenSemaphore,
1009 NtOpenTimer,
1010 NtProtectVirtualMemory,
1011 NtPulseEvent,
1012 NtQueryEvent,
1013 NtQueryMutant,
1014 NtQuerySection,
1015 NtQuerySemaphore,
1016 NtQueryTimer,
1017 NtQueryVirtualMemory,
1018 NtReadVirtualMemory,
1019 NtReleaseKeyedEvent,
1020 NtReleaseMutant,
1021 NtReleaseSemaphore,
1022 NtResetEvent,
1023 NtResetWriteWatch,
1024 NtSetContextThread,
1025 NtSetEvent,
1026 NtSetLdtEntries,
1027 NtSetTimer,
1028 NtSignalAndWaitForSingleObject,
1029 NtUnlockVirtualMemory,
1030 NtUnmapViewOfSection,
1031 NtWaitForKeyedEvent,
1032 NtWaitForMultipleObjects,
1033 NtWaitForSingleObject,
1034 NtWriteVirtualMemory,
1035 NtYieldExecution,
1036 get_main_args,
1037 get_paths,
1038 get_dll_path,
1039 get_unix_codepage,
1040 get_version,
1041 get_build_id,
1042 get_host_version,
1043 exec_wineloader,
1044 map_so_dll,
1045 virtual_map_section,
1046 virtual_get_system_info,
1047 virtual_create_builtin_view,
1048 virtual_alloc_thread_stack,
1049 virtual_handle_fault,
1050 virtual_locked_server_call,
1051 virtual_locked_read,
1052 virtual_locked_pread,
1053 virtual_locked_recvmsg,
1054 virtual_is_valid_code_address,
1055 virtual_handle_stack_fault,
1056 virtual_check_buffer_for_read,
1057 virtual_check_buffer_for_write,
1058 virtual_uninterrupted_read_memory,
1059 virtual_uninterrupted_write_memory,
1060 virtual_set_force_exec,
1061 virtual_release_address_space,
1062 virtual_set_large_address_space,
1063 init_threading,
1064 create_thread,
1065 start_process,
1066 abort_thread,
1067 exit_thread,
1068 exit_process,
1069 get_thread_ldt_entry,
1070 wine_server_call,
1071 server_select,
1072 server_wait,
1073 server_queue_process_apc,
1074 server_send_fd,
1075 server_get_unix_fd,
1076 server_fd_to_handle,
1077 server_handle_to_fd,
1078 server_release_fd,
1079 server_pipe,
1080 server_init_process_done,
1081 __wine_dbg_get_channel_flags,
1082 __wine_dbg_strdup,
1083 __wine_dbg_output,
1084 __wine_dbg_header,
1088 #ifdef __APPLE__
1089 struct apple_stack_info
1091 void *stack;
1092 size_t desired_size;
1095 static void *apple_wine_thread( void *arg )
1097 __wine_set_unix_funcs( NTDLL_UNIXLIB_VERSION, &unix_funcs );
1098 return NULL;
1101 /***********************************************************************
1102 * apple_alloc_thread_stack
1104 * Callback for mmap_enum_reserved_areas to allocate space for
1105 * the secondary thread's stack.
1107 #ifndef _WIN64
1108 static int CDECL apple_alloc_thread_stack( void *base, size_t size, void *arg )
1110 struct apple_stack_info *info = arg;
1112 /* For mysterious reasons, putting the thread stack at the very top
1113 * of the address space causes subsequent execs to fail, even on the
1114 * child side of a fork. Avoid the top 16MB. */
1115 char * const limit = (char*)0xff000000;
1116 if ((char *)base >= limit) return 0;
1117 if (size > limit - (char*)base)
1118 size = limit - (char*)base;
1119 if (size < info->desired_size) return 0;
1120 info->stack = wine_anon_mmap( (char *)base + size - info->desired_size,
1121 info->desired_size, PROT_READ|PROT_WRITE, MAP_FIXED );
1122 return (info->stack != (void *)-1);
1124 #endif
1126 /***********************************************************************
1127 * apple_create_wine_thread
1129 * Spin off a secondary thread to complete Wine initialization, leaving
1130 * the original thread for the Mac frameworks.
1132 * Invoked as a CFRunLoopSource perform callback.
1134 static void apple_create_wine_thread( void *arg )
1136 int success = 0;
1137 pthread_t thread;
1138 pthread_attr_t attr;
1140 if (!pthread_attr_init( &attr ))
1142 #ifndef _WIN64
1143 struct apple_stack_info info;
1145 /* Try to put the new thread's stack in the reserved area. If this
1146 * fails, just let it go wherever. It'll be a waste of space, but we
1147 * can go on. */
1148 if (!pthread_attr_getstacksize( &attr, &info.desired_size ) &&
1149 mmap_enum_reserved_areas( apple_alloc_thread_stack, &info, 1 ))
1151 mmap_remove_reserved_area( info.stack, info.desired_size );
1152 pthread_attr_setstackaddr( &attr, (char*)info.stack + info.desired_size );
1154 #endif
1156 if (!pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE ) &&
1157 !pthread_create( &thread, &attr, apple_wine_thread, NULL ))
1158 success = 1;
1160 pthread_attr_destroy( &attr );
1162 if (!success) exit(1);
1166 /***********************************************************************
1167 * apple_main_thread
1169 * Park the process's original thread in a Core Foundation run loop for
1170 * use by the Mac frameworks, especially receiving and handling
1171 * distributed notifications. Spin off a new thread for the rest of the
1172 * Wine initialization.
1174 static void apple_main_thread(void)
1176 CFRunLoopSourceContext source_context = { 0 };
1177 CFRunLoopSourceRef source;
1179 if (!pthread_main_np()) return;
1181 /* Multi-processing Services can get confused about the main thread if the
1182 * first time it's used is on a secondary thread. Use it here to make sure
1183 * that doesn't happen. */
1184 MPTaskIsPreemptive(MPCurrentTaskID());
1186 /* Give ourselves the best chance of having the distributed notification
1187 * center scheduled on this thread's run loop. In theory, it's scheduled
1188 * in the first thread to ask for it. */
1189 CFNotificationCenterGetDistributedCenter();
1191 /* We use this run loop source for two purposes. First, a run loop exits
1192 * if it has no more sources scheduled. So, we need at least one source
1193 * to keep the run loop running. Second, although it's not critical, it's
1194 * preferable for the Wine initialization to not proceed until we know
1195 * the run loop is running. So, we signal our source immediately after
1196 * adding it and have its callback spin off the Wine thread. */
1197 source_context.perform = apple_create_wine_thread;
1198 source = CFRunLoopSourceCreate( NULL, 0, &source_context );
1199 CFRunLoopAddSource( CFRunLoopGetCurrent(), source, kCFRunLoopCommonModes );
1200 CFRunLoopSourceSignal( source );
1201 CFRelease( source );
1202 CFRunLoopRun(); /* Should never return, except on error. */
1204 #endif /* __APPLE__ */
1207 #ifdef __ANDROID__
1209 static int pre_exec(void)
1211 #if defined(__i386__) || defined(__x86_64__)
1212 return 1; /* we have a preloader */
1213 #else
1214 return 0; /* no exec needed */
1215 #endif
1218 #elif defined(__linux__) && (defined(__i386__) || defined(__arm__))
1220 static void check_vmsplit( void *stack )
1222 if (stack < (void *)0x80000000)
1224 /* if the stack is below 0x80000000, assume we can safely try a munmap there */
1225 if (munmap( (void *)0x80000000, 1 ) == -1 && errno == EINVAL)
1226 ERR( "Warning: memory above 0x80000000 doesn't seem to be accessible.\n"
1227 "Wine requires a 3G/1G user/kernel memory split to work properly.\n" );
1231 static int pre_exec(void)
1233 int temp;
1235 check_vmsplit( &temp );
1236 #ifdef __i386__
1237 return 1; /* we have a preloader on x86 */
1238 #else
1239 return 0;
1240 #endif
1243 #elif defined(__linux__) && (defined(__x86_64__) || defined(__aarch64__))
1245 static int pre_exec(void)
1247 return 1; /* we have a preloader on x86-64/arm64 */
1250 #elif defined(__APPLE__) && (defined(__i386__) || defined(__x86_64__))
1252 static int pre_exec(void)
1254 return 1; /* we have a preloader */
1257 #elif (defined(__FreeBSD__) || defined (__FreeBSD_kernel__) || defined(__DragonFly__))
1259 static int pre_exec(void)
1261 struct rlimit rl;
1263 rl.rlim_cur = 0x02000000;
1264 rl.rlim_max = 0x02000000;
1265 setrlimit( RLIMIT_DATA, &rl );
1266 return 1;
1269 #else
1271 static int pre_exec(void)
1273 return 0; /* no exec needed */
1276 #endif
1279 /***********************************************************************
1280 * set_process_name
1282 * Change the process name in the ps output.
1284 static void set_process_name( int argc, char *argv[] )
1286 BOOL shift_strings;
1287 char *p, *name;
1288 int i;
1290 #ifdef HAVE_SETPROCTITLE
1291 setproctitle("-%s", argv[1]);
1292 shift_strings = FALSE;
1293 #else
1294 p = argv[0];
1296 shift_strings = (argc >= 2);
1297 for (i = 1; i < argc; i++)
1299 p += strlen(p) + 1;
1300 if (p != argv[i])
1302 shift_strings = FALSE;
1303 break;
1306 #endif
1308 if (shift_strings)
1310 int offset = argv[1] - argv[0];
1311 char *end = argv[argc-1] + strlen(argv[argc-1]) + 1;
1312 memmove( argv[0], argv[1], end - argv[1] );
1313 memset( end - offset, 0, offset );
1314 for (i = 1; i < argc; i++)
1315 argv[i-1] = argv[i] - offset;
1316 argv[i-1] = NULL;
1318 else
1320 /* remove argv[0] */
1321 memmove( argv, argv + 1, argc * sizeof(argv[0]) );
1324 name = argv[0];
1325 if ((p = strrchr( name, '\\' ))) name = p + 1;
1326 if ((p = strrchr( name, '/' ))) name = p + 1;
1328 #if defined(HAVE_SETPROGNAME)
1329 setprogname( name );
1330 #endif
1332 #ifdef HAVE_PRCTL
1333 #ifndef PR_SET_NAME
1334 # define PR_SET_NAME 15
1335 #endif
1336 prctl( PR_SET_NAME, name );
1337 #endif /* HAVE_PRCTL */
1341 /***********************************************************************
1342 * check_command_line
1344 * Check if command line is one that needs to be handled specially.
1346 static void check_command_line( int argc, char *argv[] )
1348 static const char usage[] =
1349 "Usage: wine PROGRAM [ARGUMENTS...] Run the specified program\n"
1350 " wine --help Display this help and exit\n"
1351 " wine --version Output version information and exit";
1353 if (argc <= 1)
1355 fprintf( stderr, "%s\n", usage );
1356 exit(1);
1358 if (!strcmp( argv[1], "--help" ))
1360 printf( "%s\n", usage );
1361 exit(0);
1363 if (!strcmp( argv[1], "--version" ))
1365 printf( "%s\n", get_build_id() );
1366 exit(0);
1371 /***********************************************************************
1372 * __wine_main
1374 * Main entry point called by the wine loader.
1376 void __wine_main( int argc, char *argv[], char *envp[] )
1378 HMODULE module;
1380 init_paths( argc, argv, envp );
1382 if (!getenv( "WINELOADERNOEXEC" )) /* first time around */
1384 static char noexec[] = "WINELOADERNOEXEC=1";
1386 putenv( noexec );
1387 check_command_line( argc, argv );
1388 if (pre_exec())
1390 char **new_argv = malloc( (argc + 2) * sizeof(*argv) );
1391 memcpy( new_argv + 1, argv, (argc + 1) * sizeof(*argv) );
1392 loader_exec( argv0, new_argv, is_win64 );
1393 fatal_error( "could not exec the wine loader\n" );
1397 #ifdef RLIMIT_NOFILE
1398 set_max_limit( RLIMIT_NOFILE );
1399 #endif
1400 #ifdef RLIMIT_AS
1401 set_max_limit( RLIMIT_AS );
1402 #endif
1404 virtual_init();
1406 module = load_ntdll();
1407 fixup_ntdll_imports( &__wine_spec_nt_header, module );
1409 set_process_name( argc, argv );
1410 init_unix_codepage();
1412 #ifdef __APPLE__
1413 apple_main_thread();
1414 #endif
1415 __wine_set_unix_funcs( NTDLL_UNIXLIB_VERSION, &unix_funcs );
1419 static int add_area( void *base, size_t size, void *arg )
1421 mmap_add_reserved_area( base, size );
1422 return 0;
1425 /***********************************************************************
1426 * __wine_init_unix_lib
1428 * Lib entry point called by ntdll.dll.so if not yet initialized.
1430 NTSTATUS __cdecl __wine_init_unix_lib( HMODULE module, const void *ptr_in, void *ptr_out )
1432 const IMAGE_NT_HEADERS *nt = ptr_in;
1434 #ifdef __APPLE__
1435 extern char **__wine_get_main_environment(void);
1436 char **envp = __wine_get_main_environment();
1437 #else
1438 char **envp = __wine_main_environ;
1439 #endif
1440 init_paths( __wine_main_argc, __wine_main_argv, envp );
1442 map_so_dll( nt, module );
1443 fixup_ntdll_imports( &__wine_spec_nt_header, module );
1444 set_process_name( __wine_main_argc, __wine_main_argv );
1445 init_unix_codepage();
1446 *(struct unix_funcs **)ptr_out = &unix_funcs;
1447 wine_mmap_enum_reserved_areas( add_area, NULL, 0 );
1448 return STATUS_SUCCESS;
1451 BOOL WINAPI DECLSPEC_HIDDEN DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved )
1453 if (reason == DLL_PROCESS_ATTACH) LdrDisableThreadCalloutsForDll( inst );
1454 return TRUE;