Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
28fe84da
Commit
28fe84da
authored
Mar 24, 2021
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntdll: Load the main image from the Unix side.
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
662730a1
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
349 additions
and
162 deletions
+349
-162
env.c
dlls/ntdll/env.c
+3
-76
loader.c
dlls/ntdll/loader.c
+41
-71
env.c
dlls/ntdll/unix/env.c
+65
-5
file.c
dlls/ntdll/unix/file.c
+135
-0
loader.c
dlls/ntdll/unix/loader.c
+102
-10
unix_private.h
dlls/ntdll/unix/unix_private.h
+3
-0
No files found.
dlls/ntdll/env.c
View file @
28fe84da
...
...
@@ -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
,
&
cmdl
ine
,
NULL
,
&
params
->
ImagePathName
,
NULL
,
NULL
,
NULL
,
&
params
->
CommandL
ine
,
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
);
}
...
...
dlls/ntdll/loader.c
View file @
28fe84da
...
...
@@ -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
())
...
...
dlls/ntdll/unix/env.c
View file @
28fe84da
...
...
@@ -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
);
}
...
...
dlls/ntdll/unix/file.c
View file @
28fe84da
...
...
@@ -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
*
...
...
dlls/ntdll/unix/loader.c
View file @
28fe84da
...
...
@@ -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
...
...
dlls/ntdll/unix/unix_private.h
View file @
28fe84da
...
...
@@ -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
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment