The Windows Process, thread and synchronization: Functions used in program examples ofWindow Processes & Threads 1,Window Processes & Threads 2,Window Processes & Threads 3,Window Processes & Threads 4,Window Processes & Threads 5 and Window Processes & Threads 6, wherever applicable. To learn about function you can jump toC & C++ functions tutorial.
The Windows Processes Page Index:
CreateProcess()
|
Parameters
lpApplicationName - [in] Pointer to a null-terminated string that specifies the module to execute. The specified module can be a Windows-based application. 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. The string can specify the full path and file name of the module to execute or it can specify a partial name. In the case of a partial name, the function uses the current drive and current directory to complete the specification. The function will not use the search path. If the file name does not contain an extension, .exe is assumed. Therefore, if the file name extension is .com, this parameter must include the.com extension.
The lpApplicationName parameter can be NULL. In that case, the module name must be the first white space-delimited token in the lpCommandLine string. If you are using a long file name that contains a space, use quoted strings to indicate where the file name ends and the arguments begin; otherwise, the file name is ambiguous. For example, consider the string "c:\program files\sub dir\program name". This string can be interpreted in a number of ways. The system tries to interpret the possibilities in the following order:
If the executable module is a 16-bit application, lpApplicationName should be NULL, and the string pointed to by lpCommandLine should specify the executable module as well as its arguments.
lpCommandLine - [in, out] Pointer to a null-terminated string that specifies the command line to execute. The maximum length of this string is 32K characters. For Windows 2000: The maximum length of this string is MAX_PATH characters.The Unicode version of this function, CreateProcessW(), will fail if this parameter is a const string.The lpCommandLine parameter can be NULL. In that case, the function uses the string pointed to by lpApplicationName as the command line.If both lpApplicationName andlpCommandLine are non-NULL, the null-terminated string pointed to bylpApplicationName specifies the module to execute, and the null-terminated string pointed to bylpCommandLine specifies the command line. The new process can use GetCommandLine() to retrieve the entire command line. Console processes written in C can use the argc and argv arguments to parse the command line. Becauseargv[0] is the module name, C programmers generally repeat the module name as the first token in the command line.If lpApplicationName is NULL, the first white-space – delimited token of the command line specifies the module name. If you are using a long file name that contains a space, use quoted strings to indicate where the file name ends and the arguments begin (see the explanation for thelpApplicationName parameter). If the file name does not contain an extension, .exe is appended. Therefore, if the file name extension is .com, this parameter must include the .com extension. If the file name ends in a period (.) with no extension, or if the file name contains a path, .exe is not appended. If the file name does not contain a directory path, the system searches for the executable file in the following sequence:
The directory from which the application loaded.
The current directory for the parent process.
The 32-bit Windows system directory. Use the GetSystemDirectory() function to get the path of this directory.
For Windows Me/98/95: The Windows system directory. Use the GetSystemDirectory() function to get the path of this directory.
The 16-bit Windows system directory. There is no function that obtains the path of this directory, but it is searched. The name of this directory is System.
The Windows directory. Use the GetWindowsDirectory() function to get the path of this directory.
The directories that are listed in thePATH environment variable.
The system adds a null character to the command line string to separate the file name from the arguments. This divides the original string into two strings for internal processing.
lpProcessAttributes - [in] Pointer to a SECURITY_ATTRIBUTES structure that determines whether the returned handle can be inherited by child processes. If lpProcessAttributes is NULL, the handle cannot be inherited. The lpSecurityDescriptor member of the structure specifies a security descriptor for the new process. IflpProcessAttributes is NULL or lpSecurityDescriptor is NULL, the process gets a default security descriptor. The ACLs in the default security descriptor for a process come from the primary or impersonation token of the creator.
lpThreadAttributes - [in] Pointer to a SECURITY_ATTRIBUTES structure that determines whether the returned handle can be inherited by child processes. If lpThreadAttributes is NULL, the handle cannot be inherited. The lpSecurityDescriptor member of the structure specifies a security descriptor for the main thread. IflpThreadAttributes is NULL or lpSecurityDescriptor is NULL, the thread gets a default security descriptor. The ACLs in the default security descriptor for a thread come from the primary or impersonation token of the creator.
bInheritHandles - [in] If this parameter TRUE, each inheritable handle in the calling process is inherited by the new process. If the parameter is FALSE, the handles are not inherited. Note that inherited handles have the same value and access rights as the original handles.
dwCreationFlags - [in] Flags that control the priority class and the creation of the process.This parameter also controls the new process's priority class, which is used to determine the scheduling priorities of the process's threads. If none of the priority class flags is specified, the priority class defaults to NORMAL_PRIORITY_CLASS unless the priority class of the creating process isIDLE_PRIORITY_CLASS or BELOW_NORMAL_PRIORITY_CLASS. In this case, the child process receives the default priority class of the calling process.
lpEnvironment - [in] Pointer 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.An environment block can contain either Unicode or ANSI characters. If the environment block pointed to by lpEnvironment contains Unicode characters, be sure that dwCreationFlags includesCREATE_UNICODE_ENVIRONMENT.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 - [in] Pointer to a null-terminated string that specifies the full path to the current directory for the process. The string can also specify a UNC path.If this parameter is NULL, the new process will have the same current drive and directory as the calling process. This feature is provided primarily for shells that need to start an application and specify its initial drive and working directory.
lpStartupInfo - [in] Pointer to a STARTUPINFO structure that specifies the window station, desktop, standard handles, and appearance of the main window for the new process.
lpProcessInformation - [out] Pointer to a PROCESS_INFORMATION structure that receives identification information about the new process. Handles in PROCESS_INFORMATION must be closed with CloseHandle() when they are no longer needed.
Some Remarks
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. It can be specified in the OpenThread() function to open a handle to the thread. 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.
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 CreateProcess() 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 sends notification of approaching termination to all DLLs attached to the process. Other means of shutting down a process do not notify the attached DLLs. Note that when a thread callsExitProcess(), other threads of the process are terminated without an opportunity to execute any additional code (including the thread termination code of attached DLLs).A parent process can directly alter the environment variables of a child process during process creation. This is the only situation when a process can directly change the environment settings of another process.If an application provides an environment block, the current directory information of the system drives is not automatically propagated to the new process. For example, there is an environment variable named =C: whose value is the current directory on drive C. An application must manually pass the current directory information to the new process. To do so, the application must explicitly create these environment variable strings, sort them alphabetically (because the system uses a sorted environment), and put them into the environment block. Typically, they will go at the front of the environment block, due to the environment block sort order.
One way to obtain the current directory information for a drive X is to call GetFullPathName("X:",..). That avoids an application having to scan the environment block. If the full path returned is X:\, there is no need to pass that value on as environment data, since the root directory is the default current directory for drive X of a new process.
Note: The name of the executable in the command line that the operating system provides to a process is not necessarily identical to that in the command line that the calling process gives to the CreateProcess() function. The operating system may prepend a fully qualified path to an executable name that is provided without a fully qualified path.When a process is created with CREATE_NEW_PROCESS_GROUP specified, an implicit call to SetConsoleCtrlHandler(NULL,TRUE) is made on behalf of the new process; this means that the new process has CTRL+C disabled. This lets shells handle CTRL+C themselves, and selectively pass that signal on to sub-processes. CTRL+BREAK is not disabled, and may be used to interrupt the process/process group.For Windows Me/98/95: CreateProcessW() is supported by the Microsoft Layer for Unicode. To use this, you must add certain files to your application, as outlined in Microsoft Layer for Unicode on Windows Me/98/95 Systems.
Security Remarks
The first parameter, lpApplicationName, can be NULL, in which case the executable name must be in the white space-delimited string pointed to by lpCommandLine. If the executable or path name has a space in it, there is a risk that a different executable could be run because of the way the function parses spaces. The following example is dangerous because the function will attempt to run "Program.exe", if it exists, instead of "MyApp.exe".
CreateProcess(NULL, "C:\\Program Files\\MyApp", ...)
If a malicious user were to create an application called "Program.exe" on a system, any program that incorrectly calls CreateProcess() using the Program Files directory will run this application instead of the intended application.
To avoid this problem, do not pass NULL for lpApplicationName. If you do pass NULL for lpApplicationName, use quotation marks around the executable path in lpCommandLine, as shown in the example below.
CreateProcess(NULL, "\"C:\\Program Files\\MyApp.exe\" -L -S", ...)
CreateProcessAsUser()
Item | Description |
Function | CreateProcessAsUser(). |
Use | To create a new process and its primary thread. The new process then runs the 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.The CreateProcessWithLogonW() and CreateProcessWithTokenW() functions are similar to CreateProcessAsUser(), except that the caller does not need to call the LogonUser() function to authenticate the user and get a token.This function is also similar to the SHCreateProcessAsUserW() function. |
Prototype | BOOL CreateProcessAsUser( HANDLE hToken, LPCTSTR lpApplicationName, LPTSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation); |
Parameters | See below. |
Return value | 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(). |
Include file | <windows.h> |
Remark | Implemented as Unicode and ANSI versions. More remarks below. |
Table 2. |
Parameters
hToken - [in] Handle to a primary token that represents a user. The handle must have the TOKEN_QUERY,TOKEN_DUPLICATE, and TOKEN_ASSIGN_PRIMARY access rights. The user represented by the token must have read and execute access to the application specified by the lpApplicationName or the lpCommandLine parameter. To get a primary token that represents the specified user, call theLogonUser() function. 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.Terminal Services: The process is run in the session specified in the token. By default, this is the same session that called LogonUser(). To change the session, use the SetTokenInformation() function.
lpApplicationName - [in] Pointer to a null-terminated string that specifies the module to execute. The specified module can be a Windows-based application. 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.
The string can specify the full path and file name of the module to execute or it can specify a partial name. In the case of a partial name, the function uses the current drive and current directory to complete the specification. The function will not use the search path. If the file name does not contain an extension, .exe is assumed. Therefore, if the file name extension is .com, this parameter must include the .com extension.
The lpApplicationName parameter can be NULL. In that case, the module name must be the first white space-delimited token in the lpCommandLine string. If you are using a long file name that contains a space, use quoted strings to indicate where the file name ends and the arguments begin; otherwise, the file name is ambiguous. For example, consider the string "c:\program files\sub dir\program name". This string can be interpreted in a number of ways. The system tries to interpret the possibilities in the following order:
If the executable module is a 16-bit application, lpApplicationName should be NULL, and the string pointed to by lpCommandLine should specify the executable module as well as its arguments. By default, all 16-bit Windows-based applications created by CreateProcessAsUser() are run in a separate VDM (equivalent to CREATE_SEPARATE_WOW_VDM in CreateProcess()).
lpCommandLine - [in] Pointer to a null-terminated string that specifies the command line to execute. The maximum length of this string is 32,000 characters. Windows 2000: The maximum length of this string is MAX_PATH characters. The Unicode version of this function, CreateProcessAsUserW(), will fail if this parameter is a const string.The lpCommandLine parameter can be NULL. In that case, the function uses the string pointed to by lpApplicationName as the command line.If both lpApplicationName andlpCommandLine are non-NULL, *lpApplicationName specifies the module to execute, and *lpCommandLine specifies the command line. The new process can use GetCommandLine() to retrieve the entire command line. Console processes written in C can use the argc and argv arguments to parse the command line. Becauseargv[0] is the module name, C programmers generally repeat the module name as the first token in the command line.
If lpApplicationName is NULL, the first white-space – delimited token of the command line specifies the module name. If you are using a long file name that contains a space, use quoted strings to indicate where the file name ends and the arguments begin (see the explanation for thelpApplicationName parameter). If the file name does not contain an extension,.exe is appended. Therefore, if the file name extension is .com, this parameter must include the .com extension. If the file name ends in a period (.) with no extension, or if the file name contains a path,.exe is not appended. If the file name does not contain a directory path, the system searches for the executable file in the following sequence:
The directory from which the application loaded.
The current directory for the parent process.
The 32-bit Windows system directory. Use the GetSystemDirectory() function to get the path of this directory.
The 16-bit Windows system directory. There is no function that obtains the path of this directory, but it is searched.
The Windows directory. Use the GetWindowsDirectory() function to get the path of this directory.
The directories that are listed in thePATH environment variable.
The system adds a null character to the command line string to separate the file name from the arguments. This divides the original string into two strings for internal processing.
lpProcessAttributes - [in] 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. IflpProcessAttributes is NULL or lpSecurityDescriptor is NULL, the process gets a default security descriptor and the handle cannot be inherited. The default security descriptor is that of the user referenced in the hToken parameter. This security descriptor may not allow access for the caller, in which case the process may not be opened again after it is run. The process handle is valid and will continue to have full access rights.
lpThreadAttributes - [in] 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. IflpThreadAttributes is NULL or lpSecurityDescriptor is NULL, the thread gets a default security descriptor and the handle cannot be inherited. The default security descriptor is that of the user referenced in the hToken parameter. This security descriptor may not allow access for the caller.
bInheritHandles - [in] If this parameter is TRUE, each inheritable handle in the calling process is inherited by the new process. If the parameter is FALSE, the handles are not inherited. Note that inherited handles have the same value and access rights as the original handles. Terminal Services: You cannot inherit handles across sessions. Additionally, if this parameter is TRUE, you must create the process in the same session as the caller.
dwCreationFlags - [in] Flags that control the priority class and the creation of the process.This parameter also controls the new process's priority class, which is used to determine the scheduling priorities of the process's threads. If none of the priority class flags is specified, the priority class defaults toNORMAL_PRIORITY_CLASS unless the priority class of the creating process isIDLE_PRIORITY_CLASS or BELOW_NORMAL_PRIORITY_CLASS. In this case, the child process receives the default priority class of the calling process.
lpEnvironment - [in] Pointer 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.An environment block can contain either Unicode or ANSI characters. If the environment block pointed to by lpEnvironment contains Unicode characters, be sure that dwCreationFlags includesCREATE_UNICODE_ENVIRONMENT.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. To retrieve a copy of the environment block for a given user, use the CreateEnvironmentBlock() function.
lpCurrentDirectory - [in] Pointer to a null-terminated string that specifies the full path to the current directory for the process. The string can also specify a UNC path.If this parameter is NULL, the new process will have the same current drive and directory as the calling process. (This feature is provided primarily for shells that need to start an application and specify its initial drive and working directory.)
lpStartupInfo - [in] Pointer to a STARTUPINFO structure that specifies the window station, desktop, standard handles, and appearance of the main window for the new process.
lpProcessInformation - [out] Pointer to a PROCESS_INFORMATION structure that receives identification information about the new process.Handles in PROCESS_INFORMATION must be closed with CloseHandle() when they are no longer needed.
Some Remarks
Typically, the process that calls the CreateProcessAsUser() function must have the SE_ASSIGNPRIMARYTOKEN_NAME and SE_INCREASE_QUOTA_NAME privileges. However, if hToken is a restricted version of the caller's primary token, theSE_ASSIGNPRIMARYTOKEN_NAME privilege is not required. If the necessary privileges are not already enabled,CreateProcessAsUser() enables them for the duration of the call. CreateProcessAsUser() must be able to open the primary token of the calling process with theTOKEN_DUPLICATE and TOKEN_IMPERSONATE access rights.By default, CreateProcessAsUser() creates the new process on a non-interactive 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 or the logon session represented by the hToken parameter.
CreateProcessAsUser() does not load the specified user's profile into the HKEY_USERS registry key. Therefore, to access the information in the HKEY_CURRENT_USER registry key, you must load the user's profile information intoHKEY_USERS with the LoadUserProfile() function 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 andUSERDOMAIN 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 theImpersonateLoggedOnUser() function before calling CreateProcessAsUser().
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. It can be specified in the OpenThread() function to open a handle to the thread. 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.
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 sends notification of approaching termination to all DLLs attached to the process. Other means of shutting down a process do not notify the attached DLLs. Note that when a thread callsExitProcess(), other threads of the process are terminated without an opportunity to execute any additional code (including the thread termination code of attached DLLs).
Security Remarks
The lpApplicationName parameter can be NULL, in which case the executable name must be the first white space-delimited string in lpCommandLine. If the executable or path name has a space in it, there is a risk that a different executable could be run because of the way the function parses spaces. The following example is dangerous because the function will attempt to run "Program.exe", if it exists, instead of "MyApp.exe".
CreateProcessAsUser(hToken, NULL, "C:\\Program Files\\MyApp", ...)
If a malicious user were to create an application called "Program.exe" on a system, any program that incorrectly calls CreateProcessAsUser() using the Program Files directory will run this application instead of the intended application.
To avoid this problem, do not pass NULL for lpApplicationName. If you do pass NULL for lpApplicationName, use quotation marks around the executable path in lpCommandLine, as shown in the example below.
CreateProcessAsUser(hToken, NULL, "\"C:\\Program Files\\MyApp.exe\" -L -S", ...)
CreateProcessWithLogonW()
Item | Description |
Function | CreateProcessWithLogonW(). |
Use | To create a new process and its primary thread. The new process then runs the specified executable file in the security context of the specified credentials (user, domain, and password). It can optionally load the user profile for the specified user.The CreateProcessWithLogonW() and CreateProcessWithTokenW() functions are similar to the CreateProcessAsUser() function, except that the caller does not need to call theLogonUser() function to authenticate the user and get a token. |
Prototype | BOOL CreateProcessWithLogonW( LPCWSTR lpUsername, LPCWSTR lpDomain, LPCWSTR lpPassword, DWORD dwLogonFlags, LPCWSTR lpApplicationName, LPWSTR lpCommandLine, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInfo); |
Parameters | See below. |
Return value | 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(). |
Include file | <windows.h> |
Remark | Implemented only as Unicode. More remarks below. |
Table 3. |
Parameters
lpUsername - [in] Pointer to a null-terminated string that specifies the name of the user. This is the name of the user account to log on to. If you use the UPN format, user@DNS_domain_name, the lpDomain parameter must be NULL. The user account must have the Log On Locally permission on the local computer. This permission is granted to all users on workstations and servers, but only to administrators on domain controllers.
lpDomain - [in] Pointer to a null-terminated string that specifies the name of the domain or server whose account database contains the lpUsername account. If this parameter is NULL, the user name must be specified in UPN format.
lpPassword - [in] Pointer to a null-terminated string that specifies the clear-text password for the lpUsername account.
dwLogonFlags - [in] Logon option. This parameter can be zero or one of the following values.
Value | Meaning |
LOGON_WITH_PROFILE | Log on, and then load the user's profile in the HKEY_USERS registry key. The function returns after the profile has been loaded. Loading the profile can be time-consuming, so it is best to use this value only if you must access the information in theHKEY_CURRENT_USER registry key. Windows Server 2003 and Windows 2000: The profile is unloaded after the new process has been terminated, regardless of whether it has created child processes.Windows XP: The profile is unloaded after the new process and all child processes it has created have been terminated. |
LOGON_NETCREDENTIALS_ONLY | Log on, but use the specified credentials on the network only. The new process uses the same token as the caller, but the system creates a new logon session within LSA, and the process uses the specified credentials as the default credentials.This value can be used to create a process that uses a different set of credentials locally than it does remotely. This is useful in inter-domain scenarios where there is no trust relationship.The system does not validate the specified credentials. Therefore, the process can start, but it may not have access to network resources. |
Table 4 |
lpApplicationName - [in] Pointer to a null-terminated string that specifies the module to execute. The specified module can be a Windows-based application. 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. The string can specify the full path and file name of the module to execute or it can specify a partial name. In the case of a partial name, the function uses the current drive and current directory to complete the specification. The function will not use the search path. If the file name does not contain an extension, .exe is assumed. Therefore, if the file name extension is .com, this parameter must include the.com extension. The lpApplicationName parameter can be NULL. In that case, the module name must be the first white space-delimited token in the lpCommandLine string. If you are using a long file name that contains a space, use quoted strings to indicate where the file name ends and the arguments begin; otherwise, the file name is ambiguous. For example, consider the string "c:\program files\sub dir\program name". This string can be interpreted in a number of ways. The system tries to interpret the possibilities in the following order:
|
If the executable module is a 16-bit application, lpApplicationName should be NULL, and the string pointed to by lpCommandLine should specify the executable module as well as its arguments.
lpCommandLine - [in] Pointer to a null-terminated string that specifies the command line to execute. The maximum length of this string is 32,000 characters. Windows 2000: The maximum length of this string is MAX_PATH characters. This function will fail if this parameter is a const string.
The lpCommandLine parameter can be NULL. In that case, the function uses the string pointed to by lpApplicationName as the command line.
If both lpApplicationName andlpCommandLine are non-NULL, *lpApplicationName specifies the module to execute, and *lpCommandLine specifies the command line. The new process can use GetCommandLine() to retrieve the entire command line. Console processes written in C can use the argc andargv arguments to parse the command line. Because argv[0] is the module name, C programmers generally repeat the module name as the first token in the command line.If lpApplicationName is NULL, the first white-space – delimited token of the command line specifies the module name. If you are using a long file name that contains a space, use quoted strings to indicate where the file name ends and the arguments begin (see the explanation for thelpApplicationName parameter). If the file name does not contain an extension, .exe is appended. Therefore, if the file name extension is .com, this parameter must include the .com extension. If the file name ends in a period with no extension, or if the file name contains a path, .exe is not appended. If the file name does not contain a directory path, the system searches for the executable file in the following sequence:
The directory from which the application loaded.
The current directory for the parent process.
The 32-bit Windows system directory. Use the GetSystemDirectory() function to get the path of this directory.
The 16-bit Windows system directory. There is no function that obtains the path of this directory, but it is searched.
The Windows directory. Use the GetWindowsDirectory() function to get the path of this directory.
The directories that are listed in thePATH environment variable.
The system adds a null character to the command line string to separate the file name from the arguments. This divides the original string into two strings for internal processing.
dwCreationFlags - [in] Flags that control how the process is created. The CREATE_DEFAULT_ERROR_MODE,CREATE_NEW_CONSOLE, and CREATE_NEW_PROCESS_GROUP flags are enabled by default, even if you do not set the flag, the system will function as if it were set. You can specify additional flags as noted.
Value | Meaning |
CREATE_DEFAULT_ERROR_MODE | The new process does not inherit the error mode of the calling process. Instead, CreateProcessWithLogonW() gives the new process the current default error mode. An application sets the current default error mode by callingSetErrorMode(). This flag is enabled by default. |
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. This flag is enabled by default. |
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 lpProcessInfo parameter. Process groups are used by theGenerateConsoleCtrlEvent() function to enable sending a CTRL+C or CTRL+BREAK signal to a group of console processes. This flag is enabled by default. |
CREATE_SEPARATE_WOW_VDM | This flag is only valid starting a 16-bit Windows-based application. If set, the new process runs in a private Virtual DOS Machine (VDM). By default, all 16-bit Windows-based applications run in a single, shared VDM. The advantage of running separately is that a crash only terminates the single VDM; any other programs running in distinct VDMs continue to function normally. Also, 16-bit Windows-based applications that run in separate VDMs have separate input queues. That means that if one application stops responding 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 theResumeThread() function is called. |
CREATE_UNICODE_ENVIRONMENT | Indicates the format of thelpEnvironment parameter. If this flag is set, the environment block pointed to by lpEnvironment uses Unicode characters. Otherwise, the environment block uses ANSI characters. |
Table 5 |
This parameter also controls the new process's priority class, which is used to determine the scheduling priorities of the process's threads. For a list of values, see GetPriorityClass(). If none of the priority class flags is specified, the priority class defaults to NORMAL_PRIORITY_CLASS unless the priority class of the creating process isIDLE_PRIORITY_CLASS or BELOW_NORMAL_PRIORITY_CLASS. In this case, the child process receives the default priority class of the calling process.
lpEnvironment - [in] Pointer to an environment block for the new process. If this parameter is NULL, the new process uses the environment of the specified user instead of 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.An environment block can contain Unicode or ANSI characters. If the environment block pointed to by lpEnvironment contains Unicode characters, be sure that dwCreationFlags includesCREATE_UNICODE_ENVIRONMENT.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.To retrieve a copy of the environment block for a given user, use theCreateEnvironmentBlock() function.
lpCurrentDirectory - [in] Pointer to a null-terminated string that specifies the full path to the current directory for the process. The string can also specify a UNC path.If this parameter is NULL, the new process will have the same current drive and directory as the calling process. (This feature is provided primarily for shells that need to start an application and specify its initial drive and working directory.)
lpStartupInfo - [in] Pointer to a STARTUPINFO structure that specifies the window station, desktop, standard handles, and appearance of the main window for the new process. The application must add permission for the specified user account to the specified window station and desktop, even for WinSta0\Default.If the lpDesktop member is NULL or an empty string, the new process inherits the desktop and window station of its parent process. The application must add permission for the specified user account to the inherited window station and desktop.Windows XP and Windows 2000: CreateProcessWithLogonW() adds permission for the specified user account to the inherited window station and desktop.
lpProcessInfo - [out] Pointer to a PROCESS_INFORMATION structure that receives identification information for the new process, including a handle to the process. Handles in PROCESS_INFORMATION must be closed with the CloseHandle() function when they are no longer needed.
Some Remarks
By default, CreateProcessWithLogonW() 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 intoHKEY_USERS before calling CreateProcessWithLogonW(), using either LOGON_WITH_PROFILE, or by calling the LoadUserProfile() function.If the lpEnvironment parameter is NULL, the new process inherits the environment of the calling process.CreateProcessWithLogonW() does not automatically modify the environment block to include environment variables specific to the user. For example, the USERNAME andUSERDOMAIN 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.When created, the new process and thread handles receive 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 access is denied, the requesting process cannot use the handle to gain access to the process or thread.
To retrieve a security token, pass the process handle in the PROCESS_INFORMATION structure to the OpenProcessToken() function.
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. It can be specified in the OpenThread() function to open a handle to the thread. 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 PROCESS_INFORMATION.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 CreateProcessWithLogonW() 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 sends notification of approaching termination to all DLLs attached to the process. Other means of shutting down a process do not notify the attached DLLs. Note that when a thread callsExitProcess(), other threads of the process are terminated without an opportunity to execute any additional code (including the thread termination code of attached DLLs). CreateProcessWithLogonW() accesses the specified directory and executable image in the security context of the target user. If the executable image is on a network and a network drive letter is specified in the path, the network drive letter is not available to the target user, as network drive letters can be assigned for each logon. If a network drive letter is specified, this function will fail. If the executable image is on a network, use the UNC path.To compile an application that uses this function, define the _WIN32_WINNTmacro as0x0500 or later. Windows XP and Windows 2000: There is a limit to the number of child processes that can be created by this function and run simultaneously. On Windows 2000, this limit is MAXIMUM_WAIT_OBJECTS. On Windows XP, this limit is MAXIMUM_WAIT_OBJECTS*4. However, you may not be able to create this many processes due to system-wide quota limits.
Security Remarks
The lpApplicationName parameter can be NULL, in which case the executable name must be the first white space-delimited string in lpCommandLine. If the executable or path name has a space in it, there is a risk that a different executable could be run because of the way the function parses spaces. The following example is dangerous because the function will attempt to run "Program.exe", if it exists, instead of "MyApp.exe".
CreateProcessWithLogonW(..., "C:\\Program Files\\MyApp", ...)
If a malicious user were to create an application called "Program.exe" on a system, any program that incorrectly calls CreateProcessWithLogonW() using the Program Files directory will run this application instead of the intended application.
To avoid this problem, do not pass NULL for lpApplicationName. If you do pass NULL for lpApplicationName, use quotation marks around the executable path in lpCommandLine, as shown in the example below.
CreateProcessWithLogonW(..., "\"C:\\Program Files\\MyApp.exe\" -L -S", ...)
CreateProcessWithTokenW()
Item | Description |
Function | CreateProcessWithTokenW(). |
Use | To create a new process and its primary thread. The new process runs in the security context of the specified token. It can optionally load the user profile for the specified user. This function is similar to theCreateProcessWithLogonW() and CreateProcessAsUser() functions. This function and CreateProcessWithLogonW() do not require a call the LogonUser() function to authenticate the user and get a token. |
Prototype | BOOL CreateProcessWithTokenW( HANDLE hToken, DWORD dwLogonFlags, LPCWSTR lpApplicationName, LPWSTR lpCommandLine, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInfo); |
Parameters | See below. |
Return value | 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(). |
Include file | <windows.h> |
Remark | Implemented only as Unicode. More remarks below. |
Table 6. |
Parameters
hToken - [in] Handle to a primary token that represents a user. The handle must have the TOKEN_QUERY,TOKEN_DUPLICATE, and TOKEN_ASSIGN_PRIMARY access rights. The user represented by the token must have read and execute access to the application specified by the lpApplicationName or the lpCommandLine parameter. To get a primary token that represents the specified user, call the LogonUser function. 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.Terminal Services: The process is run in the session specified in the token. By default, this is the same session that called LogonUser(). To change the session, use the SetTokenInformation() function.
dwLogonFlags - [in] Logon option. This parameter can be zero or one of the following values.
Value | Meaning |
LOGON_WITH_PROFILE | Log on, and then load the user's profile in the HKEY_USERS registry key. The function returns after the profile has been loaded. Loading the profile can be time-consuming, so it is best to use this value only if you must access the information in theHKEY_CURRENT_USER registry key. Windows Server 2003 and Windows 2000: The profile is unloaded after the new process has been terminated, regardless of whether it has created child processes.Windows XP: The profile is unloaded after the new process and all child processes it has created have been terminated. |
LOGON_NETCREDENTIALS_ONLY | Log on, but use the specified credentials on the network only. The new process uses the same token as the caller, but the system creates a new logon session within LSA, and the process uses the specified credentials as the default credentials.This value can be used to create a process that uses a different set of credentials locally than it does remotely. This is useful in inter-domain scenarios where there is no trust relationship.The system does not validate the specified credentials. Therefore, the process can start, but it may not have access to network resources. |
Table 7 |
lpApplicationName - [in] Pointer to a null-terminated string that specifies the module to execute. The specified module can be a Windows-based application. 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.
The string can specify the full path and file name of the module to execute or it can specify a partial name. In the case of a partial name, the function uses the current drive and current directory to complete the specification. The function will not use the search path. If the file name does not contain an extension, .exe is assumed. Therefore, if the file name extension is .com, this parameter must include the.com extension.The lpApplicationName parameter can be NULL. In that case, the module name must be the first white space-delimited token in the lpCommandLine string. If you are using a long file name that contains a space, use quoted strings to indicate where the file name ends and the arguments begin; otherwise, the file name is ambiguous. For example, consider the string "c:\program files\sub dir\program name". This string can be interpreted in a number of ways. The system tries to interpret the possibilities in the following order:
If the executable module is a 16-bit application, lpApplicationName should be NULL, and the string pointed to by lpCommandLine should specify the executable module as well as its arguments.
lpCommandLine - [in] Pointer to a null-terminated string that specifies the command line to execute. The maximum length of this string is 32,000 characters. This function will fail if this parameter is a const string.The lpCommandLine parameter can be NULL. In that case, the function uses the string pointed to by lpApplicationName as the command line.If both lpApplicationName andlpCommandLine are non-NULL, *lpApplicationName specifies the module to execute, and *lpCommandLine specifies the command line. The new process can use GetCommandLine() to retrieve the entire command line. Console processes written in C can use the argc and argv arguments to parse the command line. Becauseargv[0] is the module name, C programmers generally repeat the module name as the first token in the command line.If lpApplicationName is NULL, the first white-space – delimited token of the command line specifies the module name. If you are using a long file name that contains a space, use quoted strings to indicate where the file name ends and the arguments begin (see the explanation for thelpApplicationName parameter). If the file name does not contain an extension, .exe is appended. Therefore, if the file name extension is .com, this parameter must include the .com extension. If the file name ends in a period (.) with no extension, or if the file name contains a path, .exe is not appended. If the file name does not contain a directory path, the system searches for the executable file in the following sequence:
The directory from which the application loaded.
The current directory for the parent process.
The 32-bit Windows system directory. Use the GetSystemDirectory() function to get the path of this directory.
The 16-bit Windows system directory. There is no function that obtains the path of this directory, but it is searched.
The Windows directory. Use the GetWindowsDirectory() function to get the path of this directory.
The directories that are listed in thePATH environment variable.
The system adds a null character to the command line string to separate the file name from the arguments. This divides the original string into two strings for internal processing.
dwCreationFlags - [in] Flags that control how the process is created. The CREATE_DEFAULT_ERROR_MODE,CREATE_NEW_CONSOLE, and CREATE_NEW_PROCESS_GROUP flags are enabled by default. You can specify additional flags as noted.
Value | Meaning |
CREATE_DEFAULT_ERROR_MODE | The new process does not inherit the error mode of the calling process. Instead, the new process gets the current default error mode. An application sets the current default error mode by calling SetErrorMode(). This flag is enabled by default. |
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. This flag is enabled by default. |
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 lpProcessInfo parameter. Process groups are used by theGenerateConsoleCtrlEvent() function to enable sending a CTRL+C or CTRL+BREAK signal to a group of console processes. This flag is enabled by default. |
CREATE_SEPARATE_WOW_VDM | This flag is only valid starting a 16-bit Windows-based application. If set, the new process runs in a private Virtual DOS Machine (VDM). By default, all 16-bit Windows-based applications run in a single, shared VDM. The advantage of running separately is that a crash only terminates the single VDM; any other programs running in distinct VDMs continue to function normally. Also, 16-bit Windows-based applications that run in separate VDMs have separate input queues. That means that if one application stops responding 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 theResumeThread() function is called. |
CREATE_UNICODE_ENVIRONMENT | Indicates the format of thelpEnvironment parameter. If this flag is set, the environment block pointed to by lpEnvironment uses Unicode characters. Otherwise, the environment block uses ANSI characters. |
Table 8 |
This parameter also controls the new process's priority class, which is used to determine the scheduling priorities of the process's threads. If none of the priority class flags is specified, the priority class defaults toNORMAL_PRIORITY_CLASS unless the priority class of the creating process isIDLE_PRIORITY_CLASS or BELOW_NORMAL_PRIORITY_CLASS. In this case, the child process receives the default priority class of the calling process.
lpEnvironment - [in] Pointer 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.An environment block can contain Unicode or ANSI characters. If the environment block pointed to by lpEnvironment contains Unicode characters, be sure that dwCreationFlags includesCREATE_UNICODE_ENVIRONMENT.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. To retrieve a copy of the environment block for a given user, use the CreateEnvironmentBlock() function.
lpCurrentDirectory - [in] Pointer to a null-terminated string that specifies the full path to the current directory for the process. The string can also specify a UNC path.If this parameter is NULL, the new process will have the same current drive and directory as the calling process. This feature is provided primarily for shells that need to start an application and specify its initial drive and working directory.
lpStartupInfo - [in] Pointer to a STARTUPINFO structure that specifies the window station, desktop, standard handles, and appearance of the main window for the new process. If the lpDesktop member is NULL or an empty string, the new process inherits the desktop and window station of its parent process. The function adds permission for the specified user account to the inherited window station and desktop. Otherwise, if this member specifies a desktop, it is the responsibility of the application to add permission for the specified user account to the specified window station and desktop, even forWinSta0\Default.
lpProcessInfo - [out] Pointer to a PROCESS_INFORMATION structure that receives identification information for the new process, including a handle to the process. Handles in PROCESS_INFORMATION must be closed with the CloseHandle() function when they are no longer needed.
Some Remarks
By default, CreateProcessWithTokenW() 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 intoHKEY_USERS by either using LOGON_WITH_PROFILE, or by calling the LoadUserProfile() function before calling this function.If the lpEnvironment parameter is NULL, the new process inherits the environment of the calling process.CreateProcessWithTokenW() does not automatically modify the environment block to include environment variables specific to the user. For example, the USERNAME andUSERDOMAIN 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.When created, the new process and thread handles receive 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 access is denied, the requesting process cannot use the handle to gain access to the process or thread.To retrieve a security token, pass the process handle in the PROCESS_INFORMATION structure to the OpenProcessToken() function.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. It can be specified in the OpenThread() function to open a handle to the thread. 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 PROCESS_INFORMATION.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 CreateProcessWithTokenW() 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 sends notification of approaching termination to all DLLs attached to the process. Other means of shutting down a process do not notify the attached DLLs. Note that when a thread callsExitProcess(), other threads of the process are terminated without an opportunity to execute any additional code (including the thread termination code of attached DLLs). To compile an application that uses this function, define the_WIN32_WINNTmacro as0x0500 or later.
Security Remarks
The lpApplicationName parameter can be NULL, in which case the executable name must be the first white space-delimited string in lpCommandLine. If the executable or path name has a space in it, there is a risk that a different executable could be run because of the way the function parses spaces. The following example is dangerous because the function will attempt to run "Program.exe", if it exists, instead of "MyApp.exe".
CreateProcessWithTokenW(..., "C:\\Program Files\\MyApp", ...)
If a malicious user were to create an application called "Program.exe" on a system, any program that incorrectly calls CreateProcessWithTokenW() using the Program Files directory will run this application instead of the intended application.To avoid this problem, do not pass NULL for lpApplicationName. If you do pass NULL for lpApplicationName, use quotation marks around the executable path in lpCommandLine, as shown in the example below.
CreateProcessWithTokenW(..., "\"C:\\Program Files\\MyApp.exe\" -L -S", ...)
CreateProcessWithLogonW()
Item | Description |
Function | CreateProcessWithLogonW(). |
Use | To create a new process and its primary thread. The new process then runs the specified executable file in the security context of the specified credentials (user, domain, and password). It can optionally load the user profile for the specified user. The CreateProcessWithLogonW() and CreateProcessWithTokenW() functions are similar to the CreateProcessAsUser() function, except that the caller does not need to call the LogonUser function to authenticate the user and get a token. |
Prototype | BOOL CreateProcessWithLogonW( LPCWSTR lpUsername, LPCWSTR lpDomain, LPCWSTR lpPassword, DWORD dwLogonFlags, LPCWSTR lpApplicationName, LPWSTR lpCommandLine, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInfo); |
Parameters | See below. |
Return value | 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(). |
Include file | <windows.h> |
Remark | Implemented only as Unicode. More remarks below. |
Table 9. |
Parameters
lpUsername - [in] Pointer to a null-terminated string that specifies the name of the user. This is the name of the user account to log on to. If you use the UPN format, user@DNS_domain_name, the lpDomain parameter must be NULL. The user account must have the Log On Locally permission on the local computer. This permission is granted to all users on workstations and servers, but only to administrators on domain controllers.
lpDomain - [in] Pointer to a null-terminated string that specifies the name of the domain or server whose account database contains the lpUsername account. If this parameter is NULL, the user name must be specified in UPN format.
lpPassword - [in] Pointer to a null-terminated string that specifies the clear-text password for the lpUsername account.
dwLogonFlags - [in] Logon option. This parameter can be zero or one of the following values.
Value | Meaning |
LOGON_WITH_PROFILE | Log on, and then load the user's profile in the HKEY_USERS registry key. The function returns after the profile has been loaded. Loading the profile can be time-consuming, so it is best to use this value only if you must access the information in theHKEY_CURRENT_USER registry key. Windows Server 2003 and Windows 2000: The profile is unloaded after the new process has been terminated, regardless of whether it has created child processes.Windows XP: The profile is unloaded after the new process and all child processes it has created have been terminated. |
LOGON_NETCREDENTIALS_ONLY | Log on, but use the specified credentials on the network only. The new process uses the same token as the caller, but the system creates a new logon session within LSA, and the process uses the specified credentials as the default credentials.This value can be used to create a process that uses a different set of credentials locally than it does remotely. This is useful in inter-domain scenarios where there is no trust relationship.The system does not validate the specified credentials. Therefore, the process can start, but it may not have access to network resources. |
Table 10 |
lpApplicationName - [in] Pointer to a null-terminated string that specifies the module to execute. The specified module can be a Windows-based application. 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. The string can specify the full path and file name of the module to execute or it can specify a partial name. In the case of a partial name, the function uses the current drive and current directory to complete the specification. The function will not use the search path. If the file name does not contain an extension, .exe is assumed. Therefore, if the file name extension is .com, this parameter must include the .com extension.The lpApplicationName parameter can be NULL. In that case, the module name must be the first white space-delimited token in the lpCommandLine string. If you are using a long file name that contains a space, use quoted strings to indicate where the file name ends and the arguments begin; otherwise, the file name is ambiguous. For example, consider the string "c:\program files\sub dir\program name". This string can be interpreted in a number of ways. The system tries to interpret the possibilities in the following order:
If the executable module is a 16-bit application, lpApplicationName should be NULL, and the string pointed to by lpCommandLine should specify the executable module as well as its arguments.
lpCommandLine - [in] Pointer to a null-terminated string that specifies the command line to execute. The maximum length of this string is 32,000 characters. Windows 2000: The maximum length of this string is MAX_PATH characters. This function will fail if this parameter is a const string.
The lpCommandLine parameter can be NULL. In that case, the function uses the string pointed to by lpApplicationName as the command line.
If both lpApplicationName andlpCommandLine are non-NULL, *lpApplicationName specifies the module to execute, and *lpCommandLine specifies the command line. The new process can use GetCommandLine() to retrieve the entire command line. Console processes written in C can use the argc andargv arguments to parse the command line. Because argv[0] is the module name, C programmers generally repeat the module name as the first token in the command line.If lpApplicationName is NULL, the first white-space – delimited token of the command line specifies the module name. If you are using a long file name that contains a space, use quoted strings to indicate where the file name ends and the arguments begin (see the explanation for thelpApplicationName parameter). If the file name does not contain an extension, .exe is appended. Therefore, if the file name extension is .com, this parameter must include the .com extension. If the file name ends in a period with no extension, or if the file name contains a path, .exe is not appended. If the file name does not contain a directory path, the system searches for the executable file in the following sequence:
The directory from which the application loaded.
The current directory for the parent process.
The 32-bit Windows system directory. Use the GetSystemDirectory() function to get the path of this directory.
The 16-bit Windows system directory. There is no function that obtains the path of this directory, but it is searched.
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 system adds a null character to the command line string to separate the file name from the arguments. This divides the original string into two strings for internal processing.
dwCreationFlags - [in] Flags that control how the process is created. The CREATE_DEFAULT_ERROR_MODE,CREATE_NEW_CONSOLE, and CREATE_NEW_PROCESS_GROUP flags are enabled by default, even if you do not set the flag, the system will function as if it were set. You can specify additional flags as noted.
Value | Meaning |
CREATE_DEFAULT_ERROR_MODE | The new process does not inherit the error mode of the calling process. Instead, CreateProcessWithLogonW() gives the new process the current default error mode. An application sets the current default error mode by callingSetErrorMode(). This flag is enabled by default. |
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. This flag is enabled by default. |
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 lpProcessInfo parameter. Process groups are used by theGenerateConsoleCtrlEvent() function to enable sending a CTRL+C or CTRL+BREAK signal to a group of console processes. This flag is enabled by default. |
CREATE_SEPARATE_WOW_VDM | This flag is only valid starting a 16-bit Windows-based application. If set, the new process runs in a private Virtual DOS Machine (VDM). By default, all 16-bit Windows-based applications run in a single, shared VDM. The advantage of running separately is that a crash only terminates the single VDM; any other programs running in distinct VDMs continue to function normally. Also, 16-bit Windows-based applications that run in separate VDMs have separate input queues. That means that if one application stops responding 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 theResumeThread() function is called. |
CREATE_UNICODE_ENVIRONMENT | Indicates the format of thelpEnvironment parameter. If this flag is set, the environment block pointed to by lpEnvironment uses Unicode characters. Otherwise, the environment block uses ANSI characters. |
Table 11 |
This parameter also controls the new process's priority class, which is used to determine the scheduling priorities of the process's threads. If none of the priority class flags is specified, the priority class defaults toNORMAL_PRIORITY_CLASS unless the priority class of the creating process isIDLE_PRIORITY_CLASS or BELOW_NORMAL_PRIORITY_CLASS. In this case, the child process receives the default priority class of the calling process.
lpEnvironment - [in] Pointer to an environment block for the new process. If this parameter is NULL, the new process uses the environment of the specified user instead of 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.An environment block can contain Unicode or ANSI characters. If the environment block pointed to by lpEnvironment contains Unicode characters, be sure that dwCreationFlags includesCREATE_UNICODE_ENVIRONMENT.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. To retrieve a copy of the environment block for a given user, use the CreateEnvironmentBlock() function.
lpCurrentDirectory - [in] Pointer to a null-terminated string that specifies the full path to the current directory for the process. The string can also specify a UNC path.If this parameter is NULL, the new process will have the same current drive and directory as the calling process. This feature is provided primarily for shells that need to start an application and specify its initial drive and working directory.
lpStartupInfo - [in] Pointer to a STARTUPINFO structure that specifies the window station, desktop, standard handles, and appearance of the main window for the new process. The application must add permission for the specified user account to the specified window station and desktop, even for WinSta0\Default. If the lpDesktop member is NULL or an empty string, the new process inherits the desktop and window station of its parent process. The application must add permission for the specified user account to the inherited window station and desktop.Windows XP and Windows 2000: CreateProcessWithLogonW() adds permission for the specified user account to the inherited window station and desktop.
lpProcessInfo - [out] Pointer to a PROCESS_INFORMATION structure that receives identification information for the new process, including a handle to the process. Handles in PROCESS_INFORMATION must be closed with the CloseHandle() function when they are no longer needed.
Some Remarks
By default, CreateProcessWithLogonW() 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 intoHKEY_USERS before calling CreateProcessWithLogonW(), using either LOGON_WITH_PROFILE, or by calling the LoadUserProfile() function.If the lpEnvironment parameter is NULL, the new process inherits the environment of the calling process.CreateProcessWithLogonW() does not automatically modify the environment block to include environment variables specific to the user. For example, the USERNAME andUSERDOMAIN 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.When created, the new process and thread handles receive 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 access is denied, the requesting process cannot use the handle to gain access to the process or thread.To retrieve a security token, pass the process handle in the PROCESS_INFORMATION structure to the OpenProcessToken() function.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. It can be specified in the OpenThread() function to open a handle to the thread. 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 PROCESS_INFORMATION.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 CreateProcessWithLogonW() 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 sends notification of approaching termination to all DLLs attached to the process. Other means of shutting down a process do not notify the attached DLLs. Note that when a thread callsExitProcess(), other threads of the process are terminated without an opportunity to execute any additional code (including the thread termination code of attached DLLs).
CreateProcessWithLogonW() accesses the specified directory and executable image in the security context of the target user. If the executable image is on a network and a network drive letter is specified in the path, the network drive letter is not available to the target user, as network drive letters can be assigned for each logon. If a network drive letter is specified, this function will fail. If the executable image is on a network, use the UNC path.
To compile an application that uses this function, define the _WIN32_WINNTmacro as0x0500 or later.Windows XP and Windows 2000: There is a limit to the number of child processes that can be created by this function and run simultaneously. On Windows 2000, this limit is MAXIMUM_WAIT_OBJECTS. On Windows XP, this limit is MAXIMUM_WAIT_OBJECTS*4. However, you may not be able to create this many processes due to system-wide quota limits.
Security Remarks
The lpApplicationName parameter can be NULL, in which case the executable name must be the first white space-delimited string in lpCommandLine. If the executable or path name has a space in it, there is a risk that a different executable could be run because of the way the function parses spaces. The following example is dangerous because the function will attempt to run "Program.exe", if it exists, instead of "MyApp.exe".
CreateProcessWithLogonW(..., "C:\\Program Files\\MyApp", ...)
If a malicious user were to create an application called "Program.exe" on a system, any program that incorrectly calls CreateProcessWithLogonW() using the Program Files directory will run this application instead of the intended application.To avoid this problem, do not pass NULL for lpApplicationName. If you do pass NULL for lpApplicationName, use quotation marks around the executable path in lpCommandLine, as shown in the example below.
CreateProcessWithLogonW(..., "\"C:\\Program Files\\MyApp.exe\" -L -S", ...)
----------------------------------------Part 1/5-----------------------------------------
Further reading and digging:
Microsoft Visual C++, online MSDN.
Structure, enum, union and typedef story can be foundatC & C++ function tutorial.
For Multi-bytes, Unicode characters and Localization please refer toMultibyte & Unicode 1 (Story) andMultibyte & Unicode 2 (Implementation).
Check the best selling C / C++ and Windows books at Amazon.com.