- WinAPI Programmer's References
Telephony API (TAPI)
- Websites for programmers
Unix Manual Pages
- Software for programmers
- Follow us
- Share this page
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 function, except that the new process runs in the security context of the
user represented by the hToken parameter. By default, the new process is non-interactive, that is, it runs
on a desktop that is not visible and cannot receive user input. Also, by
default, the new process inherits the environment of the calling process, rather than
the environment associated with the specified user.
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 function to get a primary token that represents a specified user.
Alternatively, you can call the DuplicateTokenEx function to convert an impersonation token into a primary token. This allows
a server application that is impersonating a client to create a process that
has the security context of the client.
The other parameters of the CreateProcessAsUser function behave just like the analogous parameters of the CreateProcess function.
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.
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 GetCommandLine 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:
| 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
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.
Pointer to a SECURITY_ATTRIBUTES structure that specifies a security descriptor for the new process and
determines whether child processes can inherit the returned handle. If lpProcessAttributes is NULL, the process gets a default security descriptor and the handle cannot
Pointer to a SECURITY_ATTRIBUTES structure that specifies a security descriptor for the new process and
determines whether child processes can inherit the returned handle. If lpThreadAttributes is NULL, the thread gets a default security descriptor and the handle cannot
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.
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:
- The directory from which the application loaded.
- The current directory.
- The 32-bit Windows system directory. Use the GetSystemDirectory function to get the path of this directory. The name of this directory is
- 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
- The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.
- The directories that are listed in the PATH environment variable.
||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.
||The new process has a new console, instead of inheriting the parent's console.
This flag cannot be used with the DETACHED_PROCESS flag.
||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.
||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
||The primary thread of the new process is created in a suspended state, and
does not run until the ResumeThread function is called.
||If set, the environment block pointed to by lpEnvironment uses Unicode characters. If clear, the environment block uses ANSI characters.
||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.
||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.
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:
||For console processes, the new process does not have access to the console of
the parent process. The new process can call the AllocConsole function at a later time to create a new console. This flag cannot be used
with the CREATE_NEW_CONSOLE flag.
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:
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
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.
Points to a STARTUPINFO structure that specifies how the main window for the new process should
Points to a PROCESS_INFORMATION structure that receives identification information about the new process.
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.
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 structure. In addition, before calling CreateProcessAsUser, you must change the discretionary access control list (DACL) of both the
default interactive window station and the default desktop. The DACLs for the
window station and desktop must grant access to the user represented by the hToken parameter.
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 function before calling CreateProcessAsUser.
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 structure is valid and will continue to have all access. This is also true
for thread attributes.
Handles in PROCESS_INFORMATION must be closed with CloseHandle when they are no longer needed.
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 function to open a handle to the process. The initial thread in the process
is also assigned a thread identifier. The identifier is valid until the thread
terminates and can be used to uniquely identify the thread within the system.
These identifiers are returned in the PROCESS_INFORMATION structure.
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 function to wait until the new process has finished its initialization and is
waiting for user input with no input pending. This can be useful for
synchronization between parent and child processes, because CreateProcessAsUser returns without waiting for the new process to finish its initialization. For
example, the creating process would use WaitForInputIdle before trying to find a window associated with the new process.
The preferred way to shut down a process is by using the ExitProcess function, because this function notifies all dynamic-link libraries (DLLs)
attached to the process of the approaching termination. Other means of shutting
down a process do not notify the attached DLLs. Note that when a thread calls ExitProcess, other threads of the process are terminated without an opportunity to
execute any additional code (including the thread termination code of attached DLLs).
ExitProcess, ExitThread, CreateThread, 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:
||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.
||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.
||Indicates a normal process with no special scheduling needs.
||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.
AllocConsole, CloseHandle, CreateProcess, CreateRemoteThread, CreateThread, DuplicateTokenEx, ExitProcess, ExitThread, GenerateConsoleCtrlEvent, GetCommandLine, GetEnvironmentStrings, GetExitCodeProcess, GetFullPathName, GetStartupInfo, GetSystemDirectory, GetWindowsDirectory, ImpersonateLoggedOnUser, LoadModule, LogonUser, OpenProcess, PROCESS_INFORMATION, ResumeThread, SECURITY_ATTRIBUTES, SetConsoleCtrlHandler, SetErrorMode, STARTUPINFO, TerminateProcess, WaitForInputIdle, WinExec
- 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
- 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
Programming books recommended by Amazon.com
More programming books on Amazon.com