首页 > 代码库 > CreateProcess函数
CreateProcess函数
调用CreateProcess函数来创建一个进程:
一个线程调用CreateProcess时,系统将创建一个进程内核对象,其初始使用计数为1.进程内核对象不是进程本身,而是操作系统用来管理这个进程的一个小型数据结构——可以把进程内核对象想象成由进程统计信息构成的一个小型数据结构。然后,系统为新进程创建一个虚拟地址空间,并将可执行文件(和所有必要的DLL)的代码及数据加载到进程的地址空间
然后,系统为新进程的主线程创建一个线程内核对象(其使用计数为1)。和进程内核对象一样,线程内核对象也是一个小型数据结构,操作系统用它来管理这个线程。这个主线程一开始就会执行C/C++运行时的启动例程,它是由链接器设为应用程序入口的,最终会调用应用程序WinMain,wWinMain、main或wmain函数。如果系统成功创建了新进程和主线程,CreateProcess将返回TRUE
BOOL CreateProcess(LPCTSTR lpApplicationName, LPTSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation);
参数
lpApplicationName:指定新进程要使用的可执行文件的名称
lpCommandLine:指定要传给新进程的命令行字符串,lpCommandLine是一个非“常量字符串”的地址。在内部,CreateProcess实际上会修改我们传给它的命令行字符串。但在CreateProcess返回之前,它会将这个字符串还原为原来的样子;鉴于此,若命令行字符包含在文件映像的只读部分,就会引起访问违例。CreateProcess会检查字符串中的第一个标记,并假定此标记是我们想运行的可执行文件的名称
lpProcessAttributes:进程内核对象安全属性,若为NULL,将指定默认的安全描述符;若为非NULL,当lpProcessAttributes->bInheritHandle为TRUE时,子进程将继承父进程中所有可继承的句柄;当lpProcessAttributes->bInheritHandle为FALSE时,子进程讲无法继承父进程中的任何句柄
lpThreadAttributes:主线程内核对象安全属性,若为NULL,将指定默认的安全描述符;若为非NULL,当lpThreadAttributes->bInheritHandle为TRUE时,父进程的主线程内核对象将被继承;当lpThreadAttributes->bInheritHandle为FALSE时,父进程的主线程内核对象不可继承,不管传给lpProcessAttributes->bInheritHandle的值是多少
bInheritHandles:指定子进程是否能继承父进程中可继承的内核对象,若为TRUE则可继承,若为FALSE则不可继承
dwCreationFlags:标识了影响新进程创建方式的标志(flag)。多个标志可以使用按位或起来,以便同时指定多个标志组合
IDLE_PRIORITY_CLASS:低
BELOW_NORMAL_PRIORITY_CLASS:标准
ABOVE_NORMAL_PRIORITY_CLASS:高于标准
HIGH_PRIORITY_CLASS:高
REALTIME_PRIORITY_CLASS:实时
DEBUG_PROCESS:父进程希望调试子进程以及子进程将来生成的所有进程
DEBUG_ONLY_THIS_PROCESS:只有在关系最近的子进程中发生特定事件时,父进程才会得到通知
CREATE_SUSPENDED:创建新进程的同时挂起其主线程。这样一来,父进程就可以修改子进程地址空间中的内存,更改子进程的主线程优先级,或者在进程执行任何代码之前,将此进程添加到一个作业(job)中。父进程修改好子进程之后,可以调用ResumeThread函数来允许子进程执行代码
DETACHED_PROCESS:阻止一个基于CUI的进程访问其父进程的控制台窗口,并告诉系统将它的输出发送到一个新的控制台窗口,如果一个基于CUI的进程是由另一个基于CUI的进程创建的,那么默认情况下,新进程将使用父进程的控制台窗口
CREATE_NEW_CONSOLE:为新进程创建一个新的控制台窗口。如果同时指定DETACHED_PROCESS和CREATE_NEW_CONSOLE,会导致一个错误
CREATE_NO_WINDOWS:不要为应用程序创建人和控制台窗口。可以使用这个标志来执行没有用户界面的控制台应用程序
CREATE_NEW_PROCESS_GROUP:修改用户按Ctrl+C或Ctrl+Break时获得通知的进程列表
CREATE_DEFAULT_ERROR_MODE:新进程不会进程父进程的错误模式而使用默认的错误模式
CREATE_UNICODE_ENVIRONMENT:子进程的环境块应包含Unicode字符。进程的环境块默认包含的是ANSI字符串
CREATE_FORCEDOS:强制系统运行一个嵌入在16位OS/2应用程序中的MS-DOS应用程序
CREATE_BREAKAWAY_FROM_JOB:标志允许一个作业中的进程生成一个和作业无关的进程
EXTENDED_STARTUPINFO_PRESENT:标志向操作系统表明传给lpStartupInfo参数的是一个STARTUPINFOEX结构
fdwCreate参数还允许我们指定一个优先级类(priority class),对大多数程序都不应该这样做——系统会为新进程分配一个默认的优先级类,可指定的优先级如下(由低到高):
lpEnvironment:指向一块内存,其中包含新进程要使用的环境字符串
lpCurrentDirectory:子进程的当前驱动器和目录
lpStartupInfo:指向一个STARTUPINFO或STARTUPINFOEX结构,通常情况下是使用默认即可(将所有成员初始化为0,并将cb成员设为此结构的大小)
lpProcessInformation:[out],指向一个PROCESS_INFORMATION结构,函数在返回之前,会初始化这个结构体。如前所述,创建一个新的进程,会导致系统创建一个进程内核对象和一个线程内核对象。在创建时,系统会为每个对象指定一个初始的使用计数1.然后,在CreateProcess返回之前,它会使用完全访问权限打开进程对象和线程对象,并将与之相关的句柄放入lpProcessInformation的hProcess和hThread成员中。当CreateProcess在内部打开这些对象时,每个对象的使用计数变为2。这意味着系统要想释放进程对象,进程必须终止(使用计数递减1),而且父进程必须调用CloseHandle(使用计数再次递减1,变为0)。类似地,要想释放线程对象,线程必须终止而且父进程必须关闭到线程对象的句柄
返回值
CreateProcess在进程完全初始化好之前就返回TRUE。这意味着操作系统加载程序(loader)尚未尝试定位所有必要的DLL。如果一个DLL找不到或者不能正确初始化,进程就会终止。因为CreateProcess返回TRUE,所以父进程不会不会注意到任何初始化问题
若失败则返回FALSE