BOOL CreateProcess(lpszImageName, lpszCommandLine, lpsaProcess, lpsaThread, fInheritHandles, fdwCreate, lpvEnvironment, lpszCurDir, lpsi, lppi) | |||||
LPCTSTR lpszImageName; | /* address of image file name | */ | |||
LPCTSTR lpszCommandLine; | /* address of the command line | */ | |||
LPSECURITY_ATTRIBUTES lpsaProcess; | /* optional process attrs | */ | |||
LPSECURITY_ATTRIBUTES lpsaThread; | /* optional thread attrs | */ | |||
BOOL fInheritHandles; | /* new process inherits handles? | */ | |||
DWORD fdwCreate; | /* creation flags | */ | |||
LPVOID lpvEnvironment; | /* address of optional environment | */ | |||
LPTSTR lpszCurDir; | /* address of new current directory | */ | |||
LPSTARTUPINFO lpsi; | /* address of STARTUPINFO | */ | |||
LPPROCESS_INFORMATION lppi; | /* address of PROCESSINFORMATION | */ |
The CreateProcess function creates a new process and thread, and runs a specified application in the new process.
lpszImageName
Points to a null-terminated string specifying the fully-qualified path name of the image file to run. If this parameter is NULL, the image file name must be the first whitespace-delimited token on the command line. If arguments are to be passed to the new process, this parameter should be NULL and the image-file name and arguments should be specified on the command line.
lpszCommandLine
Points to a null-terminated string specifying the command line for the application to run in the new process. If lpszImageName is NULL, the first whitespace-delimited token of the command line specifies the image-file name. If the file name does not contain an extension, .EXE is assumed. If the file name does not contain a directory path, Windows will search for the executable file in:
1.The current directory
2.The windows system directory
3.The windows directory
4.The directories listed in the path environment variable
lpsaProcess
Points to a SECURITY_ATTRIBUTES data structure that specifies the security attributes for the created process.
The SECURITY_ATTRIBUTES structure has the following format:
typedef struct _SECURITY_ATTRIBUTES { /* sa */
DWORD nLength;
LPVOID lpSecurityDescriptor;
BOOL bInheritHandle;
} SECURITY_ATTRIBUTES;
If lpsaProcess is NULL, the process is created without a security descriptor, and the resulting handle is not inherited.
lpsaThread
Points to a SECURITY_ATTRIBUTES data structure that specifies the security attributes for the created thread.
If lpsaThread is NULL, the process is created without a security descriptor, and the resulting handle is not inherited.
fInheritHandles
If this parameter is TRUE, each handle in the calling process that was created with the inherit handle option is inherited by the new process. Inherited handles have the same value and access privileges as the original handles.
fdwCreate
Supplies additional flags that control the creation of the process, as shown in the following list:
Value | Meaning |
IDLE_PRIORITY_CLASS | The process will only be run when the system is idle. An idle process will always be preempted by any process with a higher priority class. A screen-saver application is an example of an Idle priority process. |
NORMAL_PRIORITY_CLASS | The process is a normal application with no special scheduling needs. This is the default priority class. Normal runnable processes will always preempt an Idle process; the idle process will only be scheduled when the normal process is blocked, and the normal process will preempt the idle process whenever the normal process can be run. |
HIGH_PRIORITY_CLASS | The process is a high priority application. It has special scheduling needs that must be addressed in order for it to run correctly. One example of such a need would be a background application that is normally idle. In response to some external event, it needs to display a pop-up window pre-empting anything else that happens to be running in the normal or idle priority classes. |
Extreme care should be taken when using the high priority class. It is possible to create a CPU-bound application in the high priority class that can soak up nearly all available cycles. | |
DEBUG_PROCESS | If this flag is set, the calling process is treated as a debugger, and the new process is a process being debugged. The kernel notifies the debugger of all debug events that occur in the process being debugged. If this flag is not set and the calling process is being debugged, then the new process becomes another process being debugged by the calling process' debugger. If this bit is not set and the calling process is not a process being debugged, no debugging-related actions occur. |
DEBUG_ONLY_THIS_PROCESS | If this flag is set, the calling process is treated as a debugger, and the new process is a process being debugged. If the new process creates additional processes, the kernel will not notify the debugger of any debug events that occur in the additional processes. |
CREATE_SUSPENDED | The initial thread of the process will not run until the process calls the ResumeThread function. |
CREATE_NEW_CONSOLE | The created process will have a new console, instead of inheriting the parent's console. |
This flag cannot be used with the DETACHED_PROCESS flag. | |
CREATE_NO_WINDOW | The created process will have a console, but no window. The process will not be able to obtain a window. |
DETACHED_PROCESS | The created process will not have a console. Calling a console function from a process with no console results in an error. The process can call AllocateConsole if it later wants to have a console. |
This flag cannot be used with the CREATE_NEW_CONSOLE flag. |
lpvEnvironment
Points to an environment block for the new process. If this parameter is NULL, the new process uses the environment of the calling process.
lpszCurDir
Points to a null-terminated string that specifies the current drive and directory for the new process. The string must be a fully qualified pathname that includes a drive letter.
if lpszCurDir 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 want to start an application and specify its initial drive and working directory.
lpsi
Points to a STARTUPINFO structure that specifies how the main window for the new process should appear.
The STARTUPINFO structure has the following form:
typedef struct _STARTUPINFO { /* si */
DWORD cb;
LPTSTR lpReserved;
LPTSTR lpDesktop;
LPSTR lpTitle;
DWORD dwX;
DWORD dwY;
DWORD dwXSize;
DWORD dwYSize;
DWORD dwXCountChars;
DWORD dwYCountChars;
DWORD dwFillAttribute;
DWORD dwFlags;
WORD wShowWindow;
WORD cbReserved2;
LPBYTE lpReserved2;
} STARTUPINFO, *LPSTARTUPINFO;
lppi
Points to a PROCESS_INFORMATION structure that receives identification information about the new process.
The PROCESS_INFORMATION structure has the following form:
typedef struct _PROCESS_INFORMATION { /* pi */
HANDLE hProcess;
HANDLE hThread;
DWORD dwProcessId;
DWORD dwThreadId;
} PROCESS_INFORMATION;
The return value is TRUE if the function was successful, or FALSE if an error occurred. Use the GetLastError function to obtain extended error information.
The CreateProcess function should be used in Win32 to run a new program. The WinExec and LoadModule functions are still available, but they are are implemented as calls to the CreateProcess function.
The CreateProcess function may be used as either a wide-character function (where text arguments must use Unicode) or an ANSI function (where text arguments must use characters from the Windows 3.x character set installed).
The created process remains in the system until all threads within the process have terminated and all handles to the process and any of its threads have been closed through calls to CloseHandle. The handles for both the process and the main thread must be closed through calls to CloseHandle. If these handles are not needed, it is best to close them immediately after the process is created.
When the last thread in a process terminates, all objects opened by the process are implicitly closed. The process's termination status changes from its initial value of STATUS_PENDING to the termination status of the last thread to terminate. The process object is then set to the signalled state, satisfying all waits on the object.
In addition to creating a process, CreateProcess also creates a thread object. The thread is created with an initial stack whose size is described in the image header of the specified program's executable file. The thread begins execution at the image's entrypoint.
The process is assigned a 32-bit process identifier. The ID is valid until the process terminates. It may be used to identify the process, or open a handle to the process to perform some action on the process. The initial thread in the process is also assigned a 32-bit thread identifier. The ID is valid until the thread terminates and by be used to uniquely identify the thread within the system.
The preferred way to shut down a process is by using the ExitProcess command, because this function notifies all DLLs attached to the process of the approaching termination. Other means of shutting down a process do not notify the attached DLLs.
ExitProcess, ExitThread, CreateThread, and a process that is starting (as the result of a CreateProcess call) are serialized between each other within a process. Only one of these events can happen in an address space at a time. This means that:
During process startup and DLL initialization routines, new threads may be created, but they will not begin execution until DLL initialization is done for the process.
Only one thread in a process may be in a DLL initialization or detach routine at a time.
ExitProcess will block until no threads are in their DLL initialization or detach routines.
This example shows how to create a process, wait for it to exit, pick up its exit status, and close the thread and process handles:
fSuccess = CreateProcess(...); /* try to create a process */
if (fSuccess) { /* if we were successful... */
hProcess = ProcessInformation.hProcess;
hThread = ProcessInformation.hThread;
/* wait for the process to complete */
dw = WaitForSingleObject(hProcess, INFINITE) ;
if (dw != 0xFFFFFFFF) { /* if we saw success ... */
/* pick up an exit code for the process */
fExit = GetExitCodeProcess(hProcess, &dwExitCode) ;
}
/* close the process and thread object handles */
CloseHandle(hThread) ;
CloseHandle(hProcess) ;
}
This example shows how to create a detached process. The thread and process handles can be closed immediately after the new process is created.
fSuccess = CreateProcess(...); /* try to create a process */
if (fSuccess) { /* if we were successful... */
/* close the thread and process object handles */
CloseHandle(ProcessInformation.hThread) ;
CloseHandle(ProcessInformation.hProcess) ;
}
CloseHandle, ExitProcess, OpenProcess, TerminateProcess