ntdll: Load the main image from the Unix side.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
662730a1bf
commit
28fe84da45
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue