Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
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-cw
Commits
eee3a4e8
Commit
eee3a4e8
authored
Nov 12, 2019
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
kernel32: Move support for starting Unix processes to ntdll.
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
1deefb84
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
184 additions
and
354 deletions
+184
-354
process.c
dlls/kernel32/process.c
+11
-353
env.c
dlls/ntdll/env.c
+68
-0
ntdll_misc.h
dlls/ntdll/ntdll_misc.h
+1
-0
process.c
dlls/ntdll/process.c
+104
-1
No files found.
dlls/kernel32/process.c
View file @
eee3a4e8
...
...
@@ -100,24 +100,6 @@ static WCHAR winevdm[] = {'C',':','\\','w','i','n','d','o','w','s',
/***********************************************************************
* is_special_env_var
*
* Check if an environment variable needs to be handled specially when
* passed through the Unix environment (i.e. prefixed with "WINE").
*/
static
inline
BOOL
is_special_env_var
(
const
char
*
var
)
{
return
(
!
strncmp
(
var
,
"PATH="
,
sizeof
(
"PATH="
)
-
1
)
||
!
strncmp
(
var
,
"PWD="
,
sizeof
(
"PWD="
)
-
1
)
||
!
strncmp
(
var
,
"HOME="
,
sizeof
(
"HOME="
)
-
1
)
||
!
strncmp
(
var
,
"TEMP="
,
sizeof
(
"TEMP="
)
-
1
)
||
!
strncmp
(
var
,
"TMP="
,
sizeof
(
"TMP="
)
-
1
)
||
!
strncmp
(
var
,
"QT_"
,
sizeof
(
"QT_"
)
-
1
)
||
!
strncmp
(
var
,
"VK_"
,
sizeof
(
"VK_"
)
-
1
));
}
/***********************************************************************
* find_exe_file
*
* Open an exe file, and return the full name and file handle.
...
...
@@ -296,317 +278,6 @@ void * CDECL __wine_kernel_init(void)
/***********************************************************************
* build_argv
*
* Build an argv array from a command-line.
* 'reserved' is the number of args to reserve before the first one.
*/
static
char
**
build_argv
(
const
UNICODE_STRING
*
cmdlineW
,
int
reserved
)
{
int
argc
;
char
**
argv
;
char
*
arg
,
*
s
,
*
d
,
*
cmdline
;
int
in_quotes
,
bcount
,
len
;
len
=
WideCharToMultiByte
(
CP_UNIXCP
,
0
,
cmdlineW
->
Buffer
,
cmdlineW
->
Length
/
sizeof
(
WCHAR
),
NULL
,
0
,
NULL
,
NULL
);
if
(
!
(
cmdline
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
+
1
)))
return
NULL
;
WideCharToMultiByte
(
CP_UNIXCP
,
0
,
cmdlineW
->
Buffer
,
cmdlineW
->
Length
/
sizeof
(
WCHAR
),
cmdline
,
len
,
NULL
,
NULL
);
cmdline
[
len
++
]
=
0
;
argc
=
reserved
+
1
;
bcount
=
0
;
in_quotes
=
0
;
s
=
cmdline
;
while
(
1
)
{
if
(
*
s
==
'\0'
||
((
*
s
==
' '
||
*
s
==
'\t'
)
&&
!
in_quotes
))
{
/* space */
argc
++
;
/* skip the remaining spaces */
while
(
*
s
==
' '
||
*
s
==
'\t'
)
{
s
++
;
}
if
(
*
s
==
'\0'
)
break
;
bcount
=
0
;
continue
;
}
else
if
(
*
s
==
'\\'
)
{
/* '\', count them */
bcount
++
;
}
else
if
((
*
s
==
'"'
)
&&
((
bcount
&
1
)
==
0
))
{
if
(
in_quotes
&&
s
[
1
]
==
'"'
)
{
s
++
;
}
else
{
/* unescaped '"' */
in_quotes
=!
in_quotes
;
bcount
=
0
;
}
}
else
{
/* a regular character */
bcount
=
0
;
}
s
++
;
}
if
(
!
(
argv
=
HeapAlloc
(
GetProcessHeap
(),
0
,
argc
*
sizeof
(
*
argv
)
+
len
)))
{
HeapFree
(
GetProcessHeap
(),
0
,
cmdline
);
return
NULL
;
}
arg
=
d
=
s
=
(
char
*
)(
argv
+
argc
);
memcpy
(
d
,
cmdline
,
len
);
bcount
=
0
;
in_quotes
=
0
;
argc
=
reserved
;
while
(
*
s
)
{
if
((
*
s
==
' '
||
*
s
==
'\t'
)
&&
!
in_quotes
)
{
/* Close the argument and copy it */
*
d
=
0
;
argv
[
argc
++
]
=
arg
;
/* skip the remaining spaces */
do
{
s
++
;
}
while
(
*
s
==
' '
||
*
s
==
'\t'
);
/* Start with a new argument */
arg
=
d
=
s
;
bcount
=
0
;
}
else
if
(
*
s
==
'\\'
)
{
/* '\\' */
*
d
++=*
s
++
;
bcount
++
;
}
else
if
(
*
s
==
'"'
)
{
/* '"' */
if
((
bcount
&
1
)
==
0
)
{
/* Preceded by an even number of '\', this is half that
* number of '\', plus a '"' which we discard.
*/
d
-=
bcount
/
2
;
s
++
;
if
(
in_quotes
&&
*
s
==
'"'
)
{
*
d
++=
'"'
;
s
++
;
}
else
{
in_quotes
=!
in_quotes
;
}
}
else
{
/* Preceded by an odd number of '\', this is half that
* number of '\' followed by a '"'
*/
d
=
d
-
bcount
/
2
-
1
;
*
d
++=
'"'
;
s
++
;
}
bcount
=
0
;
}
else
{
/* a regular character */
*
d
++=*
s
++
;
bcount
=
0
;
}
}
if
(
*
arg
)
{
*
d
=
'\0'
;
argv
[
argc
++
]
=
arg
;
}
argv
[
argc
]
=
NULL
;
HeapFree
(
GetProcessHeap
(),
0
,
cmdline
);
return
argv
;
}
/***********************************************************************
* build_envp
*
* Build the environment of a new child process.
*/
static
char
**
build_envp
(
const
WCHAR
*
envW
)
{
static
const
char
*
const
unix_vars
[]
=
{
"PATH"
,
"TEMP"
,
"TMP"
,
"HOME"
};
const
WCHAR
*
end
;
char
**
envp
;
char
*
env
,
*
p
;
int
count
=
1
,
length
;
unsigned
int
i
;
for
(
end
=
envW
;
*
end
;
count
++
)
end
+=
strlenW
(
end
)
+
1
;
end
++
;
length
=
WideCharToMultiByte
(
CP_UNIXCP
,
0
,
envW
,
end
-
envW
,
NULL
,
0
,
NULL
,
NULL
);
if
(
!
(
env
=
HeapAlloc
(
GetProcessHeap
(),
0
,
length
)))
return
NULL
;
WideCharToMultiByte
(
CP_UNIXCP
,
0
,
envW
,
end
-
envW
,
env
,
length
,
NULL
,
NULL
);
for
(
p
=
env
;
*
p
;
p
+=
strlen
(
p
)
+
1
)
if
(
is_special_env_var
(
p
))
length
+=
4
;
/* prefix it with "WINE" */
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
unix_vars
);
i
++
)
{
if
(
!
(
p
=
getenv
(
unix_vars
[
i
])))
continue
;
length
+=
strlen
(
unix_vars
[
i
])
+
strlen
(
p
)
+
2
;
count
++
;
}
if
((
envp
=
HeapAlloc
(
GetProcessHeap
(),
0
,
count
*
sizeof
(
*
envp
)
+
length
)))
{
char
**
envptr
=
envp
;
char
*
dst
=
(
char
*
)(
envp
+
count
);
/* some variables must not be modified, so we get them directly from the unix env */
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
unix_vars
);
i
++
)
{
if
(
!
(
p
=
getenv
(
unix_vars
[
i
])))
continue
;
*
envptr
++
=
strcpy
(
dst
,
unix_vars
[
i
]
);
strcat
(
dst
,
"="
);
strcat
(
dst
,
p
);
dst
+=
strlen
(
dst
)
+
1
;
}
/* now put the Windows environment strings */
for
(
p
=
env
;
*
p
;
p
+=
strlen
(
p
)
+
1
)
{
if
(
*
p
==
'='
)
continue
;
/* skip drive curdirs, this crashes some unix apps */
if
(
!
strncmp
(
p
,
"WINEPRELOADRESERVE="
,
sizeof
(
"WINEPRELOADRESERVE="
)
-
1
))
continue
;
if
(
!
strncmp
(
p
,
"WINELOADERNOEXEC="
,
sizeof
(
"WINELOADERNOEXEC="
)
-
1
))
continue
;
if
(
!
strncmp
(
p
,
"WINESERVERSOCKET="
,
sizeof
(
"WINESERVERSOCKET="
)
-
1
))
continue
;
if
(
is_special_env_var
(
p
))
/* prefix it with "WINE" */
{
*
envptr
++
=
strcpy
(
dst
,
"WINE"
);
strcat
(
dst
,
p
);
}
else
{
*
envptr
++
=
strcpy
(
dst
,
p
);
}
dst
+=
strlen
(
dst
)
+
1
;
}
*
envptr
=
0
;
}
HeapFree
(
GetProcessHeap
(),
0
,
env
);
return
envp
;
}
/***********************************************************************
* fork_and_exec
*
* Fork and exec a new Unix binary, checking for errors.
*/
static
NTSTATUS
fork_and_exec
(
const
RTL_USER_PROCESS_PARAMETERS
*
params
,
const
char
*
newdir
)
{
int
fd
[
2
],
stdin_fd
=
-
1
,
stdout_fd
=
-
1
,
stderr_fd
=
-
1
;
int
pid
,
err
;
char
**
argv
,
**
envp
;
UNICODE_STRING
nt_name
;
ANSI_STRING
unix_name
;
NTSTATUS
status
;
status
=
RtlDosPathNameToNtPathName_U_WithStatus
(
params
->
ImagePathName
.
Buffer
,
&
nt_name
,
NULL
,
NULL
);
if
(
!
status
)
{
status
=
wine_nt_to_unix_file_name
(
&
nt_name
,
&
unix_name
,
FILE_OPEN
,
FALSE
);
RtlFreeUnicodeString
(
&
nt_name
);
}
if
(
status
)
return
status
;
#ifdef HAVE_PIPE2
if
(
pipe2
(
fd
,
O_CLOEXEC
)
==
-
1
)
#endif
{
if
(
pipe
(
fd
)
==
-
1
)
{
RtlFreeAnsiString
(
&
unix_name
);
return
STATUS_TOO_MANY_OPENED_FILES
;
}
fcntl
(
fd
[
0
],
F_SETFD
,
FD_CLOEXEC
);
fcntl
(
fd
[
1
],
F_SETFD
,
FD_CLOEXEC
);
}
wine_server_handle_to_fd
(
params
->
hStdInput
,
FILE_READ_DATA
,
&
stdin_fd
,
NULL
);
wine_server_handle_to_fd
(
params
->
hStdOutput
,
FILE_WRITE_DATA
,
&
stdout_fd
,
NULL
);
wine_server_handle_to_fd
(
params
->
hStdError
,
FILE_WRITE_DATA
,
&
stderr_fd
,
NULL
);
argv
=
build_argv
(
&
params
->
CommandLine
,
0
);
envp
=
build_envp
(
params
->
Environment
);
if
(
!
(
pid
=
fork
()))
/* child */
{
if
(
!
(
pid
=
fork
()))
/* grandchild */
{
close
(
fd
[
0
]
);
if
(
params
->
ConsoleFlags
||
params
->
ConsoleHandle
==
KERNEL32_CONSOLE_ALLOC
||
(
params
->
hStdInput
==
INVALID_HANDLE_VALUE
&&
params
->
hStdOutput
==
INVALID_HANDLE_VALUE
))
{
int
nullfd
=
open
(
"/dev/null"
,
O_RDWR
);
setsid
();
/* close stdin and stdout */
if
(
nullfd
!=
-
1
)
{
dup2
(
nullfd
,
0
);
dup2
(
nullfd
,
1
);
close
(
nullfd
);
}
}
else
{
if
(
stdin_fd
!=
-
1
)
{
dup2
(
stdin_fd
,
0
);
close
(
stdin_fd
);
}
if
(
stdout_fd
!=
-
1
)
{
dup2
(
stdout_fd
,
1
);
close
(
stdout_fd
);
}
if
(
stderr_fd
!=
-
1
)
{
dup2
(
stderr_fd
,
2
);
close
(
stderr_fd
);
}
}
/* Reset signals that we previously set to SIG_IGN */
signal
(
SIGPIPE
,
SIG_DFL
);
if
(
newdir
)
chdir
(
newdir
);
if
(
argv
&&
envp
)
execve
(
unix_name
.
Buffer
,
argv
,
envp
);
}
if
(
pid
<=
0
)
/* grandchild if exec failed or child if fork failed */
{
status
=
pid
?
STATUS_NO_MEMORY
:
STATUS_ACCESS_DENIED
;
/* FIXME: FILE_GetNtStatus() */
write
(
fd
[
1
],
&
status
,
sizeof
(
status
)
);
_exit
(
1
);
}
_exit
(
0
);
/* child if fork succeeded */
}
HeapFree
(
GetProcessHeap
(),
0
,
argv
);
HeapFree
(
GetProcessHeap
(),
0
,
envp
);
RtlFreeAnsiString
(
&
unix_name
);
if
(
stdin_fd
!=
-
1
)
close
(
stdin_fd
);
if
(
stdout_fd
!=
-
1
)
close
(
stdout_fd
);
if
(
stderr_fd
!=
-
1
)
close
(
stderr_fd
);
close
(
fd
[
1
]
);
if
(
pid
!=
-
1
)
{
/* reap child */
do
{
err
=
waitpid
(
pid
,
NULL
,
0
);
}
while
(
err
<
0
&&
errno
==
EINTR
);
read
(
fd
[
0
],
&
status
,
sizeof
(
status
)
);
/* if we read something, exec or second fork failed */
}
else
status
=
STATUS_NO_MEMORY
;
close
(
fd
[
0
]
);
return
status
;
}
/***********************************************************************
* create_process_params
*/
static
RTL_USER_PROCESS_PARAMETERS
*
create_process_params
(
LPCWSTR
filename
,
LPCWSTR
cmdline
,
...
...
@@ -876,7 +547,6 @@ BOOL WINAPI CreateProcessInternalW( HANDLE token, LPCWSTR app_name, LPWSTR cmd_l
LPSTARTUPINFOW
startup_info
,
LPPROCESS_INFORMATION
info
,
HANDLE
*
new_token
)
{
char
*
unixdir
=
NULL
;
WCHAR
name
[
MAX_PATH
];
WCHAR
*
p
,
*
tidy_cmdline
=
cmd_line
;
RTL_USER_PROCESS_PARAMETERS
*
params
=
NULL
;
...
...
@@ -915,17 +585,13 @@ BOOL WINAPI CreateProcessInternalW( HANDLE token, LPCWSTR app_name, LPWSTR cmd_l
if
(
cur_dir
)
{
if
(
!
(
unixdir
=
wine_get_unix_file_name
(
cur_dir
)))
DWORD
attr
=
GetFileAttributesW
(
cur_dir
);
if
(
attr
==
INVALID_FILE_ATTRIBUTES
||
!
(
attr
&
FILE_ATTRIBUTE_DIRECTORY
))
{
status
=
STATUS_NOT_A_DIRECTORY
;
goto
done
;
}
}
else
{
WCHAR
buf
[
MAX_PATH
];
if
(
GetCurrentDirectoryW
(
MAX_PATH
,
buf
))
unixdir
=
wine_get_unix_file_name
(
buf
);
}
info
->
hThread
=
info
->
hProcess
=
0
;
info
->
dwProcessId
=
info
->
dwThreadId
=
0
;
...
...
@@ -949,24 +615,17 @@ BOOL WINAPI CreateProcessInternalW( HANDLE token, LPCWSTR app_name, LPWSTR cmd_l
break
;
case
STATUS_INVALID_IMAGE_NOT_MZ
:
/* check for .com or .bat extension */
if
((
p
=
strrchrW
(
app_name
,
'.'
)))
if
(
!
(
p
=
strrchrW
(
app_name
,
'.'
)))
break
;
if
(
!
strcmpiW
(
p
,
comW
)
||
!
strcmpiW
(
p
,
pifW
))
{
TRACE
(
"starting %s as DOS binary
\n
"
,
debugstr_w
(
app_name
)
);
status
=
create_vdm_process
(
process_attr
,
thread_attr
,
inherit
,
flags
,
params
,
&
rtl_info
);
}
else
if
(
!
strcmpiW
(
p
,
batW
)
||
!
strcmpiW
(
p
,
cmdW
))
{
if
(
!
strcmpiW
(
p
,
comW
)
||
!
strcmpiW
(
p
,
pifW
))
{
TRACE
(
"starting %s as DOS binary
\n
"
,
debugstr_w
(
app_name
)
);
status
=
create_vdm_process
(
process_attr
,
thread_attr
,
inherit
,
flags
,
params
,
&
rtl_info
);
break
;
}
if
(
!
strcmpiW
(
p
,
batW
)
||
!
strcmpiW
(
p
,
cmdW
))
{
TRACE
(
"starting %s as batch binary
\n
"
,
debugstr_w
(
app_name
)
);
status
=
create_cmd_process
(
process_attr
,
thread_attr
,
inherit
,
flags
,
params
,
&
rtl_info
);
break
;
}
TRACE
(
"starting %s as batch binary
\n
"
,
debugstr_w
(
app_name
)
);
status
=
create_cmd_process
(
process_attr
,
thread_attr
,
inherit
,
flags
,
params
,
&
rtl_info
);
}
/* unknown file, try as unix executable */
TRACE
(
"starting %s as Unix binary
\n
"
,
debugstr_w
(
app_name
)
);
status
=
fork_and_exec
(
params
,
unixdir
);
break
;
}
...
...
@@ -983,7 +642,6 @@ BOOL WINAPI CreateProcessInternalW( HANDLE token, LPCWSTR app_name, LPWSTR cmd_l
done:
RtlDestroyProcessParameters
(
params
);
if
(
tidy_cmdline
!=
cmd_line
)
HeapFree
(
GetProcessHeap
(),
0
,
tidy_cmdline
);
HeapFree
(
GetProcessHeap
(),
0
,
unixdir
);
return
set_ntstatus
(
status
);
}
...
...
dlls/ntdll/env.c
View file @
eee3a4e8
...
...
@@ -509,6 +509,74 @@ static WCHAR *build_initial_environment( char **env )
/***********************************************************************
* build_envp
*
* Build the environment of a new child process.
*/
char
**
build_envp
(
const
WCHAR
*
envW
)
{
static
const
char
*
const
unix_vars
[]
=
{
"PATH"
,
"TEMP"
,
"TMP"
,
"HOME"
};
char
**
envp
;
char
*
env
,
*
p
;
int
count
=
1
,
length
,
lenW
;
unsigned
int
i
;
lenW
=
get_env_length
(
envW
);
length
=
ntdll_wcstoumbs
(
0
,
envW
,
lenW
,
NULL
,
0
,
NULL
,
NULL
);
if
(
!
(
env
=
RtlAllocateHeap
(
GetProcessHeap
(),
0
,
length
)))
return
NULL
;
ntdll_wcstoumbs
(
0
,
envW
,
lenW
,
env
,
length
,
NULL
,
NULL
);
for
(
p
=
env
;
*
p
;
p
+=
strlen
(
p
)
+
1
)
if
(
is_special_env_var
(
p
))
length
+=
4
;
/* prefix it with "WINE" */
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
unix_vars
);
i
++
)
{
if
(
!
(
p
=
getenv
(
unix_vars
[
i
])))
continue
;
length
+=
strlen
(
unix_vars
[
i
])
+
strlen
(
p
)
+
2
;
count
++
;
}
if
((
envp
=
RtlAllocateHeap
(
GetProcessHeap
(),
0
,
count
*
sizeof
(
*
envp
)
+
length
)))
{
char
**
envptr
=
envp
;
char
*
dst
=
(
char
*
)(
envp
+
count
);
/* some variables must not be modified, so we get them directly from the unix env */
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
unix_vars
);
i
++
)
{
if
(
!
(
p
=
getenv
(
unix_vars
[
i
]
)))
continue
;
*
envptr
++
=
strcpy
(
dst
,
unix_vars
[
i
]
);
strcat
(
dst
,
"="
);
strcat
(
dst
,
p
);
dst
+=
strlen
(
dst
)
+
1
;
}
/* now put the Windows environment strings */
for
(
p
=
env
;
*
p
;
p
+=
strlen
(
p
)
+
1
)
{
if
(
*
p
==
'='
)
continue
;
/* skip drive curdirs, this crashes some unix apps */
if
(
!
strncmp
(
p
,
"WINEPRELOADRESERVE="
,
sizeof
(
"WINEPRELOADRESERVE="
)
-
1
))
continue
;
if
(
!
strncmp
(
p
,
"WINELOADERNOEXEC="
,
sizeof
(
"WINELOADERNOEXEC="
)
-
1
))
continue
;
if
(
!
strncmp
(
p
,
"WINESERVERSOCKET="
,
sizeof
(
"WINESERVERSOCKET="
)
-
1
))
continue
;
if
(
is_special_env_var
(
p
))
/* prefix it with "WINE" */
{
*
envptr
++
=
strcpy
(
dst
,
"WINE"
);
strcat
(
dst
,
p
);
}
else
{
*
envptr
++
=
strcpy
(
dst
,
p
);
}
dst
+=
strlen
(
dst
)
+
1
;
}
*
envptr
=
0
;
}
RtlFreeHeap
(
GetProcessHeap
(),
0
,
env
);
return
envp
;
}
/***********************************************************************
* get_current_directory
*
* Initialize the current directory from the Unix cwd.
...
...
dlls/ntdll/ntdll_misc.h
View file @
eee3a4e8
...
...
@@ -86,6 +86,7 @@ extern void virtual_init_threading(void) DECLSPEC_HIDDEN;
extern
void
fill_cpu_info
(
void
)
DECLSPEC_HIDDEN
;
extern
void
heap_set_debug_flags
(
HANDLE
handle
)
DECLSPEC_HIDDEN
;
extern
void
init_user_process_params
(
SIZE_T
data_size
)
DECLSPEC_HIDDEN
;
extern
char
**
build_envp
(
const
WCHAR
*
envW
)
DECLSPEC_HIDDEN
;
extern
NTSTATUS
restart_process
(
RTL_USER_PROCESS_PARAMETERS
*
params
,
NTSTATUS
status
)
DECLSPEC_HIDDEN
;
/* server support */
...
...
dlls/ntdll/process.c
View file @
eee3a4e8
...
...
@@ -1466,6 +1466,101 @@ static char *get_unix_curdir( const RTL_USER_PROCESS_PARAMETERS *params )
/***********************************************************************
* fork_and_exec
*
* Fork and exec a new Unix binary, checking for errors.
*/
static
NTSTATUS
fork_and_exec
(
UNICODE_STRING
*
path
,
const
RTL_USER_PROCESS_PARAMETERS
*
params
)
{
pid_t
pid
;
int
fd
[
2
],
stdin_fd
=
-
1
,
stdout_fd
=
-
1
;
char
**
argv
,
**
envp
;
char
*
unixdir
;
ANSI_STRING
unix_name
;
NTSTATUS
status
;
status
=
wine_nt_to_unix_file_name
(
path
,
&
unix_name
,
FILE_OPEN
,
FALSE
);
if
(
status
)
return
status
;
#ifdef HAVE_PIPE2
if
(
pipe2
(
fd
,
O_CLOEXEC
)
==
-
1
)
#endif
{
if
(
pipe
(
fd
)
==
-
1
)
{
RtlFreeAnsiString
(
&
unix_name
);
return
STATUS_TOO_MANY_OPENED_FILES
;
}
fcntl
(
fd
[
0
],
F_SETFD
,
FD_CLOEXEC
);
fcntl
(
fd
[
1
],
F_SETFD
,
FD_CLOEXEC
);
}
wine_server_handle_to_fd
(
params
->
hStdInput
,
FILE_READ_DATA
,
&
stdin_fd
,
NULL
);
wine_server_handle_to_fd
(
params
->
hStdOutput
,
FILE_WRITE_DATA
,
&
stdout_fd
,
NULL
);
argv
=
build_argv
(
&
params
->
CommandLine
,
0
);
envp
=
build_envp
(
params
->
Environment
);
unixdir
=
get_unix_curdir
(
params
);
if
(
!
(
pid
=
fork
()))
/* child */
{
if
(
!
(
pid
=
fork
()))
/* grandchild */
{
close
(
fd
[
0
]
);
if
(
params
->
ConsoleFlags
||
params
->
ConsoleHandle
==
(
HANDLE
)
1
/* KERNEL32_CONSOLE_ALLOC */
||
(
params
->
hStdInput
==
INVALID_HANDLE_VALUE
&&
params
->
hStdOutput
==
INVALID_HANDLE_VALUE
))
{
setsid
();
set_stdio_fd
(
-
1
,
-
1
);
/* close stdin and stdout */
}
else
set_stdio_fd
(
stdin_fd
,
stdout_fd
);
if
(
stdin_fd
!=
-
1
)
close
(
stdin_fd
);
if
(
stdout_fd
!=
-
1
)
close
(
stdout_fd
);
/* Reset signals that we previously set to SIG_IGN */
signal
(
SIGPIPE
,
SIG_DFL
);
if
(
unixdir
)
chdir
(
unixdir
);
if
(
argv
&&
envp
)
execve
(
unix_name
.
Buffer
,
argv
,
envp
);
}
if
(
pid
<=
0
)
/* grandchild if exec failed or child if fork failed */
{
status
=
FILE_GetNtStatus
();
write
(
fd
[
1
],
&
status
,
sizeof
(
status
)
);
_exit
(
1
);
}
_exit
(
0
);
/* child if fork succeeded */
}
close
(
fd
[
1
]
);
if
(
pid
!=
-
1
)
{
/* reap child */
pid_t
wret
;
do
{
wret
=
waitpid
(
pid
,
NULL
,
0
);
}
while
(
wret
<
0
&&
errno
==
EINTR
);
read
(
fd
[
0
],
&
status
,
sizeof
(
status
)
);
/* if we read something, exec or second fork failed */
}
else
status
=
FILE_GetNtStatus
();
close
(
fd
[
0
]
);
if
(
stdin_fd
!=
-
1
)
close
(
stdin_fd
);
if
(
stdout_fd
!=
-
1
)
close
(
stdout_fd
);
RtlFreeHeap
(
GetProcessHeap
(),
0
,
argv
);
RtlFreeHeap
(
GetProcessHeap
(),
0
,
envp
);
RtlFreeAnsiString
(
&
unix_name
);
return
status
;
}
/***********************************************************************
* restart_process
*/
NTSTATUS
restart_process
(
RTL_USER_PROCESS_PARAMETERS
*
params
,
NTSTATUS
status
)
...
...
@@ -1575,7 +1670,15 @@ NTSTATUS WINAPI RtlCreateUserProcess( UNICODE_STRING *path, ULONG attributes,
TRACE
(
"%s image %s cmdline %s
\n
"
,
debugstr_us
(
path
),
debugstr_us
(
&
params
->
ImagePathName
),
debugstr_us
(
&
params
->
CommandLine
));
if
((
status
=
get_pe_file_info
(
path
,
attributes
,
&
file_handle
,
&
pe_info
)))
goto
done
;
if
((
status
=
get_pe_file_info
(
path
,
attributes
,
&
file_handle
,
&
pe_info
)))
{
if
(
status
==
STATUS_INVALID_IMAGE_NOT_MZ
&&
!
fork_and_exec
(
path
,
params
))
{
memset
(
info
,
0
,
sizeof
(
*
info
)
);
return
STATUS_SUCCESS
;
}
goto
done
;
}
if
(
!
(
startup_info
=
create_startup_info
(
params
,
&
startup_info_size
)))
goto
done
;
env_size
=
get_env_size
(
params
,
&
winedebug
);
unixdir
=
get_unix_curdir
(
params
);
...
...
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