CreateProcessAsUser
The CreateProcessAsUser
function creates a new process and its primary thread. The new process then
executes a specified executable file. The CreateProcessAsUser function
is similar to the CreateProcess
BOOL CreateProcessAsUser(
HANDLE hToken, |
// handle to a token
that represents a logged-on user |
LPCTSTR lpApplicationName, |
// pointer to name
of executable module |
LPTSTR lpCommandLine, |
// pointer to
command line string |
LPSECURITY_ATTRIBUTES lpProcessAttributes, |
// pointer to
process security attributes |
LPSECURITY_ATTRIBUTES lpThreadAttributes, |
// pointer to
thread security attributes |
BOOL bInheritHandles, |
// new process
inherits handles |
DWORD dwCreationFlags, |
// creation flags |
LPVOID lpEnvironment, |
// pointer to new
environment block |
LPCTSTR lpCurrentDirectory, |
// pointer to
current directory name |
LPSTARTUPINFO lpStartupInfo, |
// pointer to
STARTUPINFO |
LPPROCESS_INFORMATION lpProcessInformation |
// pointer to
PROCESS_INFORMATION |
); |
|
Parameters
hToken
Handle to a
primary token that represents a user. The user represented by the token must
have read and execute access to the application specified by the lpApplicationName
or the lpCommandLine parameter.
If your
process has the SE_TCB_NAME privilege, it can call the LogonUser
Alternatively,
you can call the DuplicateTokenEx
The other parameters of the CreateProcessAsUser function behave
just like the analogous parameters of the CreateProcess
lpApplicationName
Points to a null-terminated
string specifying the full path and filename of the module to execute. If a
partial name is specified, the current drive and current directory are used by
default. If this parameter is NULL, the module name must be the first white
space-delimited token in the lpCommandLine string. The specified module
can be a Win32-based application, or it can be some other type of module (for
example, MS-DOS or OS/2) if the appropriate subsystem is available on the local
computer.
lpCommandLine
Points to a null-terminated
string specifying the command line for the application to be executed. If this
parameter is NULL, the lpApplicationName string is used as the command
line. If both lpApplicationName and lpCommandLine are non-NULL, lpApplicationName
specifies the module to execute and lpCommandLine is used as the command
line. The new process can use GetCommandLine1XS07ZY to retrieve the entire command line; or C
runtime processes can use the argc/argv mechanism.
If lpApplicationName is NULL, the first white space-delimited
token of the command line specifies the module name. If the filename does not
contain an extension, .EXE is assumed. If the filename ends in a period (.)
with no extension, or the filename contains a path, .EXE is not appended. If
the filename does not contain a directory path, Windows searches for the
executable file in the following sequence:
1. The directory from which the application loaded.
2. The current directory.
3. The 32-bit Windows system directory. Use the GetSystemDirectory
function to get the path of this directory. The name of this directory is
SYSTEM32.
4. The 16-bit Windows system directory. There is no Win32 function
that obtains the path of this directory, but it is searched. The name of this
directory is SYSTEM.
5. The Windows directory. Use the GetWindowsDirectory function to get the path
of this directory.
6. The directories that are listed in the PATH environment variable.
If the
process to be created is an MS-DOS - based or 16-bit Windows-based application, lpCommandLine should
be a full command line in which the first element is the application name.
Because this also works well for Win32-based applications, it is the most
robust way to set lpCommandLine.
lpProcessAttributes
Pointer to a SECURITY_ATTRIBUTES
lpThreadAttributes
Pointer to a SECURITY_ATTRIBUTES
bInheritHandles
Indicates
whether the new process inherits handles from the calling process. If TRUE,
each inheritable open handle in the calling process is inherited by the new
process. Inherited handles have the same value and access privileges as the
original handles.
dwCreationFlags
Specifies
additional flags that control the priority class and the creation of the
process. The following creation flags can be specified in any combination,
except as noted:
Value |
Meaning |
CREATE_DEFAULT_ERROR_MODE |
|
|
The new
process does not inherit the error mode of the calling process. Instead, CreateProcessAsUser
gives the new process the current default error mode. An application sets
the current default error mode by calling SetErrorMode This flag
is particularly useful for multi-threaded shell applications that run with
hard errors disabled. The default
behavior for CreateProcessAsUser is for the new process to inherit the
error mode of the caller. Setting this flag changes that default behavior. |
CREATE_NEW_CONSOLE |
|
|
The new
process has a new console, instead of inheriting the parent s console. This
flag cannot be used with the DETACHED_PROCESS flag. |
CREATE_NEW_PROCESS_GROUP |
|
|
The new
process is the root process of a new process group. The process group
includes all processes that are descendants of this root process. The process
identifier of the new process group is the same as the process identifier,
which is returned in the lpProcessInformation parameter. Process
groups are used by the GenerateConsoleCtrlEvent function to enable
sending a CTRL+C or CTRL+BREAK signal to a group of console processes. |
CREATE_SEPARATE_WOW_VDM |
|
|
This flag
is only valid only starting a 16-bit Windows program. If set, the new process
is run in a private Virtual DOS Machine (VDM). By default, all 16-bit Windows programs are
run in a single, shared VDM. The
advantage of running separately is that a crash only kills the single VDM;
any other programs running in distinct VDMs continue to function normally.
Also, 16-bit Windows applications that are run in separate VDMs have separate
input queues. That means that if one application hangs momentarily,
applications in separate VDMs continue to receive input. |
CREATE_SUSPENDED |
|
|
The primary
thread of the new process is created in a suspended state, and does not run
until the ResumeThread |
CREATE_UNICODE_ENVIRONMENT |
|
|
If set, the
environment block pointed to by lpEnvironment uses Unicode characters.
If clear, the environment block uses ANSI characters. |
DEBUG_PROCESS |
|
|
If set, the
calling process is treated as a debugger, and the new process is a process
being debugged. The system notifies the debugger of all debug events that
occur in the process being debugged. |
DEBUG_ONLY_THIS_PROCESS |
|
|
If not set
and the calling process is being debugged, the new process becomes another
process being debugged by the calling process s debugger. If the calling
process is not a process being debugged, no debugging-related actions occur. |
DETACHED_PROCESS |
|
|
For console
processes, the new process does not have access to the console of the parent
process. The new process can call the AllocConsole |
The dwCreationFlags parameter also controls the new process s
priority class, which is used in determining the scheduling priorities of the
process s threads. If none of the following priority class flags is specified,
the priority class defaults to NORMAL_PRIORITY_CLASS unless the priority
class of the creating process is IDLE_PRIORITY_CLASS. In this case the
default priority class of the child process is IDLE_PRIORITY_CLASS. One
of the following flags can be specified:
Priority |
Meaning |
HIGH_PRIORITY_CLASS |
Indicates a
process that performs time-critical tasks that must be executed immediately
for it to run correctly. The threads of a high-priority class process preempt
the threads of normal-priority or idle-priority class processes. An example
is Windows Task List, which must respond quickly when called by the user,
regardless of the load on the operating system. Use extreme care when using
the high-priority class, because a high-priority class CPU-bound application
can use nearly all available cycles. |
IDLE_PRIORITY_CLASS |
Indicates a
process whose threads run only when the system is idle and are preempted by
the threads of any process running in a higher priority class. An example is
a screen saver. The idle priority class is inherited by child processes. |
NORMAL_PRIORITY_CLASS |
Indicates a
normal process with no special scheduling needs. |
REALTIME_PRIORITY_CLASS |
Indicates a
process that has the highest possible priority. The threads of a real-time priority
class process preempt the threads of all other processes, including operating
system processes performing important tasks. For example, a real-time process
that executes for more than a very brief interval can cause disk caches not
to flush or cause the mouse to be unresponsive. |
lpEnvironment
Points to an
environment block for the new process. If this parameter is NULL, the new
process uses the environment of the calling process.
An environment block consists of a null-terminated block of null-terminated
strings. Each string is in the form:
name=value
Because the equal sign is used as a separator, it must not be used in
the name of an environment variable.
If an application provides an environment block, rather than passing
NULL for this parameter, the current directory information of the system drives
is not automatically propagated to the new process. For a discussion of this
situation and how to handle it, see the following Remarks section.
An environment block can contain Unicode or ANSI characters. If the
environment block pointed to by lpEnvironment contains Unicode
characters, the dwCreationFlags field s CREATE_UNICODE_ENVIRONMENT flag
will be set. If the block contains ANSI characters, that flag will be clear.
Note that an ANSI environment block is terminated by two zero bytes:
one for the last string, one more to terminate the block. A Unicode environment
block is terminated by four zero bytes: two for the last string, two more to
terminate the block.
lpCurrentDirectory
Points to a
null-terminated string that specifies the current drive and directory for the
new process. The string must be a full path and filename that includes a drive
letter. If this parameter is NULL, the new process is created with the same
current drive and directory as the calling process. This option is provided
primarily for shells that need to start an application and specify its initial
drive and working directory.
lpStartupInfo
Points to a STARTUPINFO
lpProcessInformation
Points to a PROCESS_INFORMATION
Return Values
If the function
succeeds, the return value is nonzero.
If the
function fails, the return value is zero. To get extended error information,
call GetLastError
Remarks
The CreateProcessAsUser
function requires the SE_ASSIGNPRIMARYTOKEN_NAME and SE_INCREASE_QUOTA_NAME
privileges. If they are not already enabled, CreateProcessAsUser enables
them for the duration of the call.
By default, CreateProcessAsUser
creates the new process on a noninteractive window station with a desktop that
is not visible and cannot receive user input. To enable user interaction with
the new process, you must specify the name of the default interactive window
station and desktop, winsta0\default , in the lpDesktop member of the STARTUPINFO
CreateProcessAsUser does not load the specified user s profile into the
HKEY_USERS registry key. This means that access to information in the
HKEY_CURRENT_USER registry key may not produce results consistent with a normal
interactive logon. It is your responsibility to load the user s registry hive
into HKEY_USERS before calling CreateProcessAsUser.
If the lpEnvironment
parameter is NULL, the new process inherits the environment of the calling
process. CreateProcessAsUser does not automatically modify the
environment block to include environment variables specific to the user
represented by hToken. For example, the USERNAME and USERDOMAIN
variables are inherited from the calling process if lpEnvironment is
NULL. It is your responsibility to prepare the environment block for the new
process and specify it in lpEnvironment.
CreateProcessAsUser allows you to access the specified directory and
executable image in the security context of the caller or the target user. By
default, CreateProcessAsUser accesses the directory and executable image
in the security context of the caller. In this case, if the caller does not
have access to the directory and executable image, the function fails. To
access the directory and executable image using the security context of the
target user, specify hToken in a call to the ImpersonateLoggedOnUser
The new
process and the new thread handles are created with full access rights
(PROCESS_ALL_ACCESS and THREAD_ALL_ACCESS). For either handle, if a security
descriptor is not provided, the handle can be used in any function that
requires an object handle of that type. When a security descriptor is provided,
an access check is performed on all subsequent uses of the handle before access
is granted. If the access check denies access, the requesting process is not
able to use the handle to gain access to the process or thread.
If the lpProcessAttributes
parameter is NULL, the default security descriptor for the user referenced in
the hToken parameter will be used. This security descriptor may not allow
access for the caller, in which case the process may not be opened again once
it is run. The handle returned in the PROCESS_INFORMATION
Handles in PROCESS_INFORMATION
must be closed with CloseHandle
The process
is assigned a process identifier. The identifier is valid until the process
terminates. It can be used to identify the process, or specified in the OpenProcess
When
specifying an application name in the lpApplicationName or lpCommandLine
strings, it doesn t matter whether the application name includes the filename
extension, with one exception: an MS-DOS - based or Windows-based application whose filename extension is .COM
must include the .COM extension.
The calling
thread can use the WaitForInputIdle
The preferred
way to shut down a process is by using the ExitProcess
ExitProcess, ExitThread70TS0Y, CreateRemoteThread , and a process that is
starting (as the result of a call by CreateProcessAsUser) are serialized
between each other within a process. Only one of these events can happen at a
time. This means the following restrictions hold:
During process startup and DLL
initialization routines, new threads can be created, but they do not begin
execution until DLL initialization is done for the process.
Only one thread in a process
can be in a DLL initialization or detach routine at a time.
The ExitProcess function
does not return until no threads are executing DLL initialization or detach
routines.
See Also