ntdll: Add stub for NtSetDebugFilterState().
[wine.git] / dlls / ntdll / unix / loader.c
blob10884a7a673afeffe424084efd23bd0c574b7394
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"
27 #include <assert.h>
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <stdarg.h>
31 #include <stdio.h>
32 #include <signal.h>
33 #include <string.h>
34 #include <stdlib.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <sys/mman.h>
38 #include <sys/wait.h>
39 #include <unistd.h>
40 #include <dlfcn.h>
41 #ifdef HAVE_PWD_H
42 # include <pwd.h>
43 #endif
44 #ifdef HAVE_ELF_H
45 # include <elf.h>
46 #endif
47 #ifdef HAVE_LINK_H
48 # include <link.h>
49 #endif
50 #ifdef HAVE_SYS_AUXV_H
51 # include <sys/auxv.h>
52 #endif
53 #ifdef HAVE_SYS_RESOURCE_H
54 # include <sys/resource.h>
55 #endif
56 #include <limits.h>
57 #ifdef HAVE_SYS_SYSCTL_H
58 # include <sys/sysctl.h>
59 #endif
60 #ifdef __APPLE__
61 # include <CoreFoundation/CoreFoundation.h>
62 # define LoadResource MacLoadResource
63 # define GetCurrentThread MacGetCurrentThread
64 # include <CoreServices/CoreServices.h>
65 # undef LoadResource
66 # undef GetCurrentThread
67 # include <pthread.h>
68 # include <mach/mach.h>
69 # include <mach/mach_error.h>
70 # include <mach-o/getsect.h>
71 # include <crt_externs.h>
72 # include <spawn.h>
73 # ifndef _POSIX_SPAWN_DISABLE_ASLR
74 # define _POSIX_SPAWN_DISABLE_ASLR 0x0100
75 # endif
76 #endif
77 #ifdef __ANDROID__
78 # include <jni.h>
79 #endif
81 #include "ntstatus.h"
82 #define WIN32_NO_STATUS
83 #define NONAMELESSUNION
84 #define NONAMELESSSTRUCT
85 #include "windef.h"
86 #include "winnt.h"
87 #include "winbase.h"
88 #include "winnls.h"
89 #include "winioctl.h"
90 #include "winternl.h"
91 #include "unix_private.h"
92 #include "wine/list.h"
93 #include "wine/debug.h"
95 WINE_DEFAULT_DEBUG_CHANNEL(module);
97 #ifdef __i386__
98 static const char so_dir[] = "/i386-unix";
99 #elif defined(__x86_64__)
100 static const char so_dir[] = "/x86_64-unix";
101 #elif defined(__arm__)
102 static const char so_dir[] = "/arm-unix";
103 #elif defined(__aarch64__)
104 static const char so_dir[] = "/aarch64-unix";
105 #else
106 static const char so_dir[] = "";
107 #endif
109 NTSTATUS (WINAPI *pKiRaiseUserExceptionDispatcher)(void) = NULL;
110 NTSTATUS (WINAPI *pKiUserExceptionDispatcher)(EXCEPTION_RECORD*,CONTEXT*) = NULL;
111 void (WINAPI *pKiUserApcDispatcher)(CONTEXT*,ULONG_PTR,ULONG_PTR,ULONG_PTR,PNTAPCFUNC) = NULL;
112 void (WINAPI *pKiUserCallbackDispatcher)(ULONG,void*,ULONG) = NULL;
113 void (WINAPI *pLdrInitializeThunk)(CONTEXT*,void**,ULONG_PTR,ULONG_PTR) = NULL;
114 void (WINAPI *pRtlUserThreadStart)( PRTL_THREAD_START_ROUTINE entry, void *arg ) = NULL;
115 void (WINAPI *p__wine_ctrl_routine)(void*);
116 SYSTEM_DLL_INIT_BLOCK *pLdrSystemDllInitBlock = NULL;
118 static NTSTATUS (CDECL *p__wine_set_unix_funcs)( int version, const struct unix_funcs *funcs );
119 static void *p__wine_syscall_dispatcher;
121 static void * const syscalls[] =
123 NtAcceptConnectPort,
124 NtAccessCheck,
125 NtAccessCheckAndAuditAlarm,
126 NtAddAtom,
127 NtAdjustGroupsToken,
128 NtAdjustPrivilegesToken,
129 NtAlertResumeThread,
130 NtAlertThread,
131 NtAlertThreadByThreadId,
132 NtAllocateLocallyUniqueId,
133 NtAllocateUuids,
134 NtAllocateVirtualMemory,
135 NtAllocateVirtualMemoryEx,
136 NtAreMappedFilesTheSame,
137 NtAssignProcessToJobObject,
138 NtCallbackReturn,
139 NtCancelIoFile,
140 NtCancelIoFileEx,
141 NtCancelTimer,
142 NtClearEvent,
143 NtClose,
144 NtCompareObjects,
145 NtCompleteConnectPort,
146 NtConnectPort,
147 NtContinue,
148 NtCreateDebugObject,
149 NtCreateDirectoryObject,
150 NtCreateEvent,
151 NtCreateFile,
152 NtCreateIoCompletion,
153 NtCreateJobObject,
154 NtCreateKey,
155 NtCreateKeyTransacted,
156 NtCreateKeyedEvent,
157 NtCreateLowBoxToken,
158 NtCreateMailslotFile,
159 NtCreateMutant,
160 NtCreateNamedPipeFile,
161 NtCreatePagingFile,
162 NtCreatePort,
163 NtCreateSection,
164 NtCreateSemaphore,
165 NtCreateSymbolicLinkObject,
166 NtCreateThread,
167 NtCreateThreadEx,
168 NtCreateTimer,
169 NtCreateUserProcess,
170 NtDebugActiveProcess,
171 NtDebugContinue,
172 NtDelayExecution,
173 NtDeleteAtom,
174 NtDeleteFile,
175 NtDeleteKey,
176 NtDeleteValueKey,
177 NtDeviceIoControlFile,
178 NtDisplayString,
179 NtDuplicateObject,
180 NtDuplicateToken,
181 NtEnumerateKey,
182 NtEnumerateValueKey,
183 NtFilterToken,
184 NtFindAtom,
185 NtFlushBuffersFile,
186 NtFlushInstructionCache,
187 NtFlushKey,
188 NtFlushProcessWriteBuffers,
189 NtFlushVirtualMemory,
190 NtFreeVirtualMemory,
191 NtFsControlFile,
192 NtGetContextThread,
193 NtGetCurrentProcessorNumber,
194 NtGetNextThread,
195 NtGetNlsSectionPtr,
196 NtGetWriteWatch,
197 NtImpersonateAnonymousToken,
198 NtInitiatePowerAction ,
199 NtIsProcessInJob,
200 NtListenPort,
201 NtLoadDriver,
202 NtLoadKey,
203 NtLoadKey2,
204 NtLockFile,
205 NtLockVirtualMemory,
206 NtMakeTemporaryObject,
207 NtMapViewOfSection,
208 NtNotifyChangeDirectoryFile,
209 NtNotifyChangeKey,
210 NtNotifyChangeMultipleKeys,
211 NtOpenDirectoryObject,
212 NtOpenEvent,
213 NtOpenFile,
214 NtOpenIoCompletion,
215 NtOpenJobObject,
216 NtOpenKey,
217 NtOpenKeyEx,
218 NtOpenKeyTransacted,
219 NtOpenKeyTransactedEx,
220 NtOpenKeyedEvent,
221 NtOpenMutant,
222 NtOpenProcess,
223 NtOpenProcessToken,
224 NtOpenProcessTokenEx,
225 NtOpenSection,
226 NtOpenSemaphore,
227 NtOpenSymbolicLinkObject ,
228 NtOpenThread,
229 NtOpenThreadToken,
230 NtOpenThreadTokenEx,
231 NtOpenTimer,
232 NtPowerInformation,
233 NtPrivilegeCheck,
234 NtProtectVirtualMemory,
235 NtPulseEvent,
236 NtQueryAttributesFile,
237 NtQueryDefaultLocale,
238 NtQueryDefaultUILanguage,
239 NtQueryDirectoryFile,
240 NtQueryDirectoryObject,
241 NtQueryEaFile,
242 NtQueryEvent,
243 NtQueryFullAttributesFile,
244 NtQueryInformationAtom,
245 NtQueryInformationFile,
246 NtQueryInformationJobObject,
247 NtQueryInformationProcess,
248 NtQueryInformationThread,
249 NtQueryInformationToken,
250 NtQueryInstallUILanguage,
251 NtQueryIoCompletion,
252 NtQueryKey,
253 NtQueryLicenseValue,
254 NtQueryMultipleValueKey,
255 NtQueryMutant,
256 NtQueryObject,
257 NtQueryPerformanceCounter,
258 NtQuerySection,
259 NtQuerySecurityObject,
260 NtQuerySemaphore ,
261 NtQuerySymbolicLinkObject,
262 NtQuerySystemEnvironmentValue,
263 NtQuerySystemEnvironmentValueEx,
264 NtQuerySystemInformation,
265 NtQuerySystemInformationEx,
266 NtQuerySystemTime,
267 NtQueryTimer,
268 NtQueryTimerResolution,
269 NtQueryValueKey,
270 NtQueryVirtualMemory,
271 NtQueryVolumeInformationFile,
272 NtQueueApcThread,
273 NtRaiseException,
274 NtRaiseHardError,
275 NtReadFile,
276 NtReadFileScatter,
277 NtReadVirtualMemory,
278 NtRegisterThreadTerminatePort,
279 NtReleaseKeyedEvent,
280 NtReleaseMutant,
281 NtReleaseSemaphore,
282 NtRemoveIoCompletion,
283 NtRemoveIoCompletionEx,
284 NtRemoveProcessDebug,
285 NtRenameKey,
286 NtReplaceKey,
287 NtReplyWaitReceivePort,
288 NtRequestWaitReplyPort,
289 NtResetEvent,
290 NtResetWriteWatch,
291 NtRestoreKey,
292 NtResumeProcess,
293 NtResumeThread,
294 NtSaveKey,
295 NtSecureConnectPort,
296 NtSetContextThread,
297 NtSetDebugFilterState,
298 NtSetDefaultLocale,
299 NtSetDefaultUILanguage,
300 NtSetEaFile,
301 NtSetEvent,
302 NtSetInformationDebugObject,
303 NtSetInformationFile,
304 NtSetInformationJobObject,
305 NtSetInformationKey,
306 NtSetInformationObject,
307 NtSetInformationProcess,
308 NtSetInformationThread,
309 NtSetInformationToken,
310 NtSetIntervalProfile,
311 NtSetIoCompletion,
312 NtSetLdtEntries,
313 NtSetSecurityObject,
314 NtSetSystemInformation,
315 NtSetSystemTime,
316 NtSetThreadExecutionState,
317 NtSetTimer,
318 NtSetTimerResolution,
319 NtSetValueKey,
320 NtSetVolumeInformationFile,
321 NtShutdownSystem,
322 NtSignalAndWaitForSingleObject,
323 NtSuspendProcess,
324 NtSuspendThread,
325 NtSystemDebugControl,
326 NtTerminateJobObject,
327 NtTerminateProcess,
328 NtTerminateThread,
329 NtTestAlert,
330 NtTraceControl,
331 NtUnloadDriver,
332 NtUnloadKey,
333 NtUnlockFile,
334 NtUnlockVirtualMemory,
335 NtUnmapViewOfSection,
336 NtWaitForAlertByThreadId,
337 NtWaitForDebugEvent,
338 NtWaitForKeyedEvent,
339 NtWaitForMultipleObjects,
340 NtWaitForSingleObject,
341 #ifndef _WIN64
342 NtWow64AllocateVirtualMemory64,
343 NtWow64GetNativeSystemInformation,
344 NtWow64ReadVirtualMemory64,
345 NtWow64WriteVirtualMemory64,
346 #endif
347 NtWriteFile,
348 NtWriteFileGather,
349 NtWriteVirtualMemory,
350 NtYieldExecution,
351 __wine_dbg_write,
352 __wine_unix_call,
353 __wine_unix_spawnvp,
354 wine_nt_to_unix_file_name,
355 wine_server_call,
356 wine_server_fd_to_handle,
357 wine_server_handle_to_fd,
358 wine_unix_to_nt_file_name,
361 static BYTE syscall_args[ARRAY_SIZE(syscalls)];
363 SYSTEM_SERVICE_TABLE KeServiceDescriptorTable[4];
365 #ifdef __GNUC__
366 static void fatal_error( const char *err, ... ) __attribute__((noreturn, format(printf,1,2)));
367 #endif
369 #if defined(linux) || defined(__APPLE__)
370 static const BOOL use_preloader = TRUE;
371 #else
372 static const BOOL use_preloader = FALSE;
373 #endif
375 static char *argv0;
376 static const char *bin_dir;
377 static const char *dll_dir;
378 static const char *ntdll_dir;
379 static SIZE_T dll_path_maxlen;
380 static int *p___wine_main_argc;
381 static char ***p___wine_main_argv;
382 static WCHAR ***p___wine_main_wargv;
384 const char *home_dir = NULL;
385 const char *data_dir = NULL;
386 const char *build_dir = NULL;
387 const char *config_dir = NULL;
388 const char **dll_paths = NULL;
389 const char **system_dll_paths = NULL;
390 const char *user_name = NULL;
391 SECTION_IMAGE_INFORMATION main_image_info = { NULL };
392 static HMODULE ntdll_module;
393 static const IMAGE_EXPORT_DIRECTORY *ntdll_exports;
395 /* adjust an array of pointers to make them into RVAs */
396 static inline void fixup_rva_ptrs( void *array, BYTE *base, unsigned int count )
398 BYTE **src = array;
399 DWORD *dst = array;
401 for ( ; count; count--, src++, dst++) *dst = *src ? *src - base : 0;
404 /* fixup an array of RVAs by adding the specified delta */
405 static inline void fixup_rva_dwords( DWORD *ptr, int delta, unsigned int count )
407 for ( ; count; count--, ptr++) if (*ptr) *ptr += delta;
411 /* fixup an array of name/ordinal RVAs by adding the specified delta */
412 static inline void fixup_rva_names( UINT_PTR *ptr, int delta )
414 for ( ; *ptr; ptr++) if (!(*ptr & IMAGE_ORDINAL_FLAG)) *ptr += delta;
418 /* fixup RVAs in the resource directory */
419 static void fixup_so_resources( IMAGE_RESOURCE_DIRECTORY *dir, BYTE *root, int delta )
421 IMAGE_RESOURCE_DIRECTORY_ENTRY *entry = (IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1);
422 unsigned int i;
424 for (i = 0; i < dir->NumberOfNamedEntries + dir->NumberOfIdEntries; i++, entry++)
426 void *ptr = root + entry->u2.s2.OffsetToDirectory;
427 if (entry->u2.s2.DataIsDirectory) fixup_so_resources( ptr, root, delta );
428 else fixup_rva_dwords( &((IMAGE_RESOURCE_DATA_ENTRY *)ptr)->OffsetToData, delta, 1 );
432 /* die on a fatal error; use only during initialization */
433 static void fatal_error( const char *err, ... )
435 va_list args;
437 va_start( args, err );
438 fprintf( stderr, "wine: " );
439 vfprintf( stderr, err, args );
440 va_end( args );
441 exit(1);
444 static void set_max_limit( int limit )
446 struct rlimit rlimit;
448 if (!getrlimit( limit, &rlimit ))
450 rlimit.rlim_cur = rlimit.rlim_max;
451 if (setrlimit( limit, &rlimit ) != 0)
453 #if defined(__APPLE__) && defined(RLIMIT_NOFILE) && defined(OPEN_MAX)
454 /* On Leopard, setrlimit(RLIMIT_NOFILE, ...) fails on attempts to set
455 * rlim_cur above OPEN_MAX (even if rlim_max > OPEN_MAX). */
456 if (limit == RLIMIT_NOFILE && rlimit.rlim_cur > OPEN_MAX)
458 rlimit.rlim_cur = OPEN_MAX;
459 setrlimit( limit, &rlimit );
461 #endif
466 /* canonicalize path and return its directory name */
467 static char *realpath_dirname( const char *name )
469 char *p, *fullpath = realpath( name, NULL );
471 if (fullpath)
473 p = strrchr( fullpath, '/' );
474 if (p == fullpath) p++;
475 if (p) *p = 0;
477 return fullpath;
480 /* if string ends with tail, remove it */
481 static char *remove_tail( const char *str, const char *tail )
483 size_t len = strlen( str );
484 size_t tail_len = strlen( tail );
485 char *ret;
487 if (len < tail_len) return NULL;
488 if (strcmp( str + len - tail_len, tail )) return NULL;
489 ret = malloc( len - tail_len + 1 );
490 memcpy( ret, str, len - tail_len );
491 ret[len - tail_len] = 0;
492 return ret;
495 /* build a path from the specified dir and name */
496 static char *build_path( const char *dir, const char *name )
498 size_t len = strlen( dir );
499 char *ret = malloc( len + strlen( name ) + 2 );
501 memcpy( ret, dir, len );
502 if (len && ret[len - 1] != '/') ret[len++] = '/';
503 if (name[0] == '/') name++;
504 strcpy( ret + len, name );
505 return ret;
509 static const char *get_pe_dir( WORD machine )
511 if (!machine) machine = current_machine;
513 switch(machine)
515 case IMAGE_FILE_MACHINE_I386: return "/i386-windows";
516 case IMAGE_FILE_MACHINE_AMD64: return "/x86_64-windows";
517 case IMAGE_FILE_MACHINE_ARMNT: return "/arm-windows";
518 case IMAGE_FILE_MACHINE_ARM64: return "/aarch64-windows";
519 default: return "";
524 static void set_dll_path(void)
526 char *p, *path = getenv( "WINEDLLPATH" );
527 int i, count = 0;
529 if (path) for (p = path, count = 1; *p; p++) if (*p == ':') count++;
531 dll_paths = malloc( (count + 2) * sizeof(*dll_paths) );
532 count = 0;
534 if (!build_dir) dll_paths[count++] = dll_dir;
536 if (path)
538 path = strdup(path);
539 for (p = strtok( path, ":" ); p; p = strtok( NULL, ":" )) dll_paths[count++] = strdup( p );
540 free( path );
543 for (i = 0; i < count; i++) dll_path_maxlen = max( dll_path_maxlen, strlen(dll_paths[i]) );
544 dll_paths[count] = NULL;
548 static void set_system_dll_path(void)
550 const char *p, *path = SYSTEMDLLPATH;
551 int count = 0;
553 if (path && *path) for (p = path, count = 1; *p; p++) if (*p == ':') count++;
555 system_dll_paths = malloc( (count + 1) * sizeof(*system_dll_paths) );
556 count = 0;
558 if (path && *path)
560 char *path_copy = strdup(path);
561 for (p = strtok( path_copy, ":" ); p; p = strtok( NULL, ":" ))
562 system_dll_paths[count++] = strdup( p );
563 free( path_copy );
565 system_dll_paths[count] = NULL;
569 static void set_home_dir(void)
571 const char *home = getenv( "HOME" );
572 const char *name = getenv( "USER" );
573 const char *p;
575 if (!home || !name)
577 struct passwd *pwd = getpwuid( getuid() );
578 if (pwd)
580 if (!home) home = pwd->pw_dir;
581 if (!name) name = pwd->pw_name;
583 if (!name) name = "wine";
585 if ((p = strrchr( name, '/' ))) name = p + 1;
586 if ((p = strrchr( name, '\\' ))) name = p + 1;
587 home_dir = strdup( home );
588 user_name = strdup( name );
592 static void set_config_dir(void)
594 char *p, *dir;
595 const char *prefix = getenv( "WINEPREFIX" );
597 if (prefix)
599 if (prefix[0] != '/')
600 fatal_error( "invalid directory %s in WINEPREFIX: not an absolute path\n", prefix );
601 config_dir = dir = strdup( prefix );
602 for (p = dir + strlen(dir) - 1; p > dir && *p == '/'; p--) *p = 0;
604 else
606 if (!home_dir) fatal_error( "could not determine your home directory\n" );
607 if (home_dir[0] != '/') fatal_error( "the home directory %s is not an absolute path\n", home_dir );
608 config_dir = build_path( home_dir, ".wine" );
612 static void init_paths( char *argv[] )
614 Dl_info info;
616 argv0 = strdup( argv[0] );
618 if (!dladdr( init_paths, &info ) || !(ntdll_dir = realpath_dirname( info.dli_fname )))
619 fatal_error( "cannot get path to ntdll.so\n" );
621 if (!(build_dir = remove_tail( ntdll_dir, "/dlls/ntdll" )))
623 if (!(dll_dir = remove_tail( ntdll_dir, so_dir ))) dll_dir = ntdll_dir;
624 #if (defined(__linux__) && !defined(__ANDROID__)) || defined(__FreeBSD_kernel__) || defined(__NetBSD__)
625 bin_dir = realpath_dirname( "/proc/self/exe" );
626 #elif defined (__FreeBSD__) || defined(__DragonFly__)
628 static int pathname[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
629 size_t path_size = PATH_MAX;
630 char *path = malloc( path_size );
631 if (path && !sysctl( pathname, sizeof(pathname)/sizeof(pathname[0]), path, &path_size, NULL, 0 ))
632 bin_dir = realpath_dirname( path );
633 free( path );
635 #else
636 bin_dir = realpath_dirname( argv0 );
637 #endif
638 if (!bin_dir) bin_dir = build_path( dll_dir, DLL_TO_BINDIR );
639 data_dir = build_path( bin_dir, BIN_TO_DATADIR );
642 set_dll_path();
643 set_system_dll_path();
644 set_home_dir();
645 set_config_dir();
649 static void preloader_exec( char **argv )
651 if (use_preloader)
653 static const char *preloader = "wine-preloader";
654 char *p;
656 if (!(p = strrchr( argv[1], '/' ))) p = argv[1];
657 else p++;
659 if (strlen(p) > 2 && !strcmp( p + strlen(p) - 2, "64" )) preloader = "wine64-preloader";
660 argv[0] = malloc( p - argv[1] + strlen(preloader) + 1 );
661 memcpy( argv[0], argv[1], p - argv[1] );
662 strcpy( argv[0] + (p - argv[1]), preloader );
664 #ifdef __APPLE__
666 posix_spawnattr_t attr;
667 posix_spawnattr_init( &attr );
668 posix_spawnattr_setflags( &attr, POSIX_SPAWN_SETEXEC | _POSIX_SPAWN_DISABLE_ASLR );
669 posix_spawn( NULL, argv[0], NULL, &attr, argv, *_NSGetEnviron() );
670 posix_spawnattr_destroy( &attr );
672 #endif
673 execv( argv[0], argv );
674 free( argv[0] );
676 execv( argv[1], argv + 1 );
679 static NTSTATUS loader_exec( const char *loader, char **argv, WORD machine )
681 char *p, *path;
683 if (build_dir)
685 argv[1] = build_path( build_dir, (machine == IMAGE_FILE_MACHINE_AMD64) ? "loader/wine64" : "loader/wine" );
686 preloader_exec( argv );
687 return STATUS_INVALID_IMAGE_FORMAT;
690 if ((p = strrchr( loader, '/' ))) loader = p + 1;
692 argv[1] = build_path( bin_dir, loader );
693 preloader_exec( argv );
695 argv[1] = getenv( "WINELOADER" );
696 if (argv[1]) preloader_exec( argv );
698 if ((path = getenv( "PATH" )))
700 for (p = strtok( strdup( path ), ":" ); p; p = strtok( NULL, ":" ))
702 argv[1] = build_path( p, loader );
703 preloader_exec( argv );
707 argv[1] = build_path( BINDIR, loader );
708 preloader_exec( argv );
709 return STATUS_INVALID_IMAGE_FORMAT;
713 /***********************************************************************
714 * exec_wineloader
716 * argv[0] and argv[1] must be reserved for the preloader and loader respectively.
718 NTSTATUS exec_wineloader( char **argv, int socketfd, const pe_image_info_t *pe_info )
720 WORD machine = pe_info->machine;
721 ULONGLONG res_start = pe_info->base;
722 ULONGLONG res_end = pe_info->base + pe_info->map_size;
723 const char *loader = argv0;
724 const char *loader_env = getenv( "WINELOADER" );
725 char preloader_reserve[64], socket_env[64];
726 BOOL is_child_64bit;
728 if (pe_info->image_flags & IMAGE_FLAGS_WineFakeDll) res_start = res_end = 0;
729 if (pe_info->image_flags & IMAGE_FLAGS_ComPlusNativeReady) machine = native_machine;
731 is_child_64bit = is_machine_64bit( machine );
733 if (!is_win64 ^ !is_child_64bit)
735 /* remap WINELOADER to the alternate 32/64-bit version if necessary */
736 if (loader_env)
738 int len = strlen( loader_env );
739 char *env = malloc( sizeof("WINELOADER=") + len + 2 );
741 if (!env) return STATUS_NO_MEMORY;
742 strcpy( env, "WINELOADER=" );
743 strcat( env, loader_env );
744 if (is_child_64bit)
746 strcat( env, "64" );
748 else
750 len += sizeof("WINELOADER=") - 1;
751 if (!strcmp( env + len - 2, "64" )) env[len - 2] = 0;
753 loader = env;
754 putenv( env );
756 else loader = is_child_64bit ? "wine64" : "wine";
759 signal( SIGPIPE, SIG_DFL );
761 sprintf( socket_env, "WINESERVERSOCKET=%u", socketfd );
762 sprintf( preloader_reserve, "WINEPRELOADRESERVE=%x%08x-%x%08x",
763 (ULONG)(res_start >> 32), (ULONG)res_start, (ULONG)(res_end >> 32), (ULONG)res_end );
765 putenv( preloader_reserve );
766 putenv( socket_env );
768 return loader_exec( loader, argv, machine );
772 /***********************************************************************
773 * exec_wineserver
775 * Exec a new wine server.
777 static void exec_wineserver( char **argv )
779 char *path;
781 if (build_dir)
783 if (!is_win64) /* look for 64-bit server */
785 char *loader = realpath_dirname( build_path( build_dir, "loader/wine64" ));
786 if (loader)
788 argv[0] = build_path( loader, "../server/wineserver" );
789 execv( argv[0], argv );
792 argv[0] = build_path( build_dir, "server/wineserver" );
793 execv( argv[0], argv );
794 return;
797 argv[0] = build_path( bin_dir, "wineserver" );
798 execv( argv[0], argv );
800 argv[0] = getenv( "WINESERVER" );
801 if (argv[0]) execv( argv[0], argv );
803 if ((path = getenv( "PATH" )))
805 for (path = strtok( strdup( path ), ":" ); path; path = strtok( NULL, ":" ))
807 argv[0] = build_path( path, "wineserver" );
808 execvp( argv[0], argv );
812 argv[0] = build_path( BINDIR, "wineserver" );
813 execv( argv[0], argv );
817 /***********************************************************************
818 * start_server
820 * Start a new wine server.
822 void start_server( BOOL debug )
824 static BOOL started; /* we only try once */
825 char *argv[3];
826 static char debug_flag[] = "-d";
828 if (!started)
830 int status;
831 int pid = fork();
832 if (pid == -1) fatal_error( "fork: %s", strerror(errno) );
833 if (!pid)
835 argv[1] = debug ? debug_flag : NULL;
836 argv[2] = NULL;
837 exec_wineserver( argv );
838 fatal_error( "could not exec wineserver\n" );
840 waitpid( pid, &status, 0 );
841 status = WIFEXITED(status) ? WEXITSTATUS(status) : 1;
842 if (status == 2) return; /* server lock held by someone else, will retry later */
843 if (status) exit(status); /* server failed */
844 started = TRUE;
849 /*************************************************************************
850 * map_so_dll
852 * Map a builtin dll in memory and fixup RVAs.
854 static NTSTATUS map_so_dll( const IMAGE_NT_HEADERS *nt_descr, HMODULE module )
856 static const char builtin_signature[32] = "Wine builtin DLL";
857 IMAGE_DATA_DIRECTORY *dir;
858 IMAGE_DOS_HEADER *dos;
859 IMAGE_NT_HEADERS *nt;
860 IMAGE_SECTION_HEADER *sec;
861 BYTE *addr = (BYTE *)module;
862 DWORD code_start, code_end, data_start, data_end, align_mask;
863 int delta, nb_sections = 2; /* code + data */
864 unsigned int i;
865 DWORD size = (sizeof(IMAGE_DOS_HEADER)
866 + sizeof(builtin_signature)
867 + sizeof(IMAGE_NT_HEADERS)
868 + nb_sections * sizeof(IMAGE_SECTION_HEADER));
870 if (anon_mmap_fixed( addr, size, PROT_READ | PROT_WRITE, 0 ) != addr) return STATUS_NO_MEMORY;
872 dos = (IMAGE_DOS_HEADER *)addr;
873 nt = (IMAGE_NT_HEADERS *)((BYTE *)(dos + 1) + sizeof(builtin_signature));
874 sec = (IMAGE_SECTION_HEADER *)(nt + 1);
876 /* build the DOS and NT headers */
878 dos->e_magic = IMAGE_DOS_SIGNATURE;
879 dos->e_cblp = 0x90;
880 dos->e_cp = 3;
881 dos->e_cparhdr = (sizeof(*dos) + 0xf) / 0x10;
882 dos->e_minalloc = 0;
883 dos->e_maxalloc = 0xffff;
884 dos->e_ss = 0x0000;
885 dos->e_sp = 0x00b8;
886 dos->e_lfanew = sizeof(*dos) + sizeof(builtin_signature);
887 memcpy( dos + 1, builtin_signature, sizeof(builtin_signature) );
889 *nt = *nt_descr;
891 delta = (const BYTE *)nt_descr - addr;
892 align_mask = nt->OptionalHeader.SectionAlignment - 1;
893 code_start = (size + align_mask) & ~align_mask;
894 data_start = delta & ~align_mask;
895 #ifdef __APPLE__
897 Dl_info dli;
898 unsigned long data_size;
899 /* need the mach_header, not the PE header, to give to getsegmentdata(3) */
900 dladdr(addr, &dli);
901 code_end = getsegmentdata(dli.dli_fbase, "__DATA", &data_size) - addr;
902 data_end = (code_end + data_size + align_mask) & ~align_mask;
904 #else
905 code_end = data_start;
906 data_end = (nt->OptionalHeader.SizeOfImage + delta + align_mask) & ~align_mask;
907 #endif
909 fixup_rva_ptrs( &nt->OptionalHeader.AddressOfEntryPoint, addr, 1 );
911 nt->FileHeader.NumberOfSections = nb_sections;
912 nt->OptionalHeader.BaseOfCode = code_start;
913 #ifndef _WIN64
914 nt->OptionalHeader.BaseOfData = data_start;
915 #endif
916 nt->OptionalHeader.SizeOfCode = code_end - code_start;
917 nt->OptionalHeader.SizeOfInitializedData = data_end - data_start;
918 nt->OptionalHeader.SizeOfUninitializedData = 0;
919 nt->OptionalHeader.SizeOfImage = data_end;
920 nt->OptionalHeader.ImageBase = (ULONG_PTR)addr;
922 /* build the code section */
924 memcpy( sec->Name, ".text", sizeof(".text") );
925 sec->SizeOfRawData = code_end - code_start;
926 sec->Misc.VirtualSize = sec->SizeOfRawData;
927 sec->VirtualAddress = code_start;
928 sec->PointerToRawData = code_start;
929 sec->Characteristics = (IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ);
930 sec++;
932 /* build the data section */
934 memcpy( sec->Name, ".data", sizeof(".data") );
935 sec->SizeOfRawData = data_end - data_start;
936 sec->Misc.VirtualSize = sec->SizeOfRawData;
937 sec->VirtualAddress = data_start;
938 sec->PointerToRawData = data_start;
939 sec->Characteristics = (IMAGE_SCN_CNT_INITIALIZED_DATA |
940 IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ);
941 sec++;
943 for (i = 0; i < nt->OptionalHeader.NumberOfRvaAndSizes; i++)
944 fixup_rva_dwords( &nt->OptionalHeader.DataDirectory[i].VirtualAddress, delta, 1 );
946 /* build the import directory */
948 dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_IMPORT_DIRECTORY];
949 if (dir->Size)
951 IMAGE_IMPORT_DESCRIPTOR *imports = (IMAGE_IMPORT_DESCRIPTOR *)(addr + dir->VirtualAddress);
953 while (imports->Name)
955 fixup_rva_dwords( &imports->u.OriginalFirstThunk, delta, 1 );
956 fixup_rva_dwords( &imports->Name, delta, 1 );
957 fixup_rva_dwords( &imports->FirstThunk, delta, 1 );
958 if (imports->u.OriginalFirstThunk)
959 fixup_rva_names( (UINT_PTR *)(addr + imports->u.OriginalFirstThunk), delta );
960 if (imports->FirstThunk)
961 fixup_rva_names( (UINT_PTR *)(addr + imports->FirstThunk), delta );
962 imports++;
966 /* build the resource directory */
968 dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_RESOURCE_DIRECTORY];
969 if (dir->Size)
971 void *ptr = addr + dir->VirtualAddress;
972 fixup_so_resources( ptr, ptr, delta );
975 /* build the export directory */
977 dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_EXPORT_DIRECTORY];
978 if (dir->Size)
980 IMAGE_EXPORT_DIRECTORY *exports = (IMAGE_EXPORT_DIRECTORY *)(addr + dir->VirtualAddress);
982 fixup_rva_dwords( &exports->Name, delta, 1 );
983 fixup_rva_dwords( &exports->AddressOfFunctions, delta, 1 );
984 fixup_rva_dwords( &exports->AddressOfNames, delta, 1 );
985 fixup_rva_dwords( &exports->AddressOfNameOrdinals, delta, 1 );
986 fixup_rva_dwords( (DWORD *)(addr + exports->AddressOfNames), delta, exports->NumberOfNames );
987 fixup_rva_ptrs( addr + exports->AddressOfFunctions, addr, exports->NumberOfFunctions );
989 return STATUS_SUCCESS;
992 static ULONG_PTR find_ordinal_export( HMODULE module, const IMAGE_EXPORT_DIRECTORY *exports, DWORD ordinal )
994 const DWORD *functions = (const DWORD *)((BYTE *)module + exports->AddressOfFunctions);
996 if (ordinal >= exports->NumberOfFunctions) return 0;
997 if (!functions[ordinal]) return 0;
998 return (ULONG_PTR)module + functions[ordinal];
1001 static ULONG_PTR find_named_export( HMODULE module, const IMAGE_EXPORT_DIRECTORY *exports,
1002 const char *name )
1004 const WORD *ordinals = (const WORD *)((BYTE *)module + exports->AddressOfNameOrdinals);
1005 const DWORD *names = (const DWORD *)((BYTE *)module + exports->AddressOfNames);
1006 int min = 0, max = exports->NumberOfNames - 1;
1008 while (min <= max)
1010 int res, pos = (min + max) / 2;
1011 char *ename = (char *)module + names[pos];
1012 if (!(res = strcmp( ename, name ))) return find_ordinal_export( module, exports, ordinals[pos] );
1013 if (res > 0) max = pos - 1;
1014 else min = pos + 1;
1016 return 0;
1019 static inline void *get_rva( void *module, ULONG_PTR addr )
1021 return (BYTE *)module + addr;
1024 static const void *get_module_data_dir( HMODULE module, ULONG dir, ULONG *size )
1026 const IMAGE_NT_HEADERS *nt = get_rva( module, ((IMAGE_DOS_HEADER *)module)->e_lfanew );
1027 const IMAGE_DATA_DIRECTORY *data;
1029 if (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
1030 data = &((const IMAGE_NT_HEADERS64 *)nt)->OptionalHeader.DataDirectory[dir];
1031 else if (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
1032 data = &((const IMAGE_NT_HEADERS32 *)nt)->OptionalHeader.DataDirectory[dir];
1033 else
1034 return NULL;
1035 if (!data->VirtualAddress || !data->Size) return NULL;
1036 if (size) *size = data->Size;
1037 return get_rva( module, data->VirtualAddress );
1040 static void load_ntdll_functions( HMODULE module )
1042 ntdll_exports = get_module_data_dir( module, IMAGE_FILE_EXPORT_DIRECTORY, NULL );
1043 assert( ntdll_exports );
1045 #define GET_FUNC(name) \
1046 if (!(p##name = (void *)find_named_export( module, ntdll_exports, #name ))) \
1047 ERR( "%s not found\n", #name )
1049 GET_FUNC( KiRaiseUserExceptionDispatcher );
1050 GET_FUNC( KiUserExceptionDispatcher );
1051 GET_FUNC( KiUserApcDispatcher );
1052 GET_FUNC( KiUserCallbackDispatcher );
1053 GET_FUNC( LdrInitializeThunk );
1054 GET_FUNC( LdrSystemDllInitBlock );
1055 GET_FUNC( RtlUserThreadStart );
1056 GET_FUNC( __wine_ctrl_routine );
1057 GET_FUNC( __wine_set_unix_funcs );
1058 GET_FUNC( __wine_syscall_dispatcher );
1059 #ifdef __i386__
1061 void **p__wine_ldt_copy;
1062 GET_FUNC( __wine_ldt_copy );
1063 *p__wine_ldt_copy = &__wine_ldt_copy;
1065 #endif
1066 #undef GET_FUNC
1069 static void load_ntdll_wow64_functions( HMODULE module )
1071 const IMAGE_EXPORT_DIRECTORY *exports;
1073 exports = get_module_data_dir( module, IMAGE_FILE_EXPORT_DIRECTORY, NULL );
1074 assert( exports );
1076 pLdrSystemDllInitBlock->ntdll_handle = (ULONG_PTR)module;
1078 #define GET_FUNC(name) pLdrSystemDllInitBlock->p##name = find_named_export( module, exports, #name )
1079 GET_FUNC( KiUserApcDispatcher );
1080 GET_FUNC( KiUserCallbackDispatcher );
1081 GET_FUNC( KiUserExceptionDispatcher );
1082 GET_FUNC( LdrInitializeThunk );
1083 GET_FUNC( LdrSystemDllInitBlock );
1084 GET_FUNC( RtlUserThreadStart );
1085 GET_FUNC( RtlpFreezeTimeBias );
1086 GET_FUNC( RtlpQueryProcessDebugInformationRemote );
1087 #undef GET_FUNC
1089 p__wine_ctrl_routine = (void *)find_named_export( module, exports, "__wine_ctrl_routine" );
1091 /* also set the 32-bit LdrSystemDllInitBlock */
1092 memcpy( (void *)(ULONG_PTR)pLdrSystemDllInitBlock->pLdrSystemDllInitBlock,
1093 pLdrSystemDllInitBlock, sizeof(*pLdrSystemDllInitBlock) );
1096 /* reimplementation of LdrProcessRelocationBlock */
1097 static const IMAGE_BASE_RELOCATION *process_relocation_block( void *module, const IMAGE_BASE_RELOCATION *rel,
1098 INT_PTR delta )
1100 char *page = get_rva( module, rel->VirtualAddress );
1101 UINT count = (rel->SizeOfBlock - sizeof(*rel)) / sizeof(USHORT);
1102 USHORT *relocs = (USHORT *)(rel + 1);
1104 while (count--)
1106 USHORT offset = *relocs & 0xfff;
1107 switch (*relocs >> 12)
1109 case IMAGE_REL_BASED_ABSOLUTE:
1110 break;
1111 case IMAGE_REL_BASED_HIGH:
1112 *(short *)(page + offset) += HIWORD(delta);
1113 break;
1114 case IMAGE_REL_BASED_LOW:
1115 *(short *)(page + offset) += LOWORD(delta);
1116 break;
1117 case IMAGE_REL_BASED_HIGHLOW:
1118 *(int *)(page + offset) += delta;
1119 break;
1120 case IMAGE_REL_BASED_DIR64:
1121 *(INT64 *)(page + offset) += delta;
1122 break;
1123 case IMAGE_REL_BASED_THUMB_MOV32:
1125 DWORD *inst = (DWORD *)(page + offset);
1126 WORD lo = ((inst[0] << 1) & 0x0800) + ((inst[0] << 12) & 0xf000) +
1127 ((inst[0] >> 20) & 0x0700) + ((inst[0] >> 16) & 0x00ff);
1128 WORD hi = ((inst[1] << 1) & 0x0800) + ((inst[1] << 12) & 0xf000) +
1129 ((inst[1] >> 20) & 0x0700) + ((inst[1] >> 16) & 0x00ff);
1130 DWORD imm = MAKELONG( lo, hi ) + delta;
1132 lo = LOWORD( imm );
1133 hi = HIWORD( imm );
1134 inst[0] = (inst[0] & 0x8f00fbf0) + ((lo >> 1) & 0x0400) + ((lo >> 12) & 0x000f) +
1135 ((lo << 20) & 0x70000000) + ((lo << 16) & 0xff0000);
1136 inst[1] = (inst[1] & 0x8f00fbf0) + ((hi >> 1) & 0x0400) + ((hi >> 12) & 0x000f) +
1137 ((hi << 20) & 0x70000000) + ((hi << 16) & 0xff0000);
1138 break;
1140 default:
1141 FIXME("Unknown/unsupported relocation %x\n", *relocs);
1142 return NULL;
1144 relocs++;
1146 return (IMAGE_BASE_RELOCATION *)relocs; /* return address of next block */
1149 static void relocate_ntdll( void *module )
1151 const IMAGE_NT_HEADERS *nt = get_rva( module, ((IMAGE_DOS_HEADER *)module)->e_lfanew );
1152 const IMAGE_BASE_RELOCATION *rel, *end;
1153 const IMAGE_SECTION_HEADER *sec;
1154 ULONG protect_old[96], i, size;
1155 INT_PTR delta;
1157 ERR( "ntdll could not be mapped at preferred address (%p), expect trouble\n", module );
1159 if (!(rel = get_module_data_dir( module, IMAGE_DIRECTORY_ENTRY_BASERELOC, &size ))) return;
1161 sec = (IMAGE_SECTION_HEADER *)((char *)&nt->OptionalHeader + nt->FileHeader.SizeOfOptionalHeader);
1162 for (i = 0; i < nt->FileHeader.NumberOfSections; i++)
1164 void *addr = get_rva( module, sec[i].VirtualAddress );
1165 SIZE_T size = sec[i].SizeOfRawData;
1166 NtProtectVirtualMemory( NtCurrentProcess(), &addr, &size, PAGE_READWRITE, &protect_old[i] );
1169 end = (IMAGE_BASE_RELOCATION *)((const char *)rel + size);
1170 delta = (char *)module - (char *)nt->OptionalHeader.ImageBase;
1171 while (rel && rel < end - 1 && rel->SizeOfBlock) rel = process_relocation_block( module, rel, delta );
1173 for (i = 0; i < nt->FileHeader.NumberOfSections; i++)
1175 void *addr = get_rva( module, sec[i].VirtualAddress );
1176 SIZE_T size = sec[i].SizeOfRawData;
1177 NtProtectVirtualMemory( NtCurrentProcess(), &addr, &size, protect_old[i], &protect_old[i] );
1182 static void *callback_module;
1184 /***********************************************************************
1185 * load_builtin_callback
1187 * Load a library in memory; callback function for wine_dll_register
1189 static void load_builtin_callback( void *module, const char *filename )
1191 callback_module = module;
1195 /***********************************************************************
1196 * load_libwine
1198 static void load_libwine(void)
1200 #ifdef __APPLE__
1201 #define LIBWINE "libwine.1.dylib"
1202 #else
1203 #define LIBWINE "libwine.so.1"
1204 #endif
1205 typedef void (*load_dll_callback_t)( void *, const char * );
1206 void (*p_wine_dll_set_callback)( load_dll_callback_t load );
1207 char ***p___wine_main_environ;
1209 char *path;
1210 void *handle;
1212 if (build_dir) path = build_path( build_dir, "libs/wine/" LIBWINE );
1213 else path = build_path( ntdll_dir, LIBWINE );
1215 handle = dlopen( path, RTLD_NOW );
1216 free( path );
1217 if (!handle && !(handle = dlopen( LIBWINE, RTLD_NOW ))) return;
1219 p_wine_dll_set_callback = dlsym( handle, "wine_dll_set_callback" );
1220 p___wine_main_argc = dlsym( handle, "__wine_main_argc" );
1221 p___wine_main_argv = dlsym( handle, "__wine_main_argv" );
1222 p___wine_main_wargv = dlsym( handle, "__wine_main_wargv" );
1223 p___wine_main_environ = dlsym( handle, "__wine_main_environ" );
1225 if (p_wine_dll_set_callback) p_wine_dll_set_callback( load_builtin_callback );
1226 if (p___wine_main_environ) *p___wine_main_environ = main_envp;
1230 /***********************************************************************
1231 * fill_builtin_image_info
1233 static void fill_builtin_image_info( void *module, pe_image_info_t *info )
1235 const IMAGE_DOS_HEADER *dos = (const IMAGE_DOS_HEADER *)module;
1236 const IMAGE_NT_HEADERS *nt = (IMAGE_NT_HEADERS *)((const BYTE *)dos + dos->e_lfanew);
1238 info->base = nt->OptionalHeader.ImageBase;
1239 info->entry_point = nt->OptionalHeader.AddressOfEntryPoint;
1240 info->map_size = nt->OptionalHeader.SizeOfImage;
1241 info->stack_size = nt->OptionalHeader.SizeOfStackReserve;
1242 info->stack_commit = nt->OptionalHeader.SizeOfStackCommit;
1243 info->zerobits = 0;
1244 info->subsystem = nt->OptionalHeader.Subsystem;
1245 info->subsystem_minor = nt->OptionalHeader.MinorSubsystemVersion;
1246 info->subsystem_major = nt->OptionalHeader.MajorSubsystemVersion;
1247 info->osversion_major = nt->OptionalHeader.MajorOperatingSystemVersion;
1248 info->osversion_minor = nt->OptionalHeader.MinorOperatingSystemVersion;
1249 info->image_charact = nt->FileHeader.Characteristics;
1250 info->dll_charact = nt->OptionalHeader.DllCharacteristics;
1251 info->machine = nt->FileHeader.Machine;
1252 info->contains_code = TRUE;
1253 info->image_flags = IMAGE_FLAGS_WineBuiltin;
1254 info->loader_flags = 0;
1255 info->header_size = nt->OptionalHeader.SizeOfHeaders;
1256 info->file_size = nt->OptionalHeader.SizeOfImage;
1257 info->checksum = nt->OptionalHeader.CheckSum;
1258 info->dbg_offset = 0;
1259 info->dbg_size = 0;
1263 /***********************************************************************
1264 * dlopen_dll
1266 static NTSTATUS dlopen_dll( const char *so_name, UNICODE_STRING *nt_name, void **ret_module,
1267 pe_image_info_t *image_info, BOOL prefer_native )
1269 void *module, *handle;
1270 const IMAGE_NT_HEADERS *nt;
1272 callback_module = (void *)1;
1273 handle = dlopen( so_name, RTLD_NOW );
1274 if (!handle)
1276 WARN( "failed to load .so lib %s: %s\n", debugstr_a(so_name), dlerror() );
1277 return STATUS_INVALID_IMAGE_FORMAT;
1279 if (callback_module != (void *)1) /* callback was called */
1281 if (!callback_module) return STATUS_NO_MEMORY;
1282 WARN( "got old-style builtin library %s, constructors won't work\n", debugstr_a(so_name) );
1283 module = callback_module;
1284 if (get_builtin_so_handle( module )) goto already_loaded;
1286 else if ((nt = dlsym( handle, "__wine_spec_nt_header" )))
1288 module = (HMODULE)((nt->OptionalHeader.ImageBase + 0xffff) & ~0xffff);
1289 if (get_builtin_so_handle( module )) goto already_loaded;
1290 if (map_so_dll( nt, module ))
1292 dlclose( handle );
1293 return STATUS_NO_MEMORY;
1296 else /* already loaded .so */
1298 WARN( "%s already loaded?\n", debugstr_a(so_name));
1299 return STATUS_INVALID_IMAGE_FORMAT;
1302 fill_builtin_image_info( module, image_info );
1303 if (prefer_native && (image_info->dll_charact & IMAGE_DLLCHARACTERISTICS_PREFER_NATIVE))
1305 TRACE( "%s has prefer-native flag, ignoring builtin\n", debugstr_a(so_name) );
1306 dlclose( handle );
1307 return STATUS_IMAGE_ALREADY_LOADED;
1310 if (virtual_create_builtin_view( module, nt_name, image_info, handle ))
1312 dlclose( handle );
1313 return STATUS_NO_MEMORY;
1315 *ret_module = module;
1316 return STATUS_SUCCESS;
1318 already_loaded:
1319 fill_builtin_image_info( module, image_info );
1320 *ret_module = module;
1321 dlclose( handle );
1322 return STATUS_SUCCESS;
1326 /***********************************************************************
1327 * ntdll_init_syscalls
1329 NTSTATUS ntdll_init_syscalls( ULONG id, SYSTEM_SERVICE_TABLE *table, void **dispatcher )
1331 struct syscall_info
1333 void *dispatcher;
1334 USHORT limit;
1335 BYTE args[1];
1336 } *info = (struct syscall_info *)dispatcher;
1338 if (id > 3) return STATUS_INVALID_PARAMETER;
1339 if (info->limit != table->ServiceLimit)
1341 ERR( "syscall count mismatch %u / %lu\n", info->limit, table->ServiceLimit );
1342 NtTerminateProcess( GetCurrentProcess(), STATUS_INVALID_PARAMETER );
1344 info->dispatcher = __wine_syscall_dispatcher;
1345 memcpy( table->ArgumentTable, info->args, table->ServiceLimit );
1346 KeServiceDescriptorTable[id] = *table;
1347 return STATUS_SUCCESS;
1351 /***********************************************************************
1352 * __wine_unix_call
1354 NTSTATUS WINAPI __wine_unix_call( unixlib_handle_t handle, unsigned int code, void *args )
1356 return ((unixlib_entry_t*)(UINT_PTR)handle)[code]( args );
1360 /***********************************************************************
1361 * load_so_dll
1363 static NTSTATUS CDECL load_so_dll( UNICODE_STRING *nt_name, void **module )
1365 static const WCHAR soW[] = {'.','s','o',0};
1366 OBJECT_ATTRIBUTES attr;
1367 UNICODE_STRING redir;
1368 pe_image_info_t info;
1369 char *unix_name;
1370 NTSTATUS status;
1371 DWORD len;
1373 if (get_load_order( nt_name ) == LO_DISABLED) return STATUS_DLL_NOT_FOUND;
1374 InitializeObjectAttributes( &attr, nt_name, OBJ_CASE_INSENSITIVE, 0, 0 );
1375 get_redirect( &attr, &redir );
1377 if (nt_to_unix_file_name( &attr, &unix_name, FILE_OPEN ))
1379 free( redir.Buffer );
1380 return STATUS_DLL_NOT_FOUND;
1383 /* remove .so extension from Windows name */
1384 len = nt_name->Length / sizeof(WCHAR);
1385 if (len > 3 && !wcsicmp( nt_name->Buffer + len - 3, soW )) nt_name->Length -= 3 * sizeof(WCHAR);
1387 status = dlopen_dll( unix_name, nt_name, module, &info, FALSE );
1388 free( unix_name );
1389 free( redir.Buffer );
1390 return status;
1394 /* check if the library is the correct architecture */
1395 /* only returns false for a valid library of the wrong arch */
1396 static int check_library_arch( int fd )
1398 #ifdef __APPLE__
1399 struct /* Mach-O header */
1401 unsigned int magic;
1402 unsigned int cputype;
1403 } header;
1405 if (read( fd, &header, sizeof(header) ) != sizeof(header)) return 1;
1406 if (header.magic != 0xfeedface) return 1;
1407 if (sizeof(void *) == sizeof(int)) return !(header.cputype >> 24);
1408 else return (header.cputype >> 24) == 1; /* CPU_ARCH_ABI64 */
1409 #else
1410 struct /* ELF header */
1412 unsigned char magic[4];
1413 unsigned char class;
1414 unsigned char data;
1415 unsigned char version;
1416 } header;
1418 if (read( fd, &header, sizeof(header) ) != sizeof(header)) return 1;
1419 if (memcmp( header.magic, "\177ELF", 4 )) return 1;
1420 if (header.version != 1 /* EV_CURRENT */) return 1;
1421 #ifdef WORDS_BIGENDIAN
1422 if (header.data != 2 /* ELFDATA2MSB */) return 1;
1423 #else
1424 if (header.data != 1 /* ELFDATA2LSB */) return 1;
1425 #endif
1426 if (sizeof(void *) == sizeof(int)) return header.class == 1; /* ELFCLASS32 */
1427 else return header.class == 2; /* ELFCLASS64 */
1428 #endif
1431 static inline char *prepend( char *buffer, const char *str, size_t len )
1433 return memcpy( buffer - len, str, len );
1436 /***********************************************************************
1437 * open_dll_file
1439 * Open a file for a new dll. Helper for open_builtin_pe_file.
1441 static NTSTATUS open_dll_file( const char *name, OBJECT_ATTRIBUTES *attr, HANDLE *mapping )
1443 LARGE_INTEGER size;
1444 NTSTATUS status;
1445 HANDLE handle;
1447 if ((status = open_unix_file( &handle, name, GENERIC_READ | SYNCHRONIZE, attr, 0,
1448 FILE_SHARE_READ | FILE_SHARE_DELETE, FILE_OPEN,
1449 FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE, NULL, 0 )))
1451 if (status != STATUS_OBJECT_PATH_NOT_FOUND && status != STATUS_OBJECT_NAME_NOT_FOUND)
1453 /* if the file exists but failed to open, report the error */
1454 struct stat st;
1455 if (!stat( name, &st )) return status;
1457 /* otherwise continue searching */
1458 return STATUS_DLL_NOT_FOUND;
1461 size.QuadPart = 0;
1462 status = NtCreateSection( mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY |
1463 SECTION_MAP_READ | SECTION_MAP_EXECUTE,
1464 NULL, &size, PAGE_EXECUTE_READ, SEC_IMAGE, handle );
1465 NtClose( handle );
1466 return status;
1470 /***********************************************************************
1471 * open_builtin_pe_file
1473 static NTSTATUS open_builtin_pe_file( const char *name, OBJECT_ATTRIBUTES *attr, void **module,
1474 SIZE_T *size, SECTION_IMAGE_INFORMATION *image_info,
1475 WORD machine, BOOL prefer_native )
1477 NTSTATUS status;
1478 HANDLE mapping;
1480 *module = NULL;
1481 status = open_dll_file( name, attr, &mapping );
1482 if (!status)
1484 status = virtual_map_builtin_module( mapping, module, size, image_info, machine, prefer_native );
1485 NtClose( mapping );
1487 return status;
1491 /***********************************************************************
1492 * open_builtin_so_file
1494 static NTSTATUS open_builtin_so_file( const char *name, OBJECT_ATTRIBUTES *attr, void **module,
1495 SECTION_IMAGE_INFORMATION *image_info,
1496 WORD machine, BOOL prefer_native )
1498 NTSTATUS status;
1499 int fd;
1501 *module = NULL;
1502 if (machine != current_machine) return STATUS_DLL_NOT_FOUND;
1503 if ((fd = open( name, O_RDONLY )) == -1) return STATUS_DLL_NOT_FOUND;
1505 if (check_library_arch( fd ))
1507 pe_image_info_t info;
1509 status = dlopen_dll( name, attr->ObjectName, module, &info, prefer_native );
1510 if (!status) virtual_fill_image_information( &info, image_info );
1511 else if (status != STATUS_IMAGE_ALREADY_LOADED)
1513 ERR( "failed to load .so lib %s\n", debugstr_a(name) );
1514 status = STATUS_PROCEDURE_NOT_FOUND;
1517 else status = STATUS_IMAGE_MACHINE_TYPE_MISMATCH;
1519 close( fd );
1520 return status;
1524 /***********************************************************************
1525 * find_builtin_dll
1527 static NTSTATUS find_builtin_dll( UNICODE_STRING *nt_name, void **module, SIZE_T *size_ptr,
1528 SECTION_IMAGE_INFORMATION *image_info, WORD machine, BOOL prefer_native )
1530 unsigned int i, pos, namepos, namelen, maxlen = 0;
1531 unsigned int len = nt_name->Length / sizeof(WCHAR);
1532 char *ptr = NULL, *file, *ext = NULL;
1533 const char *pe_dir = get_pe_dir( machine );
1534 OBJECT_ATTRIBUTES attr;
1535 NTSTATUS status = STATUS_DLL_NOT_FOUND;
1536 BOOL found_image = FALSE;
1538 for (i = namepos = 0; i < len; i++)
1539 if (nt_name->Buffer[i] == '/' || nt_name->Buffer[i] == '\\') namepos = i + 1;
1540 len -= namepos;
1541 if (!len) return STATUS_DLL_NOT_FOUND;
1542 InitializeObjectAttributes( &attr, nt_name, 0, 0, NULL );
1544 if (build_dir) maxlen = strlen(build_dir) + sizeof("/programs/") + len;
1545 maxlen = max( maxlen, dll_path_maxlen + 1 ) + len + sizeof("/aarch64-windows") + sizeof(".so");
1547 if (!(file = malloc( maxlen ))) return STATUS_NO_MEMORY;
1549 pos = maxlen - len - sizeof(".so");
1550 /* we don't want to depend on the current codepage here */
1551 for (i = 0; i < len; i++)
1553 if (nt_name->Buffer[namepos + i] > 127) goto done;
1554 file[pos + i] = (char)nt_name->Buffer[namepos + i];
1555 if (file[pos + i] >= 'A' && file[pos + i] <= 'Z') file[pos + i] += 'a' - 'A';
1556 else if (file[pos + i] == '.') ext = file + pos + i;
1558 file[--pos] = '/';
1560 if (build_dir)
1562 /* try as a dll */
1563 ptr = file + pos;
1564 namelen = len + 1;
1565 file[pos + len + 1] = 0;
1566 if (ext && !strcmp( ext, ".dll" )) namelen -= 4;
1567 ptr = prepend( ptr, ptr, namelen );
1568 ptr = prepend( ptr, "/dlls", sizeof("/dlls") - 1 );
1569 ptr = prepend( ptr, build_dir, strlen(build_dir) );
1570 status = open_builtin_pe_file( ptr, &attr, module, size_ptr, image_info, machine, prefer_native );
1571 if (status != STATUS_DLL_NOT_FOUND) goto done;
1572 strcpy( file + pos + len + 1, ".so" );
1573 status = open_builtin_so_file( ptr, &attr, module, image_info, machine, prefer_native );
1574 if (status != STATUS_DLL_NOT_FOUND) goto done;
1576 /* now as a program */
1577 ptr = file + pos;
1578 namelen = len + 1;
1579 file[pos + len + 1] = 0;
1580 if (ext && !strcmp( ext, ".exe" )) namelen -= 4;
1581 ptr = prepend( ptr, ptr, namelen );
1582 ptr = prepend( ptr, "/programs", sizeof("/programs") - 1 );
1583 ptr = prepend( ptr, build_dir, strlen(build_dir) );
1584 status = open_builtin_pe_file( ptr, &attr, module, size_ptr, image_info, machine, prefer_native );
1585 if (status != STATUS_DLL_NOT_FOUND) goto done;
1586 strcpy( file + pos + len + 1, ".so" );
1587 status = open_builtin_so_file( ptr, &attr, module, image_info, machine, prefer_native );
1588 if (status != STATUS_DLL_NOT_FOUND) goto done;
1591 for (i = 0; dll_paths[i]; i++)
1593 ptr = file + pos;
1594 file[pos + len + 1] = 0;
1595 ptr = prepend( ptr, pe_dir, strlen(pe_dir) );
1596 ptr = prepend( ptr, dll_paths[i], strlen(dll_paths[i]) );
1597 status = open_builtin_pe_file( ptr, &attr, module, size_ptr, image_info, machine, prefer_native );
1598 /* use so dir for unix lib */
1599 ptr = file + pos;
1600 ptr = prepend( ptr, so_dir, strlen(so_dir) );
1601 ptr = prepend( ptr, dll_paths[i], strlen(dll_paths[i]) );
1602 if (status != STATUS_DLL_NOT_FOUND) goto done;
1603 strcpy( file + pos + len + 1, ".so" );
1604 status = open_builtin_so_file( ptr, &attr, module, image_info, machine, prefer_native );
1605 if (status != STATUS_DLL_NOT_FOUND) goto done;
1606 file[pos + len + 1] = 0;
1607 ptr = prepend( file + pos, dll_paths[i], strlen(dll_paths[i]) );
1608 status = open_builtin_pe_file( ptr, &attr, module, size_ptr, image_info, machine, prefer_native );
1609 if (status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH)
1611 found_image = TRUE;
1612 continue;
1614 if (status != STATUS_DLL_NOT_FOUND) goto done;
1615 strcpy( file + pos + len + 1, ".so" );
1616 status = open_builtin_so_file( ptr, &attr, module, image_info, machine, prefer_native );
1617 if (status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH) found_image = TRUE;
1618 else if (status != STATUS_DLL_NOT_FOUND) goto done;
1621 if (found_image) status = STATUS_IMAGE_MACHINE_TYPE_MISMATCH;
1622 WARN( "cannot find builtin library for %s\n", debugstr_us(nt_name) );
1623 done:
1624 if (status >= 0 && ext)
1626 strcpy( ext, ".so" );
1627 load_builtin_unixlib( *module, ptr );
1629 free( file );
1630 return status;
1634 /***********************************************************************
1635 * load_builtin
1637 * Load the builtin dll if specified by load order configuration.
1638 * Return STATUS_IMAGE_ALREADY_LOADED if we should keep the native one that we have found.
1640 NTSTATUS load_builtin( const pe_image_info_t *image_info, WCHAR *filename,
1641 void **module, SIZE_T *size )
1643 WORD machine = image_info->machine; /* request same machine as the native one */
1644 NTSTATUS status;
1645 UNICODE_STRING nt_name;
1646 SECTION_IMAGE_INFORMATION info;
1647 enum loadorder loadorder;
1649 init_unicode_string( &nt_name, filename );
1650 loadorder = get_load_order( &nt_name );
1652 if (loadorder == LO_DISABLED) return STATUS_DLL_NOT_FOUND;
1654 if (image_info->image_flags & IMAGE_FLAGS_WineBuiltin)
1656 if (loadorder == LO_NATIVE) return STATUS_DLL_NOT_FOUND;
1657 loadorder = LO_BUILTIN_NATIVE; /* load builtin, then fallback to the file we found */
1659 else if (image_info->image_flags & IMAGE_FLAGS_WineFakeDll)
1661 TRACE( "%s is a fake Wine dll\n", debugstr_w(filename) );
1662 if (loadorder == LO_NATIVE) return STATUS_DLL_NOT_FOUND;
1663 loadorder = LO_BUILTIN; /* builtin with no fallback since mapping a fake dll is not useful */
1666 switch (loadorder)
1668 case LO_NATIVE:
1669 case LO_NATIVE_BUILTIN:
1670 return STATUS_IMAGE_ALREADY_LOADED;
1671 case LO_BUILTIN:
1672 return find_builtin_dll( &nt_name, module, size, &info, machine, FALSE );
1673 default:
1674 status = find_builtin_dll( &nt_name, module, size, &info, machine, (loadorder == LO_DEFAULT) );
1675 if (status == STATUS_DLL_NOT_FOUND || status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH)
1676 return STATUS_IMAGE_ALREADY_LOADED;
1677 return status;
1682 /***************************************************************************
1683 * get_machine_wow64_dir
1685 * cf. GetSystemWow64Directory2.
1687 static const WCHAR *get_machine_wow64_dir( WORD machine )
1689 static const WCHAR system32[] = {'\\','?','?','\\','C',':','\\','w','i','n','d','o','w','s','\\','s','y','s','t','e','m','3','2','\\',0};
1690 static const WCHAR syswow64[] = {'\\','?','?','\\','C',':','\\','w','i','n','d','o','w','s','\\','s','y','s','w','o','w','6','4','\\',0};
1691 static const WCHAR sysarm32[] = {'\\','?','?','\\','C',':','\\','w','i','n','d','o','w','s','\\','s','y','s','a','r','m','3','2','\\',0};
1692 static const WCHAR sysx8664[] = {'\\','?','?','\\','C',':','\\','w','i','n','d','o','w','s','\\','s','y','s','x','8','6','6','4','\\',0};
1693 static const WCHAR sysarm64[] = {'\\','?','?','\\','C',':','\\','w','i','n','d','o','w','s','\\','s','y','s','a','r','m','6','4','\\',0};
1695 if (machine == native_machine) machine = IMAGE_FILE_MACHINE_TARGET_HOST;
1697 switch (machine)
1699 case IMAGE_FILE_MACHINE_TARGET_HOST: return system32;
1700 case IMAGE_FILE_MACHINE_I386: return syswow64;
1701 case IMAGE_FILE_MACHINE_ARMNT: return sysarm32;
1702 case IMAGE_FILE_MACHINE_AMD64: return sysx8664;
1703 case IMAGE_FILE_MACHINE_ARM64: return sysarm64;
1704 default: return NULL;
1709 /***************************************************************************
1710 * is_builtin_path
1712 * Check if path is inside a system directory, to support loading builtins
1713 * when the corresponding file doesn't exist yet.
1715 BOOL is_builtin_path( const UNICODE_STRING *path, WORD *machine )
1717 unsigned int i, len = path->Length / sizeof(WCHAR), dirlen;
1718 const WCHAR *sysdir, *p = path->Buffer;
1720 /* only fake builtin existence during prefix bootstrap */
1721 if (!is_prefix_bootstrap) return FALSE;
1723 for (i = 0; i < supported_machines_count; i++)
1725 sysdir = get_machine_wow64_dir( supported_machines[i] );
1726 dirlen = wcslen( sysdir );
1727 if (len <= dirlen) continue;
1728 if (wcsnicmp( p, sysdir, dirlen )) continue;
1729 /* check for remaining path components */
1730 for (p += dirlen, len -= dirlen; len; p++, len--) if (*p == '\\') return FALSE;
1731 *machine = supported_machines[i];
1732 return TRUE;
1734 return FALSE;
1738 /***********************************************************************
1739 * open_main_image
1741 static NTSTATUS open_main_image( WCHAR *image, void **module, SECTION_IMAGE_INFORMATION *info,
1742 enum loadorder loadorder )
1744 static const WCHAR soW[] = {'.','s','o',0};
1745 UNICODE_STRING nt_name;
1746 OBJECT_ATTRIBUTES attr;
1747 pe_image_info_t pe_info;
1748 SIZE_T size = 0;
1749 char *unix_name;
1750 NTSTATUS status;
1751 HANDLE mapping;
1752 WCHAR *p;
1754 if (loadorder == LO_DISABLED) NtTerminateProcess( GetCurrentProcess(), STATUS_DLL_NOT_FOUND );
1756 init_unicode_string( &nt_name, image );
1757 InitializeObjectAttributes( &attr, &nt_name, OBJ_CASE_INSENSITIVE, 0, NULL );
1758 if (nt_to_unix_file_name( &attr, &unix_name, FILE_OPEN )) return STATUS_DLL_NOT_FOUND;
1760 status = open_dll_file( unix_name, &attr, &mapping );
1761 if (!status)
1763 *module = NULL;
1764 status = NtMapViewOfSection( mapping, NtCurrentProcess(), module, 0, 0, NULL, &size,
1765 ViewShare, 0, PAGE_EXECUTE_READ );
1766 if (!status)
1768 NtQuerySection( mapping, SectionImageInformation, info, sizeof(*info), NULL );
1769 if (info->u.s.ComPlusNativeReady) info->Machine = native_machine;
1771 NtClose( mapping );
1773 else if (status == STATUS_INVALID_IMAGE_NOT_MZ && loadorder != LO_NATIVE)
1775 /* remove .so extension from Windows name */
1776 p = image + wcslen(image);
1777 if (p - image > 3 && !wcsicmp( p - 3, soW ))
1779 p[-3] = 0;
1780 nt_name.Length -= 3 * sizeof(WCHAR);
1782 status = dlopen_dll( unix_name, &nt_name, module, &pe_info, FALSE );
1783 if (!status) virtual_fill_image_information( &pe_info, info );
1785 free( unix_name );
1786 return status;
1790 /***********************************************************************
1791 * load_main_exe
1793 NTSTATUS load_main_exe( const WCHAR *dos_name, const char *unix_name, const WCHAR *curdir,
1794 WCHAR **image, void **module )
1796 enum loadorder loadorder = LO_INVALID;
1797 UNICODE_STRING nt_name;
1798 WCHAR *tmp = NULL;
1799 BOOL contains_path;
1800 NTSTATUS status;
1801 SIZE_T size;
1802 struct stat st;
1803 WORD machine;
1805 /* special case for Unix file name */
1806 if (unix_name && unix_name[0] == '/' && !stat( unix_name, &st ))
1808 if ((status = unix_to_nt_file_name( unix_name, image ))) goto failed;
1809 init_unicode_string( &nt_name, *image );
1810 loadorder = get_load_order( &nt_name );
1811 status = open_main_image( *image, module, &main_image_info, loadorder );
1812 if (status != STATUS_DLL_NOT_FOUND) return status;
1813 free( *image );
1816 if (!dos_name)
1818 dos_name = tmp = malloc( (strlen(unix_name) + 1) * sizeof(WCHAR) );
1819 ntdll_umbstowcs( unix_name, strlen(unix_name) + 1, tmp, strlen(unix_name) + 1 );
1821 contains_path = (wcschr( dos_name, '/' ) ||
1822 wcschr( dos_name, '\\' ) ||
1823 (dos_name[0] && dos_name[1] == ':'));
1825 if ((status = get_full_path( dos_name, curdir, image ))) goto failed;
1826 free( tmp );
1828 init_unicode_string( &nt_name, *image );
1829 if (loadorder == LO_INVALID) loadorder = get_load_order( &nt_name );
1831 status = open_main_image( *image, module, &main_image_info, loadorder );
1832 if (status != STATUS_DLL_NOT_FOUND) return status;
1834 /* if path is in system dir, we can load the builtin even if the file itself doesn't exist */
1835 if (loadorder != LO_NATIVE && is_builtin_path( &nt_name, &machine ))
1837 status = find_builtin_dll( &nt_name, module, &size, &main_image_info, machine, FALSE );
1838 if (status != STATUS_DLL_NOT_FOUND) return status;
1840 if (!contains_path) return STATUS_DLL_NOT_FOUND;
1842 failed:
1843 MESSAGE( "wine: failed to open %s: %x\n",
1844 unix_name ? debugstr_a(unix_name) : debugstr_w(dos_name), status );
1845 NtTerminateProcess( GetCurrentProcess(), status );
1846 return status; /* unreached */
1850 /***********************************************************************
1851 * load_start_exe
1853 * Load start.exe as main image.
1855 NTSTATUS load_start_exe( WCHAR **image, void **module )
1857 static const WCHAR startW[] = {'s','t','a','r','t','.','e','x','e',0};
1858 UNICODE_STRING nt_name;
1859 NTSTATUS status;
1860 SIZE_T size;
1862 *image = malloc( sizeof("\\??\\C:\\windows\\system32\\start.exe") * sizeof(WCHAR) );
1863 wcscpy( *image, get_machine_wow64_dir( current_machine ));
1864 wcscat( *image, startW );
1865 init_unicode_string( &nt_name, *image );
1866 status = find_builtin_dll( &nt_name, module, &size, &main_image_info, current_machine, FALSE );
1867 if (status)
1869 MESSAGE( "wine: failed to load start.exe: %x\n", status );
1870 NtTerminateProcess( GetCurrentProcess(), status );
1872 return status;
1876 #ifdef __FreeBSD__
1877 /* The PT_LOAD segments are sorted in increasing order, and the first
1878 * starts at the beginning of the ELF file. By parsing the file, we can
1879 * find that first PT_LOAD segment, from which we can find the base
1880 * address it wanted, and knowing mapbase where the binary was actually
1881 * loaded, use them to work out the relocbase offset. */
1882 static BOOL get_relocbase(caddr_t mapbase, caddr_t *relocbase)
1884 Elf_Half i;
1885 #ifdef _WIN64
1886 const Elf64_Ehdr *elf_header = (Elf64_Ehdr*) mapbase;
1887 #else
1888 const Elf32_Ehdr *elf_header = (Elf32_Ehdr*) mapbase;
1889 #endif
1890 const Elf_Phdr *prog_header = (const Elf_Phdr *)(mapbase + elf_header->e_phoff);
1892 for (i = 0; i < elf_header->e_phnum; i++)
1894 if (prog_header->p_type == PT_LOAD)
1896 caddr_t desired_base = (caddr_t)((prog_header->p_vaddr / prog_header->p_align) * prog_header->p_align);
1897 *relocbase = (caddr_t) (mapbase - desired_base);
1898 return TRUE;
1900 prog_header++;
1902 return FALSE;
1904 #endif
1906 /*************************************************************************
1907 * init_builtin_dll
1909 static void CDECL init_builtin_dll( void *module )
1911 #ifdef HAVE_DLINFO
1912 void *handle = NULL;
1913 struct link_map *map;
1914 void (*init_func)(int, char **, char **) = NULL;
1915 void (**init_array)(int, char **, char **) = NULL;
1916 ULONG_PTR i, init_arraysz = 0;
1917 #ifdef _WIN64
1918 const Elf64_Dyn *dyn;
1919 #else
1920 const Elf32_Dyn *dyn;
1921 #endif
1923 if (!(handle = get_builtin_so_handle( module ))) return;
1924 if (dlinfo( handle, RTLD_DI_LINKMAP, &map )) map = NULL;
1925 release_builtin_module( module );
1926 if (!map) return;
1928 for (dyn = map->l_ld; dyn->d_tag; dyn++)
1930 caddr_t relocbase = (caddr_t)map->l_addr;
1932 #ifdef __FreeBSD__
1933 /* On older FreeBSD versions, l_addr was the absolute load address, now it's the relocation offset. */
1934 if (offsetof(struct link_map, l_addr) == 0)
1935 if (!get_relocbase(map->l_addr, &relocbase))
1936 return;
1937 #endif
1938 switch (dyn->d_tag)
1940 case 0x60009990: init_array = (void *)(relocbase + dyn->d_un.d_val); break;
1941 case 0x60009991: init_arraysz = dyn->d_un.d_val; break;
1942 case 0x60009992: init_func = (void *)(relocbase + dyn->d_un.d_val); break;
1946 TRACE( "%p: got init_func %p init_array %p %lu\n", module, init_func, init_array, init_arraysz );
1948 if (init_func) init_func( main_argc, main_argv, main_envp );
1950 if (init_array)
1951 for (i = 0; i < init_arraysz / sizeof(*init_array); i++)
1952 init_array[i]( main_argc, main_argv, main_envp );
1953 #endif
1957 /***********************************************************************
1958 * load_ntdll
1960 static void load_ntdll(void)
1962 static WCHAR path[] = {'\\','?','?','\\','C',':','\\','w','i','n','d','o','w','s','\\',
1963 's','y','s','t','e','m','3','2','\\','n','t','d','l','l','.','d','l','l',0};
1964 const char *pe_dir = get_pe_dir( current_machine );
1965 NTSTATUS status;
1966 SECTION_IMAGE_INFORMATION info;
1967 OBJECT_ATTRIBUTES attr;
1968 UNICODE_STRING str;
1969 void *module;
1970 SIZE_T size = 0;
1971 char *name;
1973 init_unicode_string( &str, path );
1974 InitializeObjectAttributes( &attr, &str, 0, 0, NULL );
1976 name = malloc( strlen( ntdll_dir ) + strlen( pe_dir ) + sizeof("/ntdll.dll.so") );
1977 if (build_dir) sprintf( name, "%s/ntdll.dll", ntdll_dir );
1978 else sprintf( name, "%s%s/ntdll.dll", dll_dir, pe_dir );
1979 status = open_builtin_pe_file( name, &attr, &module, &size, &info, current_machine, FALSE );
1980 if (status == STATUS_DLL_NOT_FOUND)
1982 sprintf( name, "%s/ntdll.dll.so", ntdll_dir );
1983 status = open_builtin_so_file( name, &attr, &module, &info, current_machine, FALSE );
1985 if (status == STATUS_IMAGE_NOT_AT_BASE) relocate_ntdll( module );
1986 else if (status) fatal_error( "failed to load %s error %x\n", name, status );
1987 free( name );
1988 load_ntdll_functions( module );
1989 ntdll_module = module;
1993 /***********************************************************************
1994 * load_wow64_ntdll
1996 static void load_wow64_ntdll( USHORT machine )
1998 static const WCHAR ntdllW[] = {'n','t','d','l','l','.','d','l','l',0};
1999 SECTION_IMAGE_INFORMATION info;
2000 UNICODE_STRING nt_name;
2001 void *module;
2002 NTSTATUS status;
2003 SIZE_T size;
2004 WCHAR *path = malloc( sizeof("\\??\\C:\\windows\\system32\\ntdll.dll") * sizeof(WCHAR) );
2006 wcscpy( path, get_machine_wow64_dir( machine ));
2007 wcscat( path, ntdllW );
2008 init_unicode_string( &nt_name, path );
2009 status = find_builtin_dll( &nt_name, &module, &size, &info, machine, FALSE );
2010 switch (status)
2012 case STATUS_IMAGE_NOT_AT_BASE:
2013 relocate_ntdll( module );
2014 /* fall through */
2015 case STATUS_SUCCESS:
2016 load_ntdll_wow64_functions( module );
2017 TRACE("loaded %s at %p\n", debugstr_w(path), module );
2018 break;
2019 default:
2020 ERR( "failed to load %s error %x\n", debugstr_w(path), status );
2021 break;
2023 free( path );
2027 /***********************************************************************
2028 * get_image_address
2030 static ULONG_PTR get_image_address(void)
2032 #ifdef HAVE_GETAUXVAL
2033 ULONG_PTR size, num, phdr_addr = getauxval( AT_PHDR );
2034 ElfW(Phdr) *phdr;
2036 if (!phdr_addr) return 0;
2037 phdr = (ElfW(Phdr) *)phdr_addr;
2038 size = getauxval( AT_PHENT );
2039 num = getauxval( AT_PHNUM );
2040 while (num--)
2042 if (phdr->p_type == PT_PHDR) return phdr_addr - phdr->p_offset;
2043 phdr = (ElfW(Phdr) *)((char *)phdr + size);
2045 #elif defined(__APPLE__) && defined(TASK_DYLD_INFO)
2046 struct task_dyld_info dyld_info;
2047 mach_msg_type_number_t size = TASK_DYLD_INFO_COUNT;
2049 if (task_info(mach_task_self(), TASK_DYLD_INFO, (task_info_t)&dyld_info, &size) == KERN_SUCCESS)
2050 return dyld_info.all_image_info_addr;
2051 #endif
2052 return 0;
2056 /***********************************************************************
2057 * unix_funcs
2059 static struct unix_funcs unix_funcs =
2061 load_so_dll,
2062 init_builtin_dll,
2063 unwind_builtin_dll,
2064 RtlGetSystemTimePrecise,
2065 #ifdef __aarch64__
2066 NtCurrentTeb,
2067 #endif
2071 /***********************************************************************
2072 * start_main_thread
2074 static void start_main_thread(void)
2076 SYSTEM_SERVICE_TABLE syscall_table = { (ULONG_PTR *)syscalls, NULL, ARRAY_SIZE(syscalls), syscall_args };
2077 NTSTATUS status;
2078 TEB *teb = virtual_alloc_first_teb();
2080 signal_init_threading();
2081 signal_alloc_thread( teb );
2082 signal_init_thread( teb );
2083 dbg_init();
2084 startup_info_size = server_init_process();
2085 virtual_map_user_shared_data();
2086 init_cpu_info();
2087 init_files();
2088 load_libwine();
2089 init_startup_info();
2090 if (p___wine_main_argc) *p___wine_main_argc = main_argc;
2091 if (p___wine_main_argv) *p___wine_main_argv = main_argv;
2092 if (p___wine_main_wargv) *p___wine_main_wargv = main_wargv;
2093 *(ULONG_PTR *)&peb->CloudFileFlags = get_image_address();
2094 set_load_order_app_name( main_wargv[0] );
2095 init_thread_stack( teb, is_win64 ? 0x7fffffff : 0, 0, 0 );
2096 NtCreateKeyedEvent( &keyed_event, GENERIC_READ | GENERIC_WRITE, NULL, 0 );
2097 load_ntdll();
2098 if (main_image_info.Machine != current_machine) load_wow64_ntdll( main_image_info.Machine );
2099 ntdll_init_syscalls( 0, &syscall_table, p__wine_syscall_dispatcher );
2100 status = p__wine_set_unix_funcs( NTDLL_UNIXLIB_VERSION, &unix_funcs );
2101 if (status == STATUS_REVISION_MISMATCH)
2103 ERR( "ntdll library version mismatch\n" );
2104 NtTerminateProcess( GetCurrentProcess(), status );
2106 server_init_process_done();
2109 #ifdef __ANDROID__
2111 #ifndef WINE_JAVA_CLASS
2112 #define WINE_JAVA_CLASS "org/winehq/wine/WineActivity"
2113 #endif
2115 JavaVM *java_vm = NULL;
2116 jobject java_object = 0;
2117 unsigned short java_gdt_sel = 0;
2119 /* main Wine initialisation */
2120 static jstring wine_init_jni( JNIEnv *env, jobject obj, jobjectArray cmdline, jobjectArray environment )
2122 char **argv;
2123 char *str;
2124 char error[1024];
2125 int i, argc, length;
2127 /* get the command line array */
2129 argc = (*env)->GetArrayLength( env, cmdline );
2130 for (i = length = 0; i < argc; i++)
2132 jobject str_obj = (*env)->GetObjectArrayElement( env, cmdline, i );
2133 length += (*env)->GetStringUTFLength( env, str_obj ) + 1;
2136 argv = malloc( (argc + 1) * sizeof(*argv) + length );
2137 str = (char *)(argv + argc + 1);
2138 for (i = 0; i < argc; i++)
2140 jobject str_obj = (*env)->GetObjectArrayElement( env, cmdline, i );
2141 length = (*env)->GetStringUTFLength( env, str_obj );
2142 (*env)->GetStringUTFRegion( env, str_obj, 0,
2143 (*env)->GetStringLength( env, str_obj ), str );
2144 argv[i] = str;
2145 str[length] = 0;
2146 str += length + 1;
2148 argv[argc] = NULL;
2150 /* set the environment variables */
2152 if (environment)
2154 int count = (*env)->GetArrayLength( env, environment );
2155 for (i = 0; i < count - 1; i += 2)
2157 jobject var_obj = (*env)->GetObjectArrayElement( env, environment, i );
2158 jobject val_obj = (*env)->GetObjectArrayElement( env, environment, i + 1 );
2159 const char *var = (*env)->GetStringUTFChars( env, var_obj, NULL );
2161 if (val_obj)
2163 const char *val = (*env)->GetStringUTFChars( env, val_obj, NULL );
2164 setenv( var, val, 1 );
2165 if (!strcmp( var, "LD_LIBRARY_PATH" ))
2167 void (*update_func)( const char * ) = dlsym( RTLD_DEFAULT,
2168 "android_update_LD_LIBRARY_PATH" );
2169 if (update_func) update_func( val );
2171 else if (!strcmp( var, "WINEDEBUGLOG" ))
2173 int fd = open( val, O_WRONLY | O_CREAT | O_APPEND, 0666 );
2174 if (fd != -1)
2176 dup2( fd, 2 );
2177 close( fd );
2180 (*env)->ReleaseStringUTFChars( env, val_obj, val );
2182 else unsetenv( var );
2184 (*env)->ReleaseStringUTFChars( env, var_obj, var );
2188 java_object = (*env)->NewGlobalRef( env, obj );
2190 init_paths( argv );
2191 virtual_init();
2192 init_environment( argc, argv, environ );
2194 #ifdef __i386__
2196 unsigned short java_fs;
2197 __asm__( "mov %%fs,%0" : "=r" (java_fs) );
2198 if (!(java_fs & 4)) java_gdt_sel = java_fs;
2199 __asm__( "mov %0,%%fs" :: "r" (0) );
2200 start_main_thread();
2201 __asm__( "mov %0,%%fs" :: "r" (java_fs) );
2203 #else
2204 start_main_thread();
2205 #endif
2206 return (*env)->NewStringUTF( env, error );
2209 jint JNI_OnLoad( JavaVM *vm, void *reserved )
2211 static const JNINativeMethod method =
2213 "wine_init", "([Ljava/lang/String;[Ljava/lang/String;)Ljava/lang/String;", wine_init_jni
2216 JNIEnv *env;
2217 jclass class;
2219 java_vm = vm;
2220 if ((*vm)->AttachCurrentThread( vm, &env, NULL ) != JNI_OK) return JNI_ERR;
2221 if (!(class = (*env)->FindClass( env, WINE_JAVA_CLASS ))) return JNI_ERR;
2222 (*env)->RegisterNatives( env, class, &method, 1 );
2223 return JNI_VERSION_1_6;
2226 #endif /* __ANDROID__ */
2228 #ifdef __APPLE__
2229 static void *apple_wine_thread( void *arg )
2231 start_main_thread();
2232 return NULL;
2235 /***********************************************************************
2236 * apple_create_wine_thread
2238 * Spin off a secondary thread to complete Wine initialization, leaving
2239 * the original thread for the Mac frameworks.
2241 * Invoked as a CFRunLoopSource perform callback.
2243 static void apple_create_wine_thread( void *arg )
2245 pthread_t thread;
2246 pthread_attr_t attr;
2248 pthread_attr_init( &attr );
2249 pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE );
2250 if (pthread_create( &thread, &attr, apple_wine_thread, NULL )) exit(1);
2251 pthread_attr_destroy( &attr );
2255 /***********************************************************************
2256 * apple_main_thread
2258 * Park the process's original thread in a Core Foundation run loop for
2259 * use by the Mac frameworks, especially receiving and handling
2260 * distributed notifications. Spin off a new thread for the rest of the
2261 * Wine initialization.
2263 static void apple_main_thread(void)
2265 CFRunLoopSourceContext source_context = { 0 };
2266 CFRunLoopSourceRef source;
2268 if (!pthread_main_np()) return;
2270 /* Multi-processing Services can get confused about the main thread if the
2271 * first time it's used is on a secondary thread. Use it here to make sure
2272 * that doesn't happen. */
2273 MPTaskIsPreemptive(MPCurrentTaskID());
2275 /* Give ourselves the best chance of having the distributed notification
2276 * center scheduled on this thread's run loop. In theory, it's scheduled
2277 * in the first thread to ask for it. */
2278 CFNotificationCenterGetDistributedCenter();
2280 /* We use this run loop source for two purposes. First, a run loop exits
2281 * if it has no more sources scheduled. So, we need at least one source
2282 * to keep the run loop running. Second, although it's not critical, it's
2283 * preferable for the Wine initialization to not proceed until we know
2284 * the run loop is running. So, we signal our source immediately after
2285 * adding it and have its callback spin off the Wine thread. */
2286 source_context.perform = apple_create_wine_thread;
2287 source = CFRunLoopSourceCreate( NULL, 0, &source_context );
2288 CFRunLoopAddSource( CFRunLoopGetCurrent(), source, kCFRunLoopCommonModes );
2289 CFRunLoopSourceSignal( source );
2290 CFRelease( source );
2291 CFRunLoopRun(); /* Should never return, except on error. */
2293 #endif /* __APPLE__ */
2296 #ifdef __ANDROID__
2298 static int pre_exec(void)
2300 #if defined(__i386__) || defined(__x86_64__)
2301 return 1; /* we have a preloader */
2302 #else
2303 return 0; /* no exec needed */
2304 #endif
2307 #elif defined(__linux__) && (defined(__i386__) || defined(__arm__))
2309 static void check_vmsplit( void *stack )
2311 if (stack < (void *)0x80000000)
2313 /* if the stack is below 0x80000000, assume we can safely try a munmap there */
2314 if (munmap( (void *)0x80000000, 1 ) == -1 && errno == EINVAL)
2315 ERR( "Warning: memory above 0x80000000 doesn't seem to be accessible.\n"
2316 "Wine requires a 3G/1G user/kernel memory split to work properly.\n" );
2320 static int pre_exec(void)
2322 int temp;
2324 check_vmsplit( &temp );
2325 return 1; /* we have a preloader on x86/arm */
2328 #elif defined(__linux__) && (defined(__x86_64__) || defined(__aarch64__))
2330 static int pre_exec(void)
2332 return 1; /* we have a preloader on x86-64/arm64 */
2335 #elif defined(__APPLE__) && (defined(__i386__) || defined(__x86_64__))
2337 static int pre_exec(void)
2339 return 1; /* we have a preloader */
2342 #elif (defined(__FreeBSD__) || defined (__FreeBSD_kernel__) || defined(__DragonFly__))
2344 static int pre_exec(void)
2346 struct rlimit rl;
2348 rl.rlim_cur = 0x02000000;
2349 rl.rlim_max = 0x02000000;
2350 setrlimit( RLIMIT_DATA, &rl );
2351 return 1;
2354 #else
2356 static int pre_exec(void)
2358 return 0; /* no exec needed */
2361 #endif
2364 /***********************************************************************
2365 * check_command_line
2367 * Check if command line is one that needs to be handled specially.
2369 static void check_command_line( int argc, char *argv[] )
2371 static const char usage[] =
2372 "Usage: wine PROGRAM [ARGUMENTS...] Run the specified program\n"
2373 " wine --help Display this help and exit\n"
2374 " wine --version Output version information and exit";
2376 if (argc <= 1)
2378 fprintf( stderr, "%s\n", usage );
2379 exit(1);
2381 if (!strcmp( argv[1], "--help" ))
2383 printf( "%s\n", usage );
2384 exit(0);
2386 if (!strcmp( argv[1], "--version" ))
2388 printf( "%s\n", wine_build );
2389 exit(0);
2394 /***********************************************************************
2395 * __wine_main
2397 * Main entry point called by the wine loader.
2399 void __wine_main( int argc, char *argv[], char *envp[] )
2401 init_paths( argv );
2403 if (!getenv( "WINELOADERNOEXEC" )) /* first time around */
2405 check_command_line( argc, argv );
2406 if (pre_exec())
2408 static char noexec[] = "WINELOADERNOEXEC=1";
2409 char **new_argv = malloc( (argc + 2) * sizeof(*argv) );
2411 memcpy( new_argv + 1, argv, (argc + 1) * sizeof(*argv) );
2412 putenv( noexec );
2413 loader_exec( argv0, new_argv, current_machine );
2414 fatal_error( "could not exec the wine loader\n" );
2418 #ifdef RLIMIT_NOFILE
2419 set_max_limit( RLIMIT_NOFILE );
2420 #endif
2421 #ifdef RLIMIT_AS
2422 set_max_limit( RLIMIT_AS );
2423 #endif
2425 virtual_init();
2426 init_environment( argc, argv, envp );
2428 #ifdef __APPLE__
2429 apple_main_thread();
2430 #endif
2431 start_main_thread();