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
712ae337
Commit
712ae337
authored
Nov 12, 2019
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
kernel32: Move CreateProcess() functions to kernelbase.
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
4405195b
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
491 additions
and
535 deletions
+491
-535
kernel32.spec
dlls/kernel32/kernel32.spec
+6
-6
kernel_private.h
dlls/kernel32/kernel_private.h
+0
-1
process.c
dlls/kernel32/process.c
+0
-522
kernelbase.spec
dlls/kernelbase/kernelbase.spec
+6
-6
process.c
dlls/kernelbase/process.c
+479
-0
No files found.
dlls/kernel32/kernel32.spec
View file @
712ae337
...
...
@@ -309,13 +309,13 @@
@ stdcall -import CreatePipe(ptr ptr ptr long)
# @ stub CreatePrivateNamespaceA
# @ stub CreatePrivateNamespaceW
@ stdcall CreateProcessA(str str ptr ptr long long ptr str ptr ptr)
@ stdcall CreateProcessAsUserA(long str str ptr ptr long long ptr str ptr ptr)
@ stdcall CreateProcessAsUserW(long wstr wstr ptr ptr long long ptr wstr ptr ptr)
@ stdcall CreateProcessInternalA(long str str ptr ptr long long ptr str ptr ptr ptr)
@ stdcall CreateProcessInternalW(long wstr wstr ptr ptr long long ptr wstr ptr ptr ptr)
@ stdcall
-import
CreateProcessA(str str ptr ptr long long ptr str ptr ptr)
@ stdcall
-import
CreateProcessAsUserA(long str str ptr ptr long long ptr str ptr ptr)
@ stdcall
-import
CreateProcessAsUserW(long wstr wstr ptr ptr long long ptr wstr ptr ptr)
@ stdcall
-import
CreateProcessInternalA(long str str ptr ptr long long ptr str ptr ptr ptr)
@ stdcall
-import
CreateProcessInternalW(long wstr wstr ptr ptr long long ptr wstr ptr ptr ptr)
# @ stub CreateProcessInternalWSecure
@ stdcall CreateProcessW(wstr wstr ptr ptr long long ptr wstr ptr ptr)
@ stdcall
-import
CreateProcessW(wstr wstr ptr ptr long long ptr wstr ptr ptr)
@ stdcall -import CreateRemoteThread(long ptr long ptr long long ptr)
@ stdcall -import CreateRemoteThreadEx(long ptr long ptr ptr long ptr ptr)
@ stdcall CreateSemaphoreA(ptr long long str)
...
...
dlls/kernel32/kernel_private.h
View file @
712ae337
...
...
@@ -59,7 +59,6 @@ extern SYSTEM_BASIC_INFORMATION system_info DECLSPEC_HIDDEN;
extern
const
WCHAR
DIR_Windows
[]
DECLSPEC_HIDDEN
;
extern
const
WCHAR
DIR_System
[]
DECLSPEC_HIDDEN
;
extern
const
WCHAR
*
DIR_SysWow64
DECLSPEC_HIDDEN
;
extern
void
FILE_SetDosError
(
void
)
DECLSPEC_HIDDEN
;
extern
WCHAR
*
FILE_name_AtoW
(
LPCSTR
name
,
BOOL
alloc
)
DECLSPEC_HIDDEN
;
...
...
dlls/kernel32/process.c
View file @
712ae337
...
...
@@ -70,16 +70,12 @@ typedef struct
DWORD
dwReserved
;
}
LOADPARMS32
;
static
BOOL
is_wow64
;
static
const
BOOL
is_win64
=
(
sizeof
(
void
*
)
>
sizeof
(
int
));
HMODULE
kernel32_handle
=
0
;
SYSTEM_BASIC_INFORMATION
system_info
=
{
0
};
const
WCHAR
DIR_Windows
[]
=
{
'C'
,
':'
,
'\\'
,
'w'
,
'i'
,
'n'
,
'd'
,
'o'
,
'w'
,
's'
,
0
};
const
WCHAR
DIR_System
[]
=
{
'C'
,
':'
,
'\\'
,
'w'
,
'i'
,
'n'
,
'd'
,
'o'
,
'w'
,
's'
,
'\\'
,
's'
,
'y'
,
's'
,
't'
,
'e'
,
'm'
,
'3'
,
'2'
,
0
};
const
WCHAR
*
DIR_SysWow64
=
NULL
;
/* Process flags */
#define PDB32_DEBUGGED 0x0001
/* Process is being debugged */
...
...
@@ -89,38 +85,6 @@ const WCHAR *DIR_SysWow64 = NULL;
#define PDB32_FILE_APIS_OEM 0x0040
/* File APIs are OEM */
#define PDB32_WIN32S_PROC 0x8000
/* Win32s process */
static
const
WCHAR
exeW
[]
=
{
'.'
,
'e'
,
'x'
,
'e'
,
0
};
static
const
WCHAR
comW
[]
=
{
'.'
,
'c'
,
'o'
,
'm'
,
0
};
static
const
WCHAR
batW
[]
=
{
'.'
,
'b'
,
'a'
,
't'
,
0
};
static
const
WCHAR
cmdW
[]
=
{
'.'
,
'c'
,
'm'
,
'd'
,
0
};
static
const
WCHAR
pifW
[]
=
{
'.'
,
'p'
,
'i'
,
'f'
,
0
};
static
WCHAR
winevdm
[]
=
{
'C'
,
':'
,
'\\'
,
'w'
,
'i'
,
'n'
,
'd'
,
'o'
,
'w'
,
's'
,
'\\'
,
's'
,
'y'
,
's'
,
't'
,
'e'
,
'm'
,
'3'
,
'2'
,
'\\'
,
'w'
,
'i'
,
'n'
,
'e'
,
'v'
,
'd'
,
'm'
,
'.'
,
'e'
,
'x'
,
'e'
,
0
};
/***********************************************************************
* find_exe_file
*
* Open an exe file, and return the full name and file handle.
* Returns FALSE if file could not be found.
*/
static
BOOL
find_exe_file
(
const
WCHAR
*
name
,
WCHAR
*
buffer
,
int
buflen
)
{
WCHAR
*
load_path
;
BOOL
ret
;
if
(
!
set_ntstatus
(
RtlGetExePath
(
name
,
&
load_path
)))
return
FALSE
;
TRACE
(
"looking for %s in %s
\n
"
,
debugstr_w
(
name
),
debugstr_w
(
load_path
)
);
ret
=
(
SearchPathW
(
load_path
,
name
,
exeW
,
buflen
,
buffer
,
NULL
)
||
/* not found, try without extension in case it is a Unix app */
SearchPathW
(
load_path
,
name
,
NULL
,
buflen
,
buffer
,
NULL
));
RtlReleasePath
(
load_path
);
return
ret
;
}
/***********************************************************************
* set_library_argv
...
...
@@ -155,22 +119,6 @@ static void set_library_argv( WCHAR **wargv )
}
/***********************************************************************
* init_windows_dirs
*/
static
void
init_windows_dirs
(
void
)
{
static
const
WCHAR
default_syswow64W
[]
=
{
'C'
,
':'
,
'\\'
,
'w'
,
'i'
,
'n'
,
'd'
,
'o'
,
'w'
,
's'
,
'\\'
,
's'
,
'y'
,
's'
,
'w'
,
'o'
,
'w'
,
'6'
,
'4'
,
0
};
if
(
is_win64
||
is_wow64
)
/* SysWow64 is always defined on 64-bit */
{
DIR_SysWow64
=
default_syswow64W
;
memcpy
(
winevdm
,
default_syswow64W
,
sizeof
(
default_syswow64W
)
-
sizeof
(
WCHAR
)
);
}
}
#ifdef __i386__
extern
DWORD
call_process_entry
(
PEB
*
peb
,
LPTHREAD_START_ROUTINE
entry
);
__ASM_GLOBAL_FUNC
(
call_process_entry
,
...
...
@@ -263,11 +211,9 @@ void * CDECL __wine_kernel_init(void)
setbuf
(
stdout
,
NULL
);
setbuf
(
stderr
,
NULL
);
kernel32_handle
=
GetModuleHandleW
(
kernel32W
);
IsWow64Process
(
GetCurrentProcess
(),
&
is_wow64
);
RtlSetUnhandledExceptionFilter
(
UnhandledExceptionFilter
);
LOCALE_Init
();
init_windows_dirs
();
convert_old_config
();
set_library_argv
(
__wine_main_wargv
);
...
...
@@ -278,474 +224,6 @@ void * CDECL __wine_kernel_init(void)
/***********************************************************************
* create_process_params
*/
static
RTL_USER_PROCESS_PARAMETERS
*
create_process_params
(
LPCWSTR
filename
,
LPCWSTR
cmdline
,
LPCWSTR
cur_dir
,
void
*
env
,
DWORD
flags
,
const
STARTUPINFOW
*
startup
)
{
RTL_USER_PROCESS_PARAMETERS
*
params
;
UNICODE_STRING
imageW
,
dllpathW
,
curdirW
,
cmdlineW
,
titleW
,
desktopW
,
runtimeW
,
newdirW
;
WCHAR
imagepath
[
MAX_PATH
];
WCHAR
*
load_path
,
*
dummy
,
*
envW
=
env
;
if
(
!
GetLongPathNameW
(
filename
,
imagepath
,
MAX_PATH
))
lstrcpynW
(
imagepath
,
filename
,
MAX_PATH
);
if
(
!
GetFullPathNameW
(
imagepath
,
MAX_PATH
,
imagepath
,
NULL
))
lstrcpynW
(
imagepath
,
filename
,
MAX_PATH
);
if
(
env
&&
!
(
flags
&
CREATE_UNICODE_ENVIRONMENT
))
/* convert environment to unicode */
{
char
*
e
=
env
;
DWORD
lenW
;
while
(
*
e
)
e
+=
strlen
(
e
)
+
1
;
e
++
;
/* final null */
lenW
=
MultiByteToWideChar
(
CP_ACP
,
0
,
env
,
e
-
(
char
*
)
env
,
NULL
,
0
);
if
((
envW
=
HeapAlloc
(
GetProcessHeap
(),
0
,
lenW
*
sizeof
(
WCHAR
)
)))
MultiByteToWideChar
(
CP_ACP
,
0
,
env
,
e
-
(
char
*
)
env
,
envW
,
lenW
);
}
newdirW
.
Buffer
=
NULL
;
if
(
cur_dir
)
{
if
(
RtlDosPathNameToNtPathName_U
(
cur_dir
,
&
newdirW
,
NULL
,
NULL
))
cur_dir
=
newdirW
.
Buffer
+
4
;
/* skip \??\ prefix */
else
cur_dir
=
NULL
;
}
LdrGetDllPath
(
imagepath
,
LOAD_WITH_ALTERED_SEARCH_PATH
,
&
load_path
,
&
dummy
);
RtlInitUnicodeString
(
&
imageW
,
imagepath
);
RtlInitUnicodeString
(
&
dllpathW
,
load_path
);
RtlInitUnicodeString
(
&
curdirW
,
cur_dir
);
RtlInitUnicodeString
(
&
cmdlineW
,
cmdline
);
RtlInitUnicodeString
(
&
titleW
,
startup
->
lpTitle
?
startup
->
lpTitle
:
imagepath
);
RtlInitUnicodeString
(
&
desktopW
,
startup
->
lpDesktop
);
runtimeW
.
Buffer
=
(
WCHAR
*
)
startup
->
lpReserved2
;
runtimeW
.
Length
=
runtimeW
.
MaximumLength
=
startup
->
cbReserved2
;
if
(
RtlCreateProcessParametersEx
(
&
params
,
&
imageW
,
&
dllpathW
,
cur_dir
?
&
curdirW
:
NULL
,
&
cmdlineW
,
envW
,
&
titleW
,
&
desktopW
,
NULL
,
&
runtimeW
,
PROCESS_PARAMS_FLAG_NORMALIZED
))
{
RtlReleasePath
(
load_path
);
if
(
envW
!=
env
)
HeapFree
(
GetProcessHeap
(),
0
,
envW
);
return
NULL
;
}
RtlReleasePath
(
load_path
);
if
(
flags
&
CREATE_NEW_PROCESS_GROUP
)
params
->
ConsoleFlags
=
1
;
if
(
flags
&
CREATE_NEW_CONSOLE
)
params
->
ConsoleHandle
=
KERNEL32_CONSOLE_ALLOC
;
if
(
startup
->
dwFlags
&
STARTF_USESTDHANDLES
)
{
params
->
hStdInput
=
startup
->
hStdInput
;
params
->
hStdOutput
=
startup
->
hStdOutput
;
params
->
hStdError
=
startup
->
hStdError
;
}
else
if
(
flags
&
DETACHED_PROCESS
)
{
params
->
hStdInput
=
INVALID_HANDLE_VALUE
;
params
->
hStdOutput
=
INVALID_HANDLE_VALUE
;
params
->
hStdError
=
INVALID_HANDLE_VALUE
;
}
else
{
params
->
hStdInput
=
NtCurrentTeb
()
->
Peb
->
ProcessParameters
->
hStdInput
;
params
->
hStdOutput
=
NtCurrentTeb
()
->
Peb
->
ProcessParameters
->
hStdOutput
;
params
->
hStdError
=
NtCurrentTeb
()
->
Peb
->
ProcessParameters
->
hStdError
;
}
if
(
flags
&
CREATE_NEW_CONSOLE
)
{
/* this is temporary (for console handles). We have no way to control that the handle is invalid in child process otherwise */
if
(
is_console_handle
(
params
->
hStdInput
))
params
->
hStdInput
=
INVALID_HANDLE_VALUE
;
if
(
is_console_handle
(
params
->
hStdOutput
))
params
->
hStdOutput
=
INVALID_HANDLE_VALUE
;
if
(
is_console_handle
(
params
->
hStdError
))
params
->
hStdError
=
INVALID_HANDLE_VALUE
;
}
else
{
if
(
is_console_handle
(
params
->
hStdInput
))
params
->
hStdInput
=
(
HANDLE
)((
UINT_PTR
)
params
->
hStdInput
&
~
3
);
if
(
is_console_handle
(
params
->
hStdOutput
))
params
->
hStdOutput
=
(
HANDLE
)((
UINT_PTR
)
params
->
hStdOutput
&
~
3
);
if
(
is_console_handle
(
params
->
hStdError
))
params
->
hStdError
=
(
HANDLE
)((
UINT_PTR
)
params
->
hStdError
&
~
3
);
}
params
->
dwX
=
startup
->
dwX
;
params
->
dwY
=
startup
->
dwY
;
params
->
dwXSize
=
startup
->
dwXSize
;
params
->
dwYSize
=
startup
->
dwYSize
;
params
->
dwXCountChars
=
startup
->
dwXCountChars
;
params
->
dwYCountChars
=
startup
->
dwYCountChars
;
params
->
dwFillAttribute
=
startup
->
dwFillAttribute
;
params
->
dwFlags
=
startup
->
dwFlags
;
params
->
wShowWindow
=
startup
->
wShowWindow
;
if
(
envW
!=
env
)
HeapFree
(
GetProcessHeap
(),
0
,
envW
);
return
params
;
}
/***********************************************************************
* create_nt_process
*/
static
NTSTATUS
create_nt_process
(
LPSECURITY_ATTRIBUTES
psa
,
LPSECURITY_ATTRIBUTES
tsa
,
BOOL
inherit
,
DWORD
flags
,
RTL_USER_PROCESS_PARAMETERS
*
params
,
RTL_USER_PROCESS_INFORMATION
*
info
)
{
NTSTATUS
status
;
UNICODE_STRING
nameW
;
if
(
!
params
->
ImagePathName
.
Buffer
[
0
])
return
STATUS_OBJECT_PATH_NOT_FOUND
;
status
=
RtlDosPathNameToNtPathName_U_WithStatus
(
params
->
ImagePathName
.
Buffer
,
&
nameW
,
NULL
,
NULL
);
if
(
!
status
)
{
params
->
DebugFlags
=
flags
;
/* hack, cf. RtlCreateUserProcess implementation */
status
=
RtlCreateUserProcess
(
&
nameW
,
OBJ_CASE_INSENSITIVE
,
params
,
psa
?
psa
->
lpSecurityDescriptor
:
NULL
,
tsa
?
tsa
->
lpSecurityDescriptor
:
NULL
,
0
,
inherit
,
0
,
0
,
info
);
RtlFreeUnicodeString
(
&
nameW
);
}
return
status
;
}
/***********************************************************************
* create_vdm_process
*
* Create a new VDM process for a 16-bit or DOS application.
*/
static
NTSTATUS
create_vdm_process
(
LPSECURITY_ATTRIBUTES
psa
,
LPSECURITY_ATTRIBUTES
tsa
,
BOOL
inherit
,
DWORD
flags
,
RTL_USER_PROCESS_PARAMETERS
*
params
,
RTL_USER_PROCESS_INFORMATION
*
info
)
{
static
const
WCHAR
argsW
[]
=
{
'%'
,
's'
,
' '
,
'-'
,
'-'
,
'a'
,
'p'
,
'p'
,
'-'
,
'n'
,
'a'
,
'm'
,
'e'
,
' '
,
'"'
,
'%'
,
's'
,
'"'
,
' '
,
'%'
,
's'
,
0
};
NTSTATUS
status
;
WCHAR
*
new_cmd_line
;
new_cmd_line
=
HeapAlloc
(
GetProcessHeap
(),
0
,
(
strlenW
(
params
->
ImagePathName
.
Buffer
)
+
strlenW
(
params
->
CommandLine
.
Buffer
)
+
strlenW
(
winevdm
)
+
16
)
*
sizeof
(
WCHAR
));
if
(
!
new_cmd_line
)
return
STATUS_NO_MEMORY
;
sprintfW
(
new_cmd_line
,
argsW
,
winevdm
,
params
->
ImagePathName
.
Buffer
,
params
->
CommandLine
.
Buffer
);
RtlInitUnicodeString
(
&
params
->
ImagePathName
,
winevdm
);
RtlInitUnicodeString
(
&
params
->
CommandLine
,
new_cmd_line
);
status
=
create_nt_process
(
psa
,
tsa
,
inherit
,
flags
,
params
,
info
);
HeapFree
(
GetProcessHeap
(),
0
,
new_cmd_line
);
return
status
;
}
/***********************************************************************
* create_cmd_process
*
* Create a new cmd shell process for a .BAT file.
*/
static
NTSTATUS
create_cmd_process
(
LPSECURITY_ATTRIBUTES
psa
,
LPSECURITY_ATTRIBUTES
tsa
,
BOOL
inherit
,
DWORD
flags
,
RTL_USER_PROCESS_PARAMETERS
*
params
,
RTL_USER_PROCESS_INFORMATION
*
info
)
{
static
const
WCHAR
argsW
[]
=
{
'%'
,
's'
,
' '
,
'/'
,
's'
,
'/'
,
'c'
,
' '
,
'"'
,
'%'
,
's'
,
'"'
,
0
};
static
const
WCHAR
comspecW
[]
=
{
'C'
,
'O'
,
'M'
,
'S'
,
'P'
,
'E'
,
'C'
,
0
};
static
const
WCHAR
cmdW
[]
=
{
'\\'
,
'c'
,
'm'
,
'd'
,
'.'
,
'e'
,
'x'
,
'e'
,
0
};
WCHAR
comspec
[
MAX_PATH
];
WCHAR
*
newcmdline
;
NTSTATUS
status
;
if
(
!
GetEnvironmentVariableW
(
comspecW
,
comspec
,
ARRAY_SIZE
(
comspec
)))
{
GetSystemDirectoryW
(
comspec
,
ARRAY_SIZE
(
comspec
)
-
ARRAY_SIZE
(
cmdW
));
strcatW
(
comspec
,
cmdW
);
}
if
(
!
(
newcmdline
=
HeapAlloc
(
GetProcessHeap
(),
0
,
(
strlenW
(
comspec
)
+
7
+
strlenW
(
params
->
CommandLine
.
Buffer
)
+
2
)
*
sizeof
(
WCHAR
))))
return
STATUS_NO_MEMORY
;
sprintfW
(
newcmdline
,
argsW
,
comspec
,
params
->
CommandLine
.
Buffer
);
RtlInitUnicodeString
(
&
params
->
ImagePathName
,
comspec
);
RtlInitUnicodeString
(
&
params
->
CommandLine
,
newcmdline
);
status
=
create_nt_process
(
psa
,
tsa
,
inherit
,
flags
,
params
,
info
);
HeapFree
(
GetProcessHeap
(),
0
,
newcmdline
);
return
status
;
}
/*************************************************************************
* get_file_name
*
* Helper for CreateProcess: retrieve the file name to load from the
* app name and command line. Store the file name in buffer, and
* return a possibly modified command line.
*/
static
LPWSTR
get_file_name
(
LPWSTR
cmdline
,
LPWSTR
buffer
,
int
buflen
)
{
WCHAR
*
name
,
*
pos
,
*
first_space
,
*
ret
=
NULL
;
const
WCHAR
*
p
;
/* first check for a quoted file name */
if
((
cmdline
[
0
]
==
'"'
)
&&
((
p
=
strchrW
(
cmdline
+
1
,
'"'
))))
{
int
len
=
p
-
cmdline
-
1
;
/* extract the quoted portion as file name */
if
(
!
(
name
=
HeapAlloc
(
GetProcessHeap
(),
0
,
(
len
+
1
)
*
sizeof
(
WCHAR
)
)))
return
NULL
;
memcpy
(
name
,
cmdline
+
1
,
len
*
sizeof
(
WCHAR
)
);
name
[
len
]
=
0
;
if
(
!
find_exe_file
(
name
,
buffer
,
buflen
))
goto
done
;
ret
=
cmdline
;
/* no change necessary */
goto
done
;
}
/* now try the command-line word by word */
if
(
!
(
name
=
HeapAlloc
(
GetProcessHeap
(),
0
,
(
strlenW
(
cmdline
)
+
1
)
*
sizeof
(
WCHAR
)
)))
return
NULL
;
pos
=
name
;
p
=
cmdline
;
first_space
=
NULL
;
for
(;;)
{
while
(
*
p
&&
*
p
!=
' '
&&
*
p
!=
'\t'
)
*
pos
++
=
*
p
++
;
*
pos
=
0
;
if
(
find_exe_file
(
name
,
buffer
,
buflen
))
{
ret
=
cmdline
;
break
;
}
if
(
!
first_space
)
first_space
=
pos
;
if
(
!
(
*
pos
++
=
*
p
++
))
break
;
}
if
(
!
ret
)
{
SetLastError
(
ERROR_FILE_NOT_FOUND
);
}
else
if
(
first_space
)
/* build a new command-line with quotes */
{
static
const
WCHAR
quotesW
[]
=
{
'"'
,
'%'
,
's'
,
'"'
,
'%'
,
's'
,
0
};
if
(
!
(
ret
=
HeapAlloc
(
GetProcessHeap
(),
0
,
(
strlenW
(
cmdline
)
+
3
)
*
sizeof
(
WCHAR
)
)))
goto
done
;
sprintfW
(
ret
,
quotesW
,
name
,
p
);
}
done:
HeapFree
(
GetProcessHeap
(),
0
,
name
);
return
ret
;
}
/**********************************************************************
* CreateProcessInternalW (KERNEL32.@)
*/
BOOL
WINAPI
CreateProcessInternalW
(
HANDLE
token
,
LPCWSTR
app_name
,
LPWSTR
cmd_line
,
LPSECURITY_ATTRIBUTES
process_attr
,
LPSECURITY_ATTRIBUTES
thread_attr
,
BOOL
inherit
,
DWORD
flags
,
LPVOID
env
,
LPCWSTR
cur_dir
,
LPSTARTUPINFOW
startup_info
,
LPPROCESS_INFORMATION
info
,
HANDLE
*
new_token
)
{
WCHAR
name
[
MAX_PATH
];
WCHAR
*
p
,
*
tidy_cmdline
=
cmd_line
;
RTL_USER_PROCESS_PARAMETERS
*
params
=
NULL
;
RTL_USER_PROCESS_INFORMATION
rtl_info
;
NTSTATUS
status
;
/* Process the AppName and/or CmdLine to get module name and path */
TRACE
(
"app %s cmdline %s
\n
"
,
debugstr_w
(
app_name
),
debugstr_w
(
cmd_line
)
);
if
(
token
)
FIXME
(
"Creating a process with a token is not yet implemented
\n
"
);
if
(
new_token
)
FIXME
(
"No support for returning created process token
\n
"
);
if
(
app_name
)
{
if
(
!
cmd_line
||
!
cmd_line
[
0
])
/* no command-line, create one */
{
static
const
WCHAR
quotesW
[]
=
{
'"'
,
'%'
,
's'
,
'"'
,
0
};
if
(
!
(
tidy_cmdline
=
HeapAlloc
(
GetProcessHeap
(),
0
,
(
strlenW
(
app_name
)
+
3
)
*
sizeof
(
WCHAR
)
)))
return
FALSE
;
sprintfW
(
tidy_cmdline
,
quotesW
,
app_name
);
}
}
else
{
if
(
!
(
tidy_cmdline
=
get_file_name
(
cmd_line
,
name
,
ARRAY_SIZE
(
name
)
)))
return
FALSE
;
app_name
=
name
;
}
/* Warn if unsupported features are used */
if
(
flags
&
(
IDLE_PRIORITY_CLASS
|
HIGH_PRIORITY_CLASS
|
REALTIME_PRIORITY_CLASS
|
CREATE_DEFAULT_ERROR_MODE
|
CREATE_NO_WINDOW
|
PROFILE_USER
|
PROFILE_KERNEL
|
PROFILE_SERVER
))
WARN
(
"(%s,...): ignoring some flags in %x
\n
"
,
debugstr_w
(
app_name
),
flags
);
if
(
cur_dir
)
{
DWORD
attr
=
GetFileAttributesW
(
cur_dir
);
if
(
attr
==
INVALID_FILE_ATTRIBUTES
||
!
(
attr
&
FILE_ATTRIBUTE_DIRECTORY
))
{
status
=
STATUS_NOT_A_DIRECTORY
;
goto
done
;
}
}
info
->
hThread
=
info
->
hProcess
=
0
;
info
->
dwProcessId
=
info
->
dwThreadId
=
0
;
if
(
!
(
params
=
create_process_params
(
app_name
,
tidy_cmdline
,
cur_dir
,
env
,
flags
,
startup_info
)))
{
status
=
STATUS_NO_MEMORY
;
goto
done
;
}
status
=
create_nt_process
(
process_attr
,
thread_attr
,
inherit
,
flags
,
params
,
&
rtl_info
);
switch
(
status
)
{
case
STATUS_SUCCESS
:
break
;
case
STATUS_INVALID_IMAGE_WIN_16
:
case
STATUS_INVALID_IMAGE_NE_FORMAT
:
case
STATUS_INVALID_IMAGE_PROTECT
:
TRACE
(
"starting %s as Win16/DOS binary
\n
"
,
debugstr_w
(
app_name
)
);
status
=
create_vdm_process
(
process_attr
,
thread_attr
,
inherit
,
flags
,
params
,
&
rtl_info
);
break
;
case
STATUS_INVALID_IMAGE_NOT_MZ
:
/* check for .com or .bat extension */
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
))
{
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
;
}
if
(
!
status
)
{
info
->
hProcess
=
rtl_info
.
Process
;
info
->
hThread
=
rtl_info
.
Thread
;
info
->
dwProcessId
=
HandleToUlong
(
rtl_info
.
ClientId
.
UniqueProcess
);
info
->
dwThreadId
=
HandleToUlong
(
rtl_info
.
ClientId
.
UniqueThread
);
if
(
!
(
flags
&
CREATE_SUSPENDED
))
NtResumeThread
(
rtl_info
.
Thread
,
NULL
);
TRACE
(
"started process pid %04x tid %04x
\n
"
,
info
->
dwProcessId
,
info
->
dwThreadId
);
}
done:
RtlDestroyProcessParameters
(
params
);
if
(
tidy_cmdline
!=
cmd_line
)
HeapFree
(
GetProcessHeap
(),
0
,
tidy_cmdline
);
return
set_ntstatus
(
status
);
}
/**********************************************************************
* CreateProcessInternalA (KERNEL32.@)
*/
BOOL
WINAPI
CreateProcessInternalA
(
HANDLE
token
,
LPCSTR
app_name
,
LPSTR
cmd_line
,
LPSECURITY_ATTRIBUTES
process_attr
,
LPSECURITY_ATTRIBUTES
thread_attr
,
BOOL
inherit
,
DWORD
flags
,
LPVOID
env
,
LPCSTR
cur_dir
,
LPSTARTUPINFOA
startup_info
,
LPPROCESS_INFORMATION
info
,
HANDLE
*
new_token
)
{
BOOL
ret
=
FALSE
;
WCHAR
*
app_nameW
=
NULL
,
*
cmd_lineW
=
NULL
,
*
cur_dirW
=
NULL
;
UNICODE_STRING
desktopW
,
titleW
;
STARTUPINFOW
infoW
;
desktopW
.
Buffer
=
NULL
;
titleW
.
Buffer
=
NULL
;
if
(
app_name
&&
!
(
app_nameW
=
FILE_name_AtoW
(
app_name
,
TRUE
)))
goto
done
;
if
(
cmd_line
&&
!
(
cmd_lineW
=
FILE_name_AtoW
(
cmd_line
,
TRUE
)))
goto
done
;
if
(
cur_dir
&&
!
(
cur_dirW
=
FILE_name_AtoW
(
cur_dir
,
TRUE
)))
goto
done
;
if
(
startup_info
->
lpDesktop
)
RtlCreateUnicodeStringFromAsciiz
(
&
desktopW
,
startup_info
->
lpDesktop
);
if
(
startup_info
->
lpTitle
)
RtlCreateUnicodeStringFromAsciiz
(
&
titleW
,
startup_info
->
lpTitle
);
memcpy
(
&
infoW
,
startup_info
,
sizeof
(
infoW
)
);
infoW
.
lpDesktop
=
desktopW
.
Buffer
;
infoW
.
lpTitle
=
titleW
.
Buffer
;
if
(
startup_info
->
lpReserved
)
FIXME
(
"StartupInfo.lpReserved is used, please report (%s)
\n
"
,
debugstr_a
(
startup_info
->
lpReserved
));
ret
=
CreateProcessInternalW
(
token
,
app_nameW
,
cmd_lineW
,
process_attr
,
thread_attr
,
inherit
,
flags
,
env
,
cur_dirW
,
&
infoW
,
info
,
new_token
);
done:
HeapFree
(
GetProcessHeap
(),
0
,
app_nameW
);
HeapFree
(
GetProcessHeap
(),
0
,
cmd_lineW
);
HeapFree
(
GetProcessHeap
(),
0
,
cur_dirW
);
RtlFreeUnicodeString
(
&
desktopW
);
RtlFreeUnicodeString
(
&
titleW
);
return
ret
;
}
/**********************************************************************
* CreateProcessA (KERNEL32.@)
*/
BOOL
WINAPI
DECLSPEC_HOTPATCH
CreateProcessA
(
LPCSTR
app_name
,
LPSTR
cmd_line
,
LPSECURITY_ATTRIBUTES
process_attr
,
LPSECURITY_ATTRIBUTES
thread_attr
,
BOOL
inherit
,
DWORD
flags
,
LPVOID
env
,
LPCSTR
cur_dir
,
LPSTARTUPINFOA
startup_info
,
LPPROCESS_INFORMATION
info
)
{
return
CreateProcessInternalA
(
NULL
,
app_name
,
cmd_line
,
process_attr
,
thread_attr
,
inherit
,
flags
,
env
,
cur_dir
,
startup_info
,
info
,
NULL
);
}
/**********************************************************************
* CreateProcessW (KERNEL32.@)
*/
BOOL
WINAPI
DECLSPEC_HOTPATCH
CreateProcessW
(
LPCWSTR
app_name
,
LPWSTR
cmd_line
,
LPSECURITY_ATTRIBUTES
process_attr
,
LPSECURITY_ATTRIBUTES
thread_attr
,
BOOL
inherit
,
DWORD
flags
,
LPVOID
env
,
LPCWSTR
cur_dir
,
LPSTARTUPINFOW
startup_info
,
LPPROCESS_INFORMATION
info
)
{
return
CreateProcessInternalW
(
NULL
,
app_name
,
cmd_line
,
process_attr
,
thread_attr
,
inherit
,
flags
,
env
,
cur_dir
,
startup_info
,
info
,
NULL
);
}
/**********************************************************************
* CreateProcessAsUserA (KERNEL32.@)
*/
BOOL
WINAPI
DECLSPEC_HOTPATCH
CreateProcessAsUserA
(
HANDLE
token
,
LPCSTR
app_name
,
LPSTR
cmd_line
,
LPSECURITY_ATTRIBUTES
process_attr
,
LPSECURITY_ATTRIBUTES
thread_attr
,
BOOL
inherit
,
DWORD
flags
,
LPVOID
env
,
LPCSTR
cur_dir
,
LPSTARTUPINFOA
startup_info
,
LPPROCESS_INFORMATION
info
)
{
return
CreateProcessInternalA
(
token
,
app_name
,
cmd_line
,
process_attr
,
thread_attr
,
inherit
,
flags
,
env
,
cur_dir
,
startup_info
,
info
,
NULL
);
}
/**********************************************************************
* CreateProcessAsUserW (KERNEL32.@)
*/
BOOL
WINAPI
DECLSPEC_HOTPATCH
CreateProcessAsUserW
(
HANDLE
token
,
LPCWSTR
app_name
,
LPWSTR
cmd_line
,
LPSECURITY_ATTRIBUTES
process_attr
,
LPSECURITY_ATTRIBUTES
thread_attr
,
BOOL
inherit
,
DWORD
flags
,
LPVOID
env
,
LPCWSTR
cur_dir
,
LPSTARTUPINFOW
startup_info
,
LPPROCESS_INFORMATION
info
)
{
return
CreateProcessInternalW
(
token
,
app_name
,
cmd_line
,
process_attr
,
thread_attr
,
inherit
,
flags
,
env
,
cur_dir
,
startup_info
,
info
,
NULL
);
}
/***********************************************************************
* wait_input_idle
*
* Wrapper to call WaitForInputIdle USER function
...
...
dlls/kernelbase/kernelbase.spec
View file @
712ae337
...
...
@@ -205,12 +205,12 @@
@ stdcall CreatePrivateObjectSecurity(ptr ptr ptr long long ptr)
@ stdcall CreatePrivateObjectSecurityEx(ptr ptr ptr ptr long long long ptr)
@ stdcall CreatePrivateObjectSecurityWithMultipleInheritance(ptr ptr ptr ptr long long long long ptr)
@ stdcall CreateProcessA(str str ptr ptr long long ptr str ptr ptr)
kernel32.CreateProcessA
@ stdcall CreateProcessAsUserA(long str str ptr ptr long long ptr str ptr ptr)
kernel32.CreateProcessAsUserA
@ stdcall CreateProcessAsUserW(long wstr wstr ptr ptr long long ptr wstr ptr ptr)
kernel32.CreateProcessAsUserW
@ stdcall CreateProcessInternalA(long str str ptr ptr long long ptr str ptr ptr ptr)
kernel32.CreateProcessInternalA
@ stdcall CreateProcessInternalW(long wstr wstr ptr ptr long long ptr wstr ptr ptr ptr)
kernel32.CreateProcessInternalW
@ stdcall CreateProcessW(wstr wstr ptr ptr long long ptr wstr ptr ptr)
kernel32.CreateProcessW
@ stdcall CreateProcessA(str str ptr ptr long long ptr str ptr ptr)
@ stdcall CreateProcessAsUserA(long str str ptr ptr long long ptr str ptr ptr)
@ stdcall CreateProcessAsUserW(long wstr wstr ptr ptr long long ptr wstr ptr ptr)
@ stdcall CreateProcessInternalA(long str str ptr ptr long long ptr str ptr ptr ptr)
@ stdcall CreateProcessInternalW(long wstr wstr ptr ptr long long ptr wstr ptr ptr ptr)
@ stdcall CreateProcessW(wstr wstr ptr ptr long long ptr wstr ptr ptr)
@ stdcall CreateRemoteThread(long ptr long ptr long long ptr)
@ stdcall CreateRemoteThreadEx(long ptr long ptr ptr long ptr ptr)
@ stdcall CreateRestrictedToken(long long long ptr long ptr long ptr ptr)
...
...
dlls/kernelbase/process.c
View file @
712ae337
...
...
@@ -42,6 +42,279 @@ static DWORD shutdown_priority = 0x280;
***********************************************************************/
/***********************************************************************
* find_exe_file
*/
static
BOOL
find_exe_file
(
const
WCHAR
*
name
,
WCHAR
*
buffer
,
DWORD
buflen
)
{
WCHAR
*
load_path
;
BOOL
ret
;
if
(
!
set_ntstatus
(
RtlGetExePath
(
name
,
&
load_path
)))
return
FALSE
;
TRACE
(
"looking for %s in %s
\n
"
,
debugstr_w
(
name
),
debugstr_w
(
load_path
)
);
ret
=
(
SearchPathW
(
load_path
,
name
,
L".exe"
,
buflen
,
buffer
,
NULL
)
||
/* not found, try without extension in case it is a Unix app */
SearchPathW
(
load_path
,
name
,
NULL
,
buflen
,
buffer
,
NULL
));
RtlReleasePath
(
load_path
);
return
ret
;
}
/*************************************************************************
* get_file_name
*
* Helper for CreateProcess: retrieve the file name to load from the
* app name and command line. Store the file name in buffer, and
* return a possibly modified command line.
*/
static
WCHAR
*
get_file_name
(
WCHAR
*
cmdline
,
WCHAR
*
buffer
,
DWORD
buflen
)
{
WCHAR
*
name
,
*
pos
,
*
first_space
,
*
ret
=
NULL
;
const
WCHAR
*
p
;
/* first check for a quoted file name */
if
(
cmdline
[
0
]
==
'"'
&&
(
p
=
wcschr
(
cmdline
+
1
,
'"'
)))
{
int
len
=
p
-
cmdline
-
1
;
/* extract the quoted portion as file name */
if
(
!
(
name
=
RtlAllocateHeap
(
GetProcessHeap
(),
0
,
(
len
+
1
)
*
sizeof
(
WCHAR
)
)))
return
NULL
;
memcpy
(
name
,
cmdline
+
1
,
len
*
sizeof
(
WCHAR
)
);
name
[
len
]
=
0
;
if
(
!
find_exe_file
(
name
,
buffer
,
buflen
))
goto
done
;
ret
=
cmdline
;
/* no change necessary */
goto
done
;
}
/* now try the command-line word by word */
if
(
!
(
name
=
RtlAllocateHeap
(
GetProcessHeap
(),
0
,
(
lstrlenW
(
cmdline
)
+
1
)
*
sizeof
(
WCHAR
)
)))
return
NULL
;
pos
=
name
;
p
=
cmdline
;
first_space
=
NULL
;
for
(;;)
{
while
(
*
p
&&
*
p
!=
' '
&&
*
p
!=
'\t'
)
*
pos
++
=
*
p
++
;
*
pos
=
0
;
if
(
find_exe_file
(
name
,
buffer
,
buflen
))
{
ret
=
cmdline
;
break
;
}
if
(
!
first_space
)
first_space
=
pos
;
if
(
!
(
*
pos
++
=
*
p
++
))
break
;
}
if
(
!
ret
)
{
SetLastError
(
ERROR_FILE_NOT_FOUND
);
}
else
if
(
first_space
)
/* build a new command-line with quotes */
{
if
(
!
(
ret
=
HeapAlloc
(
GetProcessHeap
(),
0
,
(
lstrlenW
(
cmdline
)
+
3
)
*
sizeof
(
WCHAR
)
)))
goto
done
;
swprintf
(
ret
,
lstrlenW
(
cmdline
)
+
3
,
L"
\"
%s
\"
%s"
,
name
,
p
);
}
done:
RtlFreeHeap
(
GetProcessHeap
(),
0
,
name
);
return
ret
;
}
/***********************************************************************
* create_process_params
*/
static
RTL_USER_PROCESS_PARAMETERS
*
create_process_params
(
const
WCHAR
*
filename
,
const
WCHAR
*
cmdline
,
const
WCHAR
*
cur_dir
,
void
*
env
,
DWORD
flags
,
const
STARTUPINFOW
*
startup
)
{
RTL_USER_PROCESS_PARAMETERS
*
params
;
UNICODE_STRING
imageW
,
dllpathW
,
curdirW
,
cmdlineW
,
titleW
,
desktopW
,
runtimeW
,
newdirW
;
WCHAR
imagepath
[
MAX_PATH
];
WCHAR
*
load_path
,
*
dummy
,
*
envW
=
env
;
if
(
!
GetLongPathNameW
(
filename
,
imagepath
,
MAX_PATH
))
lstrcpynW
(
imagepath
,
filename
,
MAX_PATH
);
if
(
!
GetFullPathNameW
(
imagepath
,
MAX_PATH
,
imagepath
,
NULL
))
lstrcpynW
(
imagepath
,
filename
,
MAX_PATH
);
if
(
env
&&
!
(
flags
&
CREATE_UNICODE_ENVIRONMENT
))
/* convert environment to unicode */
{
char
*
e
=
env
;
DWORD
lenW
;
while
(
*
e
)
e
+=
strlen
(
e
)
+
1
;
e
++
;
/* final null */
lenW
=
MultiByteToWideChar
(
CP_ACP
,
0
,
env
,
e
-
(
char
*
)
env
,
NULL
,
0
);
if
((
envW
=
RtlAllocateHeap
(
GetProcessHeap
(),
0
,
lenW
*
sizeof
(
WCHAR
)
)))
MultiByteToWideChar
(
CP_ACP
,
0
,
env
,
e
-
(
char
*
)
env
,
envW
,
lenW
);
}
newdirW
.
Buffer
=
NULL
;
if
(
cur_dir
)
{
if
(
RtlDosPathNameToNtPathName_U
(
cur_dir
,
&
newdirW
,
NULL
,
NULL
))
cur_dir
=
newdirW
.
Buffer
+
4
;
/* skip \??\ prefix */
else
cur_dir
=
NULL
;
}
LdrGetDllPath
(
imagepath
,
LOAD_WITH_ALTERED_SEARCH_PATH
,
&
load_path
,
&
dummy
);
RtlInitUnicodeString
(
&
imageW
,
imagepath
);
RtlInitUnicodeString
(
&
dllpathW
,
load_path
);
RtlInitUnicodeString
(
&
curdirW
,
cur_dir
);
RtlInitUnicodeString
(
&
cmdlineW
,
cmdline
);
RtlInitUnicodeString
(
&
titleW
,
startup
->
lpTitle
?
startup
->
lpTitle
:
imagepath
);
RtlInitUnicodeString
(
&
desktopW
,
startup
->
lpDesktop
);
runtimeW
.
Buffer
=
(
WCHAR
*
)
startup
->
lpReserved2
;
runtimeW
.
Length
=
runtimeW
.
MaximumLength
=
startup
->
cbReserved2
;
if
(
RtlCreateProcessParametersEx
(
&
params
,
&
imageW
,
&
dllpathW
,
cur_dir
?
&
curdirW
:
NULL
,
&
cmdlineW
,
envW
,
&
titleW
,
&
desktopW
,
NULL
,
&
runtimeW
,
PROCESS_PARAMS_FLAG_NORMALIZED
))
{
RtlReleasePath
(
load_path
);
if
(
envW
!=
env
)
RtlFreeHeap
(
GetProcessHeap
(),
0
,
envW
);
return
NULL
;
}
RtlReleasePath
(
load_path
);
if
(
flags
&
CREATE_NEW_PROCESS_GROUP
)
params
->
ConsoleFlags
=
1
;
if
(
flags
&
CREATE_NEW_CONSOLE
)
params
->
ConsoleHandle
=
(
HANDLE
)
1
;
/* KERNEL32_CONSOLE_ALLOC */
if
(
startup
->
dwFlags
&
STARTF_USESTDHANDLES
)
{
params
->
hStdInput
=
startup
->
hStdInput
;
params
->
hStdOutput
=
startup
->
hStdOutput
;
params
->
hStdError
=
startup
->
hStdError
;
}
else
if
(
flags
&
DETACHED_PROCESS
)
{
params
->
hStdInput
=
INVALID_HANDLE_VALUE
;
params
->
hStdOutput
=
INVALID_HANDLE_VALUE
;
params
->
hStdError
=
INVALID_HANDLE_VALUE
;
}
else
{
params
->
hStdInput
=
NtCurrentTeb
()
->
Peb
->
ProcessParameters
->
hStdInput
;
params
->
hStdOutput
=
NtCurrentTeb
()
->
Peb
->
ProcessParameters
->
hStdOutput
;
params
->
hStdError
=
NtCurrentTeb
()
->
Peb
->
ProcessParameters
->
hStdError
;
}
if
(
flags
&
CREATE_NEW_CONSOLE
)
{
/* this is temporary (for console handles). We have no way to control that the handle is invalid in child process otherwise */
if
(
is_console_handle
(
params
->
hStdInput
))
params
->
hStdInput
=
INVALID_HANDLE_VALUE
;
if
(
is_console_handle
(
params
->
hStdOutput
))
params
->
hStdOutput
=
INVALID_HANDLE_VALUE
;
if
(
is_console_handle
(
params
->
hStdError
))
params
->
hStdError
=
INVALID_HANDLE_VALUE
;
}
else
{
if
(
is_console_handle
(
params
->
hStdInput
))
params
->
hStdInput
=
(
HANDLE
)((
UINT_PTR
)
params
->
hStdInput
&
~
3
);
if
(
is_console_handle
(
params
->
hStdOutput
))
params
->
hStdOutput
=
(
HANDLE
)((
UINT_PTR
)
params
->
hStdOutput
&
~
3
);
if
(
is_console_handle
(
params
->
hStdError
))
params
->
hStdError
=
(
HANDLE
)((
UINT_PTR
)
params
->
hStdError
&
~
3
);
}
params
->
dwX
=
startup
->
dwX
;
params
->
dwY
=
startup
->
dwY
;
params
->
dwXSize
=
startup
->
dwXSize
;
params
->
dwYSize
=
startup
->
dwYSize
;
params
->
dwXCountChars
=
startup
->
dwXCountChars
;
params
->
dwYCountChars
=
startup
->
dwYCountChars
;
params
->
dwFillAttribute
=
startup
->
dwFillAttribute
;
params
->
dwFlags
=
startup
->
dwFlags
;
params
->
wShowWindow
=
startup
->
wShowWindow
;
if
(
envW
!=
env
)
RtlFreeHeap
(
GetProcessHeap
(),
0
,
envW
);
return
params
;
}
/***********************************************************************
* create_nt_process
*/
static
NTSTATUS
create_nt_process
(
SECURITY_ATTRIBUTES
*
psa
,
SECURITY_ATTRIBUTES
*
tsa
,
BOOL
inherit
,
DWORD
flags
,
RTL_USER_PROCESS_PARAMETERS
*
params
,
RTL_USER_PROCESS_INFORMATION
*
info
)
{
NTSTATUS
status
;
UNICODE_STRING
nameW
;
if
(
!
params
->
ImagePathName
.
Buffer
[
0
])
return
STATUS_OBJECT_PATH_NOT_FOUND
;
status
=
RtlDosPathNameToNtPathName_U_WithStatus
(
params
->
ImagePathName
.
Buffer
,
&
nameW
,
NULL
,
NULL
);
if
(
!
status
)
{
params
->
DebugFlags
=
flags
;
/* hack, cf. RtlCreateUserProcess implementation */
status
=
RtlCreateUserProcess
(
&
nameW
,
OBJ_CASE_INSENSITIVE
,
params
,
psa
?
psa
->
lpSecurityDescriptor
:
NULL
,
tsa
?
tsa
->
lpSecurityDescriptor
:
NULL
,
0
,
inherit
,
0
,
0
,
info
);
RtlFreeUnicodeString
(
&
nameW
);
}
return
status
;
}
/***********************************************************************
* create_vdm_process
*/
static
NTSTATUS
create_vdm_process
(
SECURITY_ATTRIBUTES
*
psa
,
SECURITY_ATTRIBUTES
*
tsa
,
BOOL
inherit
,
DWORD
flags
,
RTL_USER_PROCESS_PARAMETERS
*
params
,
RTL_USER_PROCESS_INFORMATION
*
info
)
{
const
WCHAR
*
winevdm
=
(
is_win64
||
is_wow64
?
L"C:
\\
windows
\\
syswow64
\\
winevdm.exe"
:
L"C:
\\
windows
\\
system32
\\
winevdm.exe"
);
WCHAR
*
newcmdline
;
NTSTATUS
status
;
UINT
len
;
len
=
(
lstrlenW
(
params
->
ImagePathName
.
Buffer
)
+
lstrlenW
(
params
->
CommandLine
.
Buffer
)
+
lstrlenW
(
winevdm
)
+
16
);
if
(
!
(
newcmdline
=
RtlAllocateHeap
(
GetProcessHeap
(),
0
,
len
*
sizeof
(
WCHAR
)
)))
return
STATUS_NO_MEMORY
;
swprintf
(
newcmdline
,
len
,
L"%s --app-name
\"
%s
\"
%s"
,
winevdm
,
params
->
ImagePathName
.
Buffer
,
params
->
CommandLine
.
Buffer
);
RtlInitUnicodeString
(
&
params
->
ImagePathName
,
winevdm
);
RtlInitUnicodeString
(
&
params
->
CommandLine
,
newcmdline
);
status
=
create_nt_process
(
psa
,
tsa
,
inherit
,
flags
,
params
,
info
);
HeapFree
(
GetProcessHeap
(),
0
,
newcmdline
);
return
status
;
}
/***********************************************************************
* create_cmd_process
*/
static
NTSTATUS
create_cmd_process
(
SECURITY_ATTRIBUTES
*
psa
,
SECURITY_ATTRIBUTES
*
tsa
,
BOOL
inherit
,
DWORD
flags
,
RTL_USER_PROCESS_PARAMETERS
*
params
,
RTL_USER_PROCESS_INFORMATION
*
info
)
{
WCHAR
comspec
[
MAX_PATH
];
WCHAR
*
newcmdline
;
NTSTATUS
status
;
UINT
len
;
if
(
!
GetEnvironmentVariableW
(
L"COMSPEC"
,
comspec
,
ARRAY_SIZE
(
comspec
)))
lstrcpyW
(
comspec
,
L"C:
\\
windows
\\
system32
\\
cmd.exe"
);
len
=
lstrlenW
(
comspec
)
+
7
+
lstrlenW
(
params
->
CommandLine
.
Buffer
)
+
2
;
if
(
!
(
newcmdline
=
RtlAllocateHeap
(
GetProcessHeap
(),
0
,
len
*
sizeof
(
WCHAR
)
)))
return
STATUS_NO_MEMORY
;
swprintf
(
newcmdline
,
len
,
L"%s /s/c
\"
%s
\"
"
,
comspec
,
params
->
CommandLine
.
Buffer
);
RtlInitUnicodeString
(
&
params
->
ImagePathName
,
comspec
);
RtlInitUnicodeString
(
&
params
->
CommandLine
,
newcmdline
);
status
=
create_nt_process
(
psa
,
tsa
,
inherit
,
flags
,
params
,
info
);
RtlFreeHeap
(
GetProcessHeap
(),
0
,
newcmdline
);
return
status
;
}
/*********************************************************************
* CloseHandle (kernelbase.@)
*/
...
...
@@ -59,6 +332,212 @@ BOOL WINAPI DECLSPEC_HOTPATCH CloseHandle( HANDLE handle )
}
/**********************************************************************
* CreateProcessAsUserA (kernelbase.@)
*/
BOOL
WINAPI
DECLSPEC_HOTPATCH
CreateProcessAsUserA
(
HANDLE
token
,
const
char
*
app_name
,
char
*
cmd_line
,
SECURITY_ATTRIBUTES
*
process_attr
,
SECURITY_ATTRIBUTES
*
thread_attr
,
BOOL
inherit
,
DWORD
flags
,
void
*
env
,
const
char
*
cur_dir
,
STARTUPINFOA
*
startup_info
,
PROCESS_INFORMATION
*
info
)
{
return
CreateProcessInternalA
(
token
,
app_name
,
cmd_line
,
process_attr
,
thread_attr
,
inherit
,
flags
,
env
,
cur_dir
,
startup_info
,
info
,
NULL
);
}
/**********************************************************************
* CreateProcessAsUserW (kernelbase.@)
*/
BOOL
WINAPI
DECLSPEC_HOTPATCH
CreateProcessAsUserW
(
HANDLE
token
,
const
WCHAR
*
app_name
,
WCHAR
*
cmd_line
,
SECURITY_ATTRIBUTES
*
process_attr
,
SECURITY_ATTRIBUTES
*
thread_attr
,
BOOL
inherit
,
DWORD
flags
,
void
*
env
,
const
WCHAR
*
cur_dir
,
STARTUPINFOW
*
startup_info
,
PROCESS_INFORMATION
*
info
)
{
return
CreateProcessInternalW
(
token
,
app_name
,
cmd_line
,
process_attr
,
thread_attr
,
inherit
,
flags
,
env
,
cur_dir
,
startup_info
,
info
,
NULL
);
}
/**********************************************************************
* CreateProcessInternalA (kernelbase.@)
*/
BOOL
WINAPI
DECLSPEC_HOTPATCH
CreateProcessInternalA
(
HANDLE
token
,
const
char
*
app_name
,
char
*
cmd_line
,
SECURITY_ATTRIBUTES
*
process_attr
,
SECURITY_ATTRIBUTES
*
thread_attr
,
BOOL
inherit
,
DWORD
flags
,
void
*
env
,
const
char
*
cur_dir
,
STARTUPINFOA
*
startup_info
,
PROCESS_INFORMATION
*
info
,
HANDLE
*
new_token
)
{
BOOL
ret
=
FALSE
;
WCHAR
*
app_nameW
=
NULL
,
*
cmd_lineW
=
NULL
,
*
cur_dirW
=
NULL
;
UNICODE_STRING
desktopW
,
titleW
;
STARTUPINFOW
infoW
;
desktopW
.
Buffer
=
NULL
;
titleW
.
Buffer
=
NULL
;
if
(
app_name
&&
!
(
app_nameW
=
file_name_AtoW
(
app_name
,
TRUE
)))
goto
done
;
if
(
cmd_line
&&
!
(
cmd_lineW
=
file_name_AtoW
(
cmd_line
,
TRUE
)))
goto
done
;
if
(
cur_dir
&&
!
(
cur_dirW
=
file_name_AtoW
(
cur_dir
,
TRUE
)))
goto
done
;
if
(
startup_info
->
lpDesktop
)
RtlCreateUnicodeStringFromAsciiz
(
&
desktopW
,
startup_info
->
lpDesktop
);
if
(
startup_info
->
lpTitle
)
RtlCreateUnicodeStringFromAsciiz
(
&
titleW
,
startup_info
->
lpTitle
);
memcpy
(
&
infoW
,
startup_info
,
sizeof
(
infoW
)
);
infoW
.
lpDesktop
=
desktopW
.
Buffer
;
infoW
.
lpTitle
=
titleW
.
Buffer
;
ret
=
CreateProcessInternalW
(
token
,
app_nameW
,
cmd_lineW
,
process_attr
,
thread_attr
,
inherit
,
flags
,
env
,
cur_dirW
,
&
infoW
,
info
,
new_token
);
done:
RtlFreeHeap
(
GetProcessHeap
(),
0
,
app_nameW
);
RtlFreeHeap
(
GetProcessHeap
(),
0
,
cmd_lineW
);
RtlFreeHeap
(
GetProcessHeap
(),
0
,
cur_dirW
);
RtlFreeUnicodeString
(
&
desktopW
);
RtlFreeUnicodeString
(
&
titleW
);
return
ret
;
}
/**********************************************************************
* CreateProcessInternalW (kernelbase.@)
*/
BOOL
WINAPI
DECLSPEC_HOTPATCH
CreateProcessInternalW
(
HANDLE
token
,
const
WCHAR
*
app_name
,
WCHAR
*
cmd_line
,
SECURITY_ATTRIBUTES
*
process_attr
,
SECURITY_ATTRIBUTES
*
thread_attr
,
BOOL
inherit
,
DWORD
flags
,
void
*
env
,
const
WCHAR
*
cur_dir
,
STARTUPINFOW
*
startup_info
,
PROCESS_INFORMATION
*
info
,
HANDLE
*
new_token
)
{
WCHAR
name
[
MAX_PATH
];
WCHAR
*
p
,
*
tidy_cmdline
=
cmd_line
;
RTL_USER_PROCESS_PARAMETERS
*
params
=
NULL
;
RTL_USER_PROCESS_INFORMATION
rtl_info
;
NTSTATUS
status
;
/* Process the AppName and/or CmdLine to get module name and path */
TRACE
(
"app %s cmdline %s
\n
"
,
debugstr_w
(
app_name
),
debugstr_w
(
cmd_line
)
);
if
(
token
)
FIXME
(
"Creating a process with a token is not yet implemented
\n
"
);
if
(
new_token
)
FIXME
(
"No support for returning created process token
\n
"
);
if
(
app_name
)
{
if
(
!
cmd_line
||
!
cmd_line
[
0
])
/* no command-line, create one */
{
if
(
!
(
tidy_cmdline
=
RtlAllocateHeap
(
GetProcessHeap
(),
0
,
(
lstrlenW
(
app_name
)
+
3
)
*
sizeof
(
WCHAR
)
)))
return
FALSE
;
swprintf
(
tidy_cmdline
,
lstrlenW
(
app_name
)
+
3
,
L"
\"
%s
\"
"
,
app_name
);
}
}
else
{
if
(
!
(
tidy_cmdline
=
get_file_name
(
cmd_line
,
name
,
ARRAY_SIZE
(
name
)
)))
return
FALSE
;
app_name
=
name
;
}
/* Warn if unsupported features are used */
if
(
flags
&
(
IDLE_PRIORITY_CLASS
|
HIGH_PRIORITY_CLASS
|
REALTIME_PRIORITY_CLASS
|
CREATE_DEFAULT_ERROR_MODE
|
CREATE_NO_WINDOW
|
PROFILE_USER
|
PROFILE_KERNEL
|
PROFILE_SERVER
))
WARN
(
"(%s,...): ignoring some flags in %x
\n
"
,
debugstr_w
(
app_name
),
flags
);
if
(
cur_dir
)
{
DWORD
attr
=
GetFileAttributesW
(
cur_dir
);
if
(
attr
==
INVALID_FILE_ATTRIBUTES
||
!
(
attr
&
FILE_ATTRIBUTE_DIRECTORY
))
{
status
=
STATUS_NOT_A_DIRECTORY
;
goto
done
;
}
}
info
->
hThread
=
info
->
hProcess
=
0
;
info
->
dwProcessId
=
info
->
dwThreadId
=
0
;
if
(
!
(
params
=
create_process_params
(
app_name
,
tidy_cmdline
,
cur_dir
,
env
,
flags
,
startup_info
)))
{
status
=
STATUS_NO_MEMORY
;
goto
done
;
}
status
=
create_nt_process
(
process_attr
,
thread_attr
,
inherit
,
flags
,
params
,
&
rtl_info
);
switch
(
status
)
{
case
STATUS_SUCCESS
:
break
;
case
STATUS_INVALID_IMAGE_WIN_16
:
case
STATUS_INVALID_IMAGE_NE_FORMAT
:
case
STATUS_INVALID_IMAGE_PROTECT
:
TRACE
(
"starting %s as Win16/DOS binary
\n
"
,
debugstr_w
(
app_name
)
);
status
=
create_vdm_process
(
process_attr
,
thread_attr
,
inherit
,
flags
,
params
,
&
rtl_info
);
break
;
case
STATUS_INVALID_IMAGE_NOT_MZ
:
/* check for .com or .bat extension */
if
(
!
(
p
=
wcsrchr
(
app_name
,
'.'
)))
break
;
if
(
!
wcsicmp
(
p
,
L".com"
)
||
!
wcsicmp
(
p
,
L".pif"
))
{
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
(
!
wcsicmp
(
p
,
L".bat"
)
||
!
wcsicmp
(
p
,
L".cmd"
))
{
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
;
}
if
(
!
status
)
{
info
->
hProcess
=
rtl_info
.
Process
;
info
->
hThread
=
rtl_info
.
Thread
;
info
->
dwProcessId
=
HandleToUlong
(
rtl_info
.
ClientId
.
UniqueProcess
);
info
->
dwThreadId
=
HandleToUlong
(
rtl_info
.
ClientId
.
UniqueThread
);
if
(
!
(
flags
&
CREATE_SUSPENDED
))
NtResumeThread
(
rtl_info
.
Thread
,
NULL
);
TRACE
(
"started process pid %04x tid %04x
\n
"
,
info
->
dwProcessId
,
info
->
dwThreadId
);
}
done:
RtlDestroyProcessParameters
(
params
);
if
(
tidy_cmdline
!=
cmd_line
)
HeapFree
(
GetProcessHeap
(),
0
,
tidy_cmdline
);
return
set_ntstatus
(
status
);
}
/**********************************************************************
* CreateProcessA (kernelbase.@)
*/
BOOL
WINAPI
DECLSPEC_HOTPATCH
CreateProcessA
(
const
char
*
app_name
,
char
*
cmd_line
,
SECURITY_ATTRIBUTES
*
process_attr
,
SECURITY_ATTRIBUTES
*
thread_attr
,
BOOL
inherit
,
DWORD
flags
,
void
*
env
,
const
char
*
cur_dir
,
STARTUPINFOA
*
startup_info
,
PROCESS_INFORMATION
*
info
)
{
return
CreateProcessInternalA
(
NULL
,
app_name
,
cmd_line
,
process_attr
,
thread_attr
,
inherit
,
flags
,
env
,
cur_dir
,
startup_info
,
info
,
NULL
);
}
/**********************************************************************
* CreateProcessW (kernelbase.@)
*/
BOOL
WINAPI
DECLSPEC_HOTPATCH
CreateProcessW
(
const
WCHAR
*
app_name
,
WCHAR
*
cmd_line
,
SECURITY_ATTRIBUTES
*
process_attr
,
SECURITY_ATTRIBUTES
*
thread_attr
,
BOOL
inherit
,
DWORD
flags
,
void
*
env
,
const
WCHAR
*
cur_dir
,
STARTUPINFOW
*
startup_info
,
PROCESS_INFORMATION
*
info
)
{
return
CreateProcessInternalW
(
NULL
,
app_name
,
cmd_line
,
process_attr
,
thread_attr
,
inherit
,
flags
,
env
,
cur_dir
,
startup_info
,
info
,
NULL
);
}
/*********************************************************************
* DuplicateHandle (kernelbase.@)
*/
...
...
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