ntdll: Load the main image from the Unix side.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2021-03-24 10:53:53 +01:00
parent 662730a1bf
commit 28fe84da45
6 changed files with 349 additions and 162 deletions

View File

@ -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( &params->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, &params->ImagePathName, &dllpath,
&params->CurrentDirectory.DosPath,
&cmdline, NULL, &params->ImagePathName, NULL, NULL, NULL,
&params->CommandLine, NULL, &params->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 );
}

View File

@ -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(&params->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(&params->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( &params->ImagePathName, appname );
RtlInitUnicodeString( &params->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(&params->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(&params->ImagePathName) );
break;
case STATUS_DLL_NOT_FOUND:
ERR( "%s not found\n", debugstr_us(&params->ImagePathName) );
break;
default:
ERR( "failed to load %s, error %x\n", debugstr_us(&params->ImagePathName), status );
break;
}
NtTerminateProcess( GetCurrentProcess(), status );
}
build_main_module();
#ifndef _WIN64
if (NtCurrentTeb64())

View File

@ -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(&params->ImagePathName) );
NtTerminateProcess( GetCurrentProcess(), status );
}
NtCurrentTeb()->Peb->ImageBaseAddress = module;
free( image );
}

View File

@ -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
*

View File

@ -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

View File

@ -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;