CreateProcess函数
接下来进入到本章最重要的知识点:CreateProcess函数。
该函数用以创建一个进程:
Bool CreateProcess( PCTSTR pszApplicationName, PTSTR pszCommandLine, PSECURTITY_ATTRIBUTES psaProcess, PSECUTRITY_ATTRIBUTE psaThread, Bool hInheritHandles, DWROD fdwCreate, PVOID pvEnvironment, PCTSTR pszCurDir, PSTARTUPINFO psiStartInfo, PPROCESS_INFORMATION ppiProcInfo ); |
当此函数被调用时,系统将首先创建一个进程对象,其初始使用计数为1。进程内核对象并不是进程本身,而是操作系统用来管理这个进程的一个数据结构。此后系统为新进程创建一个虚拟地址空间,并将可执行文件的代码及数据加载到进程的地址空间。然后系统会新进程的主线程创建一个线程内核对象,也将其使用计数设为1。和进程内核对象一样它也是操作系统用以管理线程的数据结构。主线程首先会执行C/C++运行时的启动函数,启动函数调用入口函数。进程被创建成功后CreateProcess返回true,函数返回前CreateProcess可能还没有完全初始化好。
psaApplicationName和pszCommandLine分别指定新进程要使用的可执行文件称和要传给新进程的命令行字符串。
注意此处的pszCommandLine是非常量字符串。传入常量字符串将会导致访问违规,因为在内部CreateProcess会修改传入的命令行字符串,返回时再将这个字符串还原。
所以一下代码是错误的:
STARTUPINFO si={sizeof(si)}; PROCESS_INFORMATION pi; CreateProcess(NULL,TEXT (“NOTEPAD”),NULL,NULL,FALSE,0,NULL,NULL,&si,&pi); |
因为TEXT("NOTEPAD")是常量字符串,当CreateProcess试图修改字符串会引起访问违规。解决方法是将TEXT("NOTEPAD")放在一个缓冲区内:
STARTUPINFO si={sizeof(si)}; PROCESS_INFORMATION pi; TCHAR cmdLine[200]=TEXT("NOTEPAD"); CreateProcess(NULL,cmdLine,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi);
|
这一点要特别注意,很容易出错!!!!这也有个例外,windows vista以及win7的ANSI版本以上是不会发生访问违规的,因为它们会为命令行创建一个临时副本。
在解析命令行时,CreateProcess会检查字符串中第一个标记,假定此标记就是我们想运行的可执行文件名称。如果可执行文件没有扩展名,就会默认是.exe扩展名。CreateProcess会在以下目录下搜索可执行文件:
1:主调进程.exe文件所在目录。
2:主调进程的当前目录。
3:windows系统目录。即System32目录。
4:windows目录。
5:PATH环境变量中列出的目录。