diff --git a/dlls/ntdll/env.c b/dlls/ntdll/env.c index 9d648ff0fb2..f615945cd33 100644 --- a/dlls/ntdll/env.c +++ b/dlls/ntdll/env.c @@ -106,69 +106,6 @@ static void set_wow64_environment( WCHAR **env ) } -/*********************************************************************** - * is_path_prefix - */ -static inline BOOL is_path_prefix( const WCHAR *prefix, const WCHAR *path, const WCHAR *file ) -{ - DWORD len = wcslen( prefix ); - - if (wcsnicmp( path, prefix, len )) return FALSE; - while (path[len] == '\\') len++; - return path + len == file; -} - - -/*********************************************************************** - * get_image_path - */ -static void get_image_path( const WCHAR *name, WCHAR *full_name, UINT size ) -{ - WCHAR *load_path, *file_part; - DWORD len; - - if (RtlDetermineDosPathNameType_U( name ) != RELATIVE_PATH || - wcschr( name, '/' ) || wcschr( name, '\\' )) - { - len = RtlGetFullPathName_U( name, size, full_name, &file_part ); - if (!len || len > size) goto failed; - /* try first without extension */ - if (RtlDoesFileExists_U( full_name )) return; - if (len < size - 4 * sizeof(WCHAR) && !wcschr( file_part, '.' )) - { - wcscat( file_part, L".exe" ); - if (RtlDoesFileExists_U( full_name )) return; - } - /* check for builtin path inside system directory */ - if (!is_path_prefix( system_dir, full_name, file_part )) - { - if (!is_win64 && !is_wow64) goto failed; - if (!is_path_prefix( syswow64_dir, full_name, file_part )) goto failed; - } - } - else - { - RtlGetExePath( name, &load_path ); - len = RtlDosSearchPath_U( load_path, name, L".exe", size, full_name, &file_part ); - RtlReleasePath( load_path ); - if (!len || len > size) - { - /* build builtin path inside system directory */ - len = wcslen( system_dir ); - if (wcslen( name ) >= size/sizeof(WCHAR) - 4 - len) goto failed; - wcscpy( full_name, system_dir ); - wcscat( full_name, name ); - if (!wcschr( name, '.' )) wcscat( full_name, L".exe" ); - } - } - return; - -failed: - MESSAGE( "wine: cannot find %s\n", debugstr_w(name) ); - RtlExitUserProcess( STATUS_DLL_NOT_FOUND ); -} - - /****************************************************************************** * RtlCreateEnvironment [NTDLL.@] */ @@ -700,10 +637,10 @@ void WINAPI RtlDestroyProcessParameters( RTL_USER_PROCESS_PARAMETERS *params ) */ void init_user_process_params(void) { - WCHAR *env, *load_path, *dummy, image[MAX_PATH]; + WCHAR *env, *load_path, *dummy; SIZE_T env_size; RTL_USER_PROCESS_PARAMETERS *new_params, *params = NtCurrentTeb()->Peb->ProcessParameters; - UNICODE_STRING curdir, dllpath, cmdline; + UNICODE_STRING curdir, dllpath; /* environment needs to be a separate memory block */ env_size = params->EnvironmentSize; @@ -717,15 +654,6 @@ void init_user_process_params(void) if (!params->DllPath.MaximumLength) /* not inherited from parent process */ { - get_image_path( params->ImagePathName.Buffer, image, sizeof(image) ); - RtlInitUnicodeString( ¶ms->ImagePathName, image ); - - cmdline.Length = params->ImagePathName.Length + params->CommandLine.MaximumLength + 3 * sizeof(WCHAR); - cmdline.MaximumLength = cmdline.Length + sizeof(WCHAR); - cmdline.Buffer = RtlAllocateHeap( GetProcessHeap(), 0, cmdline.MaximumLength ); - swprintf( cmdline.Buffer, cmdline.MaximumLength / sizeof(WCHAR), - L"\"%s\" %s", params->ImagePathName.Buffer, params->CommandLine.Buffer ); - LdrGetDllPath( params->ImagePathName.Buffer, 0, &load_path, &dummy ); RtlInitUnicodeString( &dllpath, load_path ); @@ -733,7 +661,7 @@ void init_user_process_params(void) params->Environment = NULL; /* avoid copying it */ if (RtlCreateProcessParametersEx( &new_params, ¶ms->ImagePathName, &dllpath, ¶ms->CurrentDirectory.DosPath, - &cmdline, NULL, ¶ms->ImagePathName, NULL, NULL, NULL, + ¶ms->CommandLine, NULL, ¶ms->ImagePathName, NULL, NULL, NULL, PROCESS_PARAMS_FLAG_NORMALIZED )) return; @@ -747,7 +675,6 @@ void init_user_process_params(void) new_params->wShowWindow = params->wShowWindow; NtCurrentTeb()->Peb->ProcessParameters = params = new_params; - RtlFreeUnicodeString( &cmdline ); RtlReleasePath( load_path ); } diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index ff88c6c5b5e..bf03c1f9baa 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -68,7 +68,6 @@ const WCHAR windows_dir[] = L"C:\\windows"; const WCHAR system_dir[] = L"C:\\windows\\system32\\"; const WCHAR syswow64_dir[] = L"C:\\windows\\syswow64\\"; -static const BOOL is_win64 = (sizeof(void *) > sizeof(int)); BOOL is_wow64 = FALSE; /* system search path */ @@ -2410,6 +2409,46 @@ static NTSTATUS load_builtin_dll( LPCWSTR load_path, UNICODE_STRING *nt_name, } +/************************************************************************* + * build_main_module + * + * Build the module data for the main image. + */ +static void build_main_module(void) +{ + SECTION_IMAGE_INFORMATION info; + UNICODE_STRING nt_name; + WINE_MODREF *wm; + NTSTATUS status; + RTL_USER_PROCESS_PARAMETERS *params = NtCurrentTeb()->Peb->ProcessParameters; + void *module = NtCurrentTeb()->Peb->ImageBaseAddress; + + NtQueryInformationProcess( GetCurrentProcess(), ProcessImageInformation, &info, sizeof(info), NULL ); + if (info.ImageCharacteristics & IMAGE_FILE_DLL) + { + MESSAGE( "wine: %s is a dll, not an executable\n", debugstr_us(¶ms->ImagePathName) ); + NtTerminateProcess( GetCurrentProcess(), STATUS_INVALID_IMAGE_FORMAT ); + } +#ifdef _WIN64 + if (!convert_to_pe64( module, &info )) + { + status = STATUS_INVALID_IMAGE_FORMAT; + goto failed; + } +#endif + status = RtlDosPathNameToNtPathName_U_WithStatus( params->ImagePathName.Buffer, &nt_name, NULL, NULL ); + if (status) goto failed; + status = build_module( params->DllPath.Buffer, &nt_name, &module, &info, + NULL, DONT_RESOLVE_DLL_REFERENCES, &wm ); + RtlFreeUnicodeString( &nt_name ); + if (!status) return; +failed: + MESSAGE( "wine: failed to create main module for %s, status %x\n", + debugstr_us(¶ms->ImagePathName), status ); + NtTerminateProcess( GetCurrentProcess(), status ); +} + + /*********************************************************************** * find_actctx_dll * @@ -3894,28 +3933,6 @@ BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved ) } -/*********************************************************************** - * restart_winevdm - */ -static void restart_winevdm( RTL_USER_PROCESS_PARAMETERS *params ) -{ - DWORD len; - WCHAR *appname, *cmdline; - - len = wcslen(system_dir) + wcslen(L"winevdm.exe") + 1; - appname = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) ); - wcscpy( appname, (is_win64 || is_wow64) ? syswow64_dir : system_dir ); - wcscat( appname, L"winevdm.exe" ); - - len += 16 + wcslen(params->ImagePathName.Buffer) + wcslen(params->CommandLine.Buffer); - cmdline = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) ); - swprintf( cmdline, len, L"%s --app-name \"%s\" %s", - appname, params->ImagePathName.Buffer, params->CommandLine.Buffer ); - - RtlInitUnicodeString( ¶ms->ImagePathName, appname ); - RtlInitUnicodeString( ¶ms->CommandLine, cmdline ); -} - #ifndef _WIN64 void *Wow64Transition = NULL; @@ -3993,54 +4010,7 @@ static NTSTATUS process_init(void) load_global_options(); version_init(); - - if (!(status = load_dll( params->DllPath.Buffer, params->ImagePathName.Buffer, NULL, - DONT_RESOLVE_DLL_REFERENCES, &wm ))) - { - peb->ImageBaseAddress = wm->ldr.DllBase; - TRACE( "main exe loaded %s at %p\n", debugstr_us(¶ms->ImagePathName), peb->ImageBaseAddress ); - if (wm->ldr.Flags & LDR_IMAGE_IS_DLL) - { - MESSAGE( "wine: %s is a dll, not an executable\n", debugstr_w(wm->ldr.FullDllName.Buffer) ); - NtTerminateProcess( GetCurrentProcess(), STATUS_INVALID_IMAGE_FORMAT ); - } - } - else - { - switch (status) - { - case STATUS_INVALID_IMAGE_NOT_MZ: - { - WCHAR *p = wcsrchr( params->ImagePathName.Buffer, '.' ); - if (p && (!wcsicmp( p, L".com" ) || !wcsicmp( p, L".pif" ))) - { - restart_winevdm( params ); - status = STATUS_INVALID_IMAGE_WIN_16; - } - return status; - } - case STATUS_INVALID_IMAGE_WIN_16: - case STATUS_INVALID_IMAGE_NE_FORMAT: - case STATUS_INVALID_IMAGE_PROTECT: - restart_winevdm( params ); - return status; - case STATUS_CONFLICTING_ADDRESSES: - case STATUS_NO_MEMORY: - case STATUS_INVALID_IMAGE_FORMAT: - return status; - case STATUS_INVALID_IMAGE_WIN_64: - ERR( "%s 64-bit application not supported in 32-bit prefix\n", - debugstr_us(¶ms->ImagePathName) ); - break; - case STATUS_DLL_NOT_FOUND: - ERR( "%s not found\n", debugstr_us(¶ms->ImagePathName) ); - break; - default: - ERR( "failed to load %s, error %x\n", debugstr_us(¶ms->ImagePathName), status ); - break; - } - NtTerminateProcess( GetCurrentProcess(), status ); - } + build_main_module(); #ifndef _WIN64 if (NtCurrentTeb64()) diff --git a/dlls/ntdll/unix/env.c b/dlls/ntdll/unix/env.c index a635a8c6944..38bd56241ad 100644 --- a/dlls/ntdll/unix/env.c +++ b/dlls/ntdll/unix/env.c @@ -936,6 +936,22 @@ static WCHAR **build_wargv( char **argv ) } +/*********************************************************************** + * prepend_main_wargv + * + * Rebuild the main_wargv array with some extra arguments in front. + */ +static void prepend_main_wargv( const WCHAR **args, int count ) +{ + WCHAR **argv = malloc( (main_argc + count + 1) * sizeof(*argv) ); + + memcpy( argv, args, count * sizeof(*argv) ); + memcpy( argv + count, main_wargv, (main_argc + 1) * sizeof(*argv) ); + main_wargv = argv; + main_argc += count; +} + + /* Unix format is: lang[_country][.charset][@modifier] * Windows format is: lang[-script][-country][_modifier] */ static BOOL unix_to_win_locale( const char *unix_name, char *win_name ) @@ -1669,8 +1685,8 @@ static WCHAR *build_command_line( WCHAR **wargv ) int i, bcount; WCHAR *a; - /* check for quotes and spaces in this argument */ - has_space = !**arg || wcschr( *arg, ' ' ) || wcschr( *arg, '\t' ); + /* check for quotes and spaces in this argument (first arg is always quoted) */ + has_space = (arg == wargv) || !**arg || wcschr( *arg, ' ' ) || wcschr( *arg, '\t' ); has_quote = wcschr( *arg, '"' ) != NULL; /* now transfer it to the command line */ @@ -1831,11 +1847,12 @@ static RTL_USER_PROCESS_PARAMETERS *build_initial_params(void) { static const WCHAR pathW[] = {'P','A','T','H'}; RTL_USER_PROCESS_PARAMETERS *params = NULL; + SECTION_IMAGE_INFORMATION image_info; SIZE_T size, env_pos, env_size; - WCHAR *dst, *p, *path = NULL; - WCHAR *cmdline = build_command_line( main_wargv + 1 ); + WCHAR *dst, *image, *cmdline, *p, *path = NULL; WCHAR *env = get_initial_environment( &env_pos, &env_size ); WCHAR *curdir = get_initial_directory(); + void *module; NTSTATUS status; /* store the initial PATH value */ @@ -1855,6 +1872,37 @@ static RTL_USER_PROCESS_PARAMETERS *build_initial_params(void) add_registry_environment( &env, &env_pos, &env_size ); env[env_pos++] = 0; + status = load_main_exe( main_wargv[0], curdir, &image, &module, &image_info ); + if (!status && image_info.Machine != current_machine) /* need to restart for Wow64 */ + { + NtUnmapViewOfSection( GetCurrentProcess(), module ); + status = STATUS_INVALID_IMAGE_FORMAT; + } + + if (status) /* try launching it through start.exe */ + { + static const WCHAR startW[] = {'C',':','\\','w','i','n','d','o','w','s','\\', + 's','y','s','t','e','m','3','2','\\','s','t','a','r','t','.','e','x','e',0}; + static const WCHAR slashwW[] = {'/','w',0}; + static const WCHAR slashbW[] = {'/','b',0}; + const WCHAR *args[] = { startW, slashwW, slashbW }; + + free( image ); + prepend_main_wargv( args, 3 ); + if ((status = load_main_exe( startW, curdir, &image, &module, &image_info ))) + { + MESSAGE( "wine: failed to start %s\n", debugstr_w(main_wargv[2]) ); + NtTerminateProcess( GetCurrentProcess(), status ); + } + } + else main_wargv[0] = get_dos_path( image ); + + NtCurrentTeb()->Peb->ImageBaseAddress = module; + cmdline = build_command_line( main_wargv ); + + TRACE( "image %s cmdline %s dir %s\n", + debugstr_w(main_wargv[0]), debugstr_w(cmdline), debugstr_w(curdir) ); + size = (sizeof(*params) + MAX_PATH * sizeof(WCHAR) /* curdir */ + (wcslen( cmdline ) + 1) * sizeof(WCHAR) /* command line */ @@ -1897,10 +1945,12 @@ static RTL_USER_PROCESS_PARAMETERS *build_initial_params(void) */ void init_startup_info(void) { - WCHAR *src, *dst, *env; + WCHAR *src, *dst, *env, *image; + void *module; NTSTATUS status; SIZE_T size, info_size, env_size, env_pos; RTL_USER_PROCESS_PARAMETERS *params = NULL; + SECTION_IMAGE_INFORMATION image_info; startup_info_t *info; if (!startup_info_size) @@ -1992,6 +2042,16 @@ void init_startup_info(void) free( env ); free( info ); NtCurrentTeb()->Peb->ProcessParameters = params; + + status = load_main_exe( params->ImagePathName.Buffer, params->CommandLine.Buffer, + &image, &module, &image_info ); + if (status) + { + MESSAGE( "wine: failed to start %s\n", debugstr_us(¶ms->ImagePathName) ); + NtTerminateProcess( GetCurrentProcess(), status ); + } + NtCurrentTeb()->Peb->ImageBaseAddress = module; + free( image ); } diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index 233778df3b2..35ff3c7dea7 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -3493,6 +3493,141 @@ NTSTATUS CDECL wine_unix_to_nt_file_name( const char *name, WCHAR *buffer, SIZE_ } +/****************************************************************** + * collapse_path + * + * Get rid of . and .. components in the path. + */ +static void collapse_path( WCHAR *path ) +{ + WCHAR *p, *start, *next; + + /* convert every / into a \ */ + for (p = path; *p; p++) if (*p == '/') *p = '\\'; + + p = path + 4; + while (*p && *p != '\\') p++; + start = p + 1; + + /* collapse duplicate backslashes */ + next = start; + for (p = next; *p; p++) if (*p != '\\' || next[-1] != '\\') *next++ = *p; + *next = 0; + + p = start; + while (*p) + { + if (*p == '.') + { + switch(p[1]) + { + case '\\': /* .\ component */ + next = p + 2; + memmove( p, next, (wcslen(next) + 1) * sizeof(WCHAR) ); + continue; + case 0: /* final . */ + if (p > start) p--; + *p = 0; + continue; + case '.': + if (p[2] == '\\') /* ..\ component */ + { + next = p + 3; + if (p > start) + { + p--; + while (p > start && p[-1] != '\\') p--; + } + memmove( p, next, (wcslen(next) + 1) * sizeof(WCHAR) ); + continue; + } + else if (!p[2]) /* final .. */ + { + if (p > start) + { + p--; + while (p > start && p[-1] != '\\') p--; + if (p > start) p--; + } + *p = 0; + continue; + } + break; + } + } + /* skip to the next component */ + while (*p && *p != '\\') p++; + if (*p == '\\') + { + /* remove last dot in previous dir name */ + if (p > start && p[-1] == '.') memmove( p-1, p, (wcslen(p) + 1) * sizeof(WCHAR) ); + else p++; + } + } + + /* remove trailing spaces and dots (yes, Windows really does that, don't ask) */ + while (p > start && (p[-1] == ' ' || p[-1] == '.')) p--; + *p = 0; +} + + +#define IS_SEPARATOR(ch) ((ch) == '\\' || (ch) == '/') + +/*********************************************************************** + * get_full_path + * + * Simplified version of RtlGetFullPathName_U. + */ +NTSTATUS get_full_path( const WCHAR *name, const WCHAR *curdir, WCHAR **path ) +{ + static const WCHAR uncW[] = {'\\','?','?','\\','U','N','C','\\',0}; + static const WCHAR devW[] = {'\\','?','?','\\',0}; + static const WCHAR unixW[] = {'u','n','i','x'}; + WCHAR *ret, root[] = {'\\','?','?','\\','C',':','\\',0}; + NTSTATUS status = STATUS_SUCCESS; + const WCHAR *prefix; + + if (IS_SEPARATOR(name[0]) && IS_SEPARATOR(name[1])) /* \\ prefix */ + { + if ((name[2] == '.' || name[2] == '?') && IS_SEPARATOR(name[3])) /* \\?\ device */ + { + name += 4; + if (!wcsnicmp( name, unixW, 4 ) && IS_SEPARATOR(name[4])) /* \\?\unix special name */ + { + char *unix_name; + name += 4; + unix_name = malloc( wcslen(name) * 3 + 1 ); + ntdll_wcstoumbs( name, wcslen(name) + 1, unix_name, wcslen(name) * 3 + 1, FALSE ); + status = unix_to_nt_file_name( unix_name, path ); + free( unix_name ); + return status; + } + prefix = devW; + } + else prefix = uncW; /* UNC path */ + } + else if (IS_SEPARATOR(name[0])) /* absolute path */ + { + root[4] = curdir[0]; + prefix = root; + } + else if (name[0] && name[1] == ':') /* drive letter */ + { + root[4] = towupper(name[0]); + name += 2; + prefix = root; + } + else prefix = curdir; /* relative path */ + + ret = malloc( (wcslen(prefix) + wcslen(name) + 1) * sizeof(WCHAR) ); + wcscpy( ret, prefix ); + wcscat( ret, name ); + collapse_path( ret ); + *path = ret; + return STATUS_SUCCESS; +} + + /*********************************************************************** * unmount_device * diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index f615e364461..c4e7e3a4146 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -1214,13 +1214,11 @@ static inline char *prepend( char *buffer, const char *str, size_t len ) * * Open a file for a new dll. Helper for open_builtin_file. */ -static NTSTATUS open_dll_file( const char *name, OBJECT_ATTRIBUTES *attr, void **module, - SIZE_T *size_ptr, SECTION_IMAGE_INFORMATION *image_info, - WORD machine, BOOL prefer_native ) +static NTSTATUS open_dll_file( const char *name, OBJECT_ATTRIBUTES *attr, HANDLE *mapping ) { LARGE_INTEGER size; NTSTATUS status; - HANDLE handle, mapping; + HANDLE handle; if ((status = open_unix_file( &handle, name, GENERIC_READ | SYNCHRONIZE, attr, 0, FILE_SHARE_READ | FILE_SHARE_DELETE, FILE_OPEN, @@ -1237,14 +1235,10 @@ static NTSTATUS open_dll_file( const char *name, OBJECT_ATTRIBUTES *attr, void * } size.QuadPart = 0; - status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | + status = NtCreateSection( mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_EXECUTE, NULL, &size, PAGE_EXECUTE_READ, SEC_IMAGE, handle ); NtClose( handle ); - if (status) return status; - - status = virtual_map_builtin_module( mapping, module, size_ptr, image_info, machine, prefer_native ); - NtClose( mapping ); return status; } @@ -1256,10 +1250,16 @@ static NTSTATUS open_builtin_file( char *name, OBJECT_ATTRIBUTES *attr, void **m SECTION_IMAGE_INFORMATION *image_info, WORD machine, BOOL prefer_native ) { NTSTATUS status; + HANDLE mapping; int fd; *module = NULL; - status = open_dll_file( name, attr, module, size, image_info, machine, prefer_native ); + status = open_dll_file( name, attr, &mapping ); + if (!status) + { + status = virtual_map_builtin_module( mapping, module, size, image_info, machine, prefer_native ); + NtClose( mapping ); + } if (status != STATUS_DLL_NOT_FOUND) return status; /* try .so file */ @@ -1452,6 +1452,98 @@ NTSTATUS load_builtin( const pe_image_info_t *image_info, const WCHAR *filename, } +/*********************************************************************** + * open_main_image + */ +static NTSTATUS open_main_image( WCHAR *image, void **module, SECTION_IMAGE_INFORMATION *info ) +{ + static const WCHAR soW[] = {'.','s','o',0}; + UNICODE_STRING nt_name; + OBJECT_ATTRIBUTES attr; + pe_image_info_t pe_info; + SIZE_T size = 0; + char *unix_name; + NTSTATUS status; + HANDLE mapping; + WCHAR *p; + + init_unicode_string( &nt_name, image ); + InitializeObjectAttributes( &attr, &nt_name, OBJ_CASE_INSENSITIVE, 0, NULL ); + if (nt_to_unix_file_name( &nt_name, &unix_name, NULL, FILE_OPEN )) return STATUS_DLL_NOT_FOUND; + + status = open_dll_file( unix_name, &attr, &mapping ); + if (!status) + { + *module = NULL; + status = NtMapViewOfSection( mapping, NtCurrentProcess(), module, 0, 0, NULL, &size, + ViewShare, 0, PAGE_EXECUTE_READ ); + if (!status) NtQuerySection( mapping, SectionImageInformation, info, sizeof(*info), NULL ); + NtClose( mapping ); + } + else if (status == STATUS_INVALID_IMAGE_NOT_MZ) + { + /* remove .so extension from Windows name */ + p = image + wcslen(image); + if (p - image > 3 && !wcsicmp( p - 3, soW )) + { + p[-3] = 0; + nt_name.Length -= 3 * sizeof(WCHAR); + } + status = dlopen_dll( unix_name, &nt_name, module, &pe_info, FALSE ); + if (!status) virtual_fill_image_information( &pe_info, info ); + } + free( unix_name ); + return status; +} + + +/*********************************************************************** + * load_main_exe + */ +NTSTATUS load_main_exe( const WCHAR *name, const WCHAR *curdir, WCHAR **image, void **module, + SECTION_IMAGE_INFORMATION *image_info ) +{ + UNICODE_STRING nt_name; + NTSTATUS status; + SIZE_T size; + struct stat st; + const WCHAR *p; + + /* special case for Unix file name */ + if (main_argv[0][0] == '/' && !stat( main_argv[0], &st )) + { + if ((status = unix_to_nt_file_name( main_argv[0], image ))) goto failed; + status = open_main_image( *image, module, image_info ); + if (status != STATUS_DLL_NOT_FOUND) return status; + free( *image ); + } + + if ((status = get_full_path( name, curdir, image ))) goto failed; + status = open_main_image( *image, module, image_info ); + if (status != STATUS_DLL_NOT_FOUND) return status; + + /* if path is in system dir, we can load the builtin even if the file itself doesn't exist */ + if (!wcsnicmp( *image, system_dir, wcslen(system_dir) )) + { + p = *image + wcslen( system_dir ); + while (*p == '\\') p++; + if (wcschr( p, '\\' )) goto failed; + init_unicode_string( &nt_name, *image ); + status = find_builtin_dll( &nt_name, module, &size, image_info, current_machine, FALSE ); + if (status != STATUS_DLL_NOT_FOUND) return status; + } + /* if name contains a path, bail out */ + if (wcschr( name, '/' ) || wcschr( name, '\\' ) || (name[0] && name[1] == ':')) goto failed; + + return STATUS_DLL_NOT_FOUND; + +failed: + MESSAGE( "wine: failed to open %s: %x\n", debugstr_w(name), status ); + NtTerminateProcess( GetCurrentProcess(), status ); + return status; /* unreached */ +} + + #ifdef __FreeBSD__ /* The PT_LOAD segments are sorted in increasing order, and the first * starts at the beginning of the ELF file. By parsing the file, we can diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index b0a9ed7925b..b2780257ccc 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -143,6 +143,8 @@ extern char **build_envp( const WCHAR *envW ) DECLSPEC_HIDDEN; extern NTSTATUS exec_wineloader( char **argv, int socketfd, const pe_image_info_t *pe_info ) DECLSPEC_HIDDEN; extern NTSTATUS load_builtin( const pe_image_info_t *image_info, const WCHAR *filename, void **addr_ptr, SIZE_T *size_ptr ) DECLSPEC_HIDDEN; +extern NTSTATUS load_main_exe( const WCHAR *name, const WCHAR *curdir, WCHAR **image, void **module, + SECTION_IMAGE_INFORMATION *image_info ) DECLSPEC_HIDDEN; extern void start_server( BOOL debug ) DECLSPEC_HIDDEN; extern ULONG_PTR get_image_address(void) DECLSPEC_HIDDEN; @@ -243,6 +245,7 @@ extern NTSTATUS errno_to_status( int err ) DECLSPEC_HIDDEN; extern NTSTATUS nt_to_unix_file_name( const UNICODE_STRING *nameW, char **unix_name_ret, UNICODE_STRING *nt_name, UINT disposition ) DECLSPEC_HIDDEN; extern NTSTATUS unix_to_nt_file_name( const char *name, WCHAR **nt ) DECLSPEC_HIDDEN; +extern NTSTATUS get_full_path( const WCHAR *name, const WCHAR *curdir, WCHAR **path ) DECLSPEC_HIDDEN; extern NTSTATUS open_unix_file( HANDLE *handle, const char *unix_name, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr, ULONG attributes, ULONG sharing, ULONG disposition, ULONG options, void *ea_buffer, ULONG ea_length ) DECLSPEC_HIDDEN;