谁来和我一起读windows核心编程?[读书摘记]

v_JULY_v
博客专家认证
2010-11-16 07:42:29
一起来读windows核心编程
-----windows核心编程读书摘记



---------------------
混csdn前期回顾:
精选微软等数据结构+算法面试100题,整的一大半了,虽还只公布到第60题,
但整天 看代码,也实在 趣味不多。详情见此帖:
http://topic.csdn.net/u/20101023/20/5652ccd7-d510-4c10-9671-307a56006e6d.html

整理资源,下载地址:
[最新答案V0.3版]微软等数据结构+算法面试100题[第21-40题答案]
http://download.csdn.net/source/2832862

[第1题-60题汇总]微软等数据结构+算法面试100题
http://download.csdn.net/source/2826690

[答案V0.2版]精选微软数据结构+算法面试100题[前20题]--修正
http://download.csdn.net/source/2813890
//此份答案是针对最初的V0.1版本,进行的校正与修正。

[答案V0.1版]精选微软数据结构+算法面试100题[前25题]
http://download.csdn.net/source/2796735

[第二部分]精选微软等公司结构+算法面试100题[前41-60题]:
http://download.csdn.net/source/2811703

[第一部分]精选微软等公司数据结构+算法经典面试100题[1-40题]
http://download.csdn.net/source/2778852

更多资源,下载地址:
http://v_july_v.download.csdn.net/
//目前,第61题-100题尚在整理中。


近期闲着无事,正好静下心来,读点书。
一翻windows核心编程,挺不错的,喜爱有加。
又曾于前几天,看到论坛上,有人提问,寻求看windows核心编程的方法。
一本好书,不用问怎么看,看就对了。尤其是一本世界级经典著作。

楼主声明:
1.本读书摘记以:windows via c/c++(windows核心编程第五版 中文版),为准。
2.欢迎各位,与我一起就此书交流,无论触及内容是深是浅,来者,一律不拒。
尤其是欢迎大方之家,对此书摘记 提出自己的 独到见解,或经验,于众网友共享。
特别精彩的回复,我愿慷慨解囊,送20分一人。
每发现此读书摘记中,一处内容错误,奖5分/人。
3.希望,在微软面试题热浪之后,又能在论坛上刮起一阵热度 windows核心编程的热潮。:)...
4.作者本人July对以下全部所有任何内容享有版权,转载请注明出处。
先向你的厚道致敬。
以下所有文字,都是一字一字敲出来的,请尊重他人劳动成果。
谢谢。:)。


不要问我,这样做,是为了什么。我告诉你,纯粹是为了练习打字。:)。
如果,你内心浮躁,我想,你一定静不下心来,看我打的这一个一个子。
这样,你就可以无视此帖,悄然飘过~。


windows核心编程完整中文版,下载地址:
[极品收藏]Windows 核心编程完整中文pdf版(上)
http://download.csdn.net/source/2782631

[极品收藏]Windows 核心编程完整中文pdf版(中)
http://download.csdn.net/source/2782639

[极品收藏]Windows 核心编程完整中文pdf版(下)
http://download.csdn.net/source/2782654

更多资源,下载地址:
http://v_july_v.download.csdn.net/
//日后,我会上传windows核心编程英文版+最新的第5版中文版。
...全文
829 52 打赏 收藏 转发到动态 举报
写回复
用AI写文章
52 条回复
切换为时间正序
请发表友善的回复…
发表回复
taoloveliang 2011-07-12
  • 打赏
  • 举报
回复
刚借了这本书,看到一大推没接触的什么什么函数,头都大了。。。而且,这个贴也太长了,实在没耐心看完
cpf4012114 2011-06-09
  • 打赏
  • 举报
回复
楼主有专门讨论的版块吗
zgsdzhaolanxiang1 2011-06-09
  • 打赏
  • 举报
回复
这本书读了三遍,是本好书。
hw_henry2008 2010-12-05
  • 打赏
  • 举报
回复
如果有个这样的人跟我泡图书馆,该多好···
等我看完现在的书再来啃这本
v_JULY_v 2010-11-18
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 yutaooo 的回复:]
有点兴趣。书已买好。准备明年读。如果明年LZ还活跃的话,是要经常请教了。

LZ到时候可别嫌麻烦噢。嘿嘿嘿。
[/Quote]

把这位哥们,漏了,下次,一定补上。
如果还来回复我的帖子的话。:)。
v_JULY_v 2010-11-18
  • 打赏
  • 举报
回复
[Quote=引用楼主 v_july_v 的回复:]
一起来读windows核心编程
-----windows核心编程读书摘记



---------------------
混csdn前期回顾:
精选微软等数据结构+算法面试100题,整的一大半了,虽还只公布到第60题,
但整天 看代码,也实在 趣味不多。详情见此帖:
http://topic.csdn.net/u/20101023/20/5652ccd7-d510-4c10……
[/Quote]

要结帖子,送分了。
na2650945 2010-11-17
  • 打赏
  • 举报
回复
那书买了好久。
一直没怎么看。
失落的凡凡 2010-11-17
  • 打赏
  • 举报
回复
[Quote=引用 42 楼 v_july_v 的回复:]

引用 41 楼 milkylove 的回复:
那您的帖子到底是读书笔记呢还是经典书籍推荐呢?


俩者都是。

大哥,不要跟我在这里争吵了,
有时间的话,去多回答回答 别人的提出的 问题吧。
那才是你的 初衷+本意啊。

我与你无怨无仇。
没必要在这里因为争吵而 浪费时间,真的。
[/Quote]
你说的很有道理。
v_JULY_v 2010-11-17
  • 打赏
  • 举报
回复
[Quote=引用 41 楼 milkylove 的回复:]
那您的帖子到底是读书笔记呢还是经典书籍推荐呢?
[/Quote]

俩者都是。

大哥,不要跟我在这里争吵了,
有时间的话,去多回答回答 别人的提出的 问题吧。
那才是你的 初衷+本意啊。

我与你无怨无仇。
没必要在这里因为争吵而 浪费时间,真的。
失落的凡凡 2010-11-17
  • 打赏
  • 举报
回复
那您的帖子到底是读书笔记呢还是经典书籍推荐呢?
v_JULY_v 2010-11-17
  • 打赏
  • 举报
回复
[Quote=引用 38 楼 milkylove 的回复:]
看不惯就无视, 也许是楼主的风格,也是很多人的风格,但不是我的风格。这么大一个帖子,每天占据C/C++大版的第一页,提高了人们得到有效信息的成本, 降低了新手提的问题被回答的机会,难道你不觉得这是不道德么?
还有,你的帖子发在论坛上,论坛是给大家交流用的,哪怕论坛是你开的, 你也没有要求别人走开的权利。
[/Quote]

欢迎,和我继续争吵下去。
虽然不是针对本书内容本身。无所谓了。反正,闲着。


[Quote=引用 39 楼 milkylove 的回复:]
引用 37 楼 v_july_v 的回复:

本论坛,CSDN - CSDN社区 - C/C++ - C++ 语言
[置顶] “华章公司”携手“CSDN C++论坛”举办“免费读经典”活动

敢说,csdn 论坛,都存在道德问题?


《CSAPP》是一本经典的书,推荐一本经典的书, 我不觉得有什么不道德。
[/Quote]

windows核心编程,是一本经典的书,推荐一本经典的书, 我不觉得有什么不道德。
失落的凡凡 2010-11-17
  • 打赏
  • 举报
回复
[Quote=引用 37 楼 v_july_v 的回复:]

本论坛,CSDN - CSDN社区 - C/C++ - C++ 语言
[置顶] “华章公司”携手“CSDN C++论坛”举办“免费读经典”活动

敢说,csdn 论坛,都存在道德问题?
[/Quote]

《CSAPP》是一本经典的书,推荐一本经典的书, 我不觉得有什么不道德。
失落的凡凡 2010-11-17
  • 打赏
  • 举报
回复
看不惯就无视, 也许是楼主的风格,也是很多人的风格,但不是我的风格。这么大一个帖子,每天占据C/C++大版的第一页,提高了人们得到有效信息的成本, 降低了新手提的问题被回答的机会,难道你不觉得这是不道德么?
还有,你的帖子发在论坛上,论坛是给大家交流用的,哪怕论坛是你开的, 你也没有要求别人走开的权利。
v_JULY_v 2010-11-17
  • 打赏
  • 举报
回复
本论坛,CSDN - CSDN社区 - C/C++ - C++ 语言
[置顶] “华章公司”携手“CSDN C++论坛”举办“免费读经典”活动

敢说,csdn 论坛,都存在道德问题?
v_JULY_v 2010-11-17
  • 打赏
  • 举报
回复
[Quote=引用 34 楼 milkylove 的回复:]
好吧,如果你不觉得这是一个道德问题,那我就不多说什么了。
[/Quote]

晕。还跟我讲起道德来了。
算了,无视此帖把。你走吧~
cnpsl 2010-11-17
  • 打赏
  • 举报
回复
感谢楼主分享,正在读核心编程。。。
失落的凡凡 2010-11-17
  • 打赏
  • 举报
回复
好吧,如果你不觉得这是一个道德问题,那我就不多说什么了。
pengzhixi 2010-11-17
  • 打赏
  • 举报
回复
我觉得应该是将一些疑问贴出来更好。
v_JULY_v 2010-11-17
  • 打赏
  • 举报
回复
[Quote=引用 31 楼 v_july_v 的回复:]
引用 23 楼 v_july_v 的回复:
引用 22 楼 v_july_v 的回复:
第Ⅱ部分 完成编程任务
本部分内容包括
第4章进程
第5章作业
第6章线程基础
第7章线程进度安排、优先级和线程亲和性
第8章用户模式下的线程同步
第9章线程与内核对象的同步
第10章同步和异步设备I/O
第11章 Windows线程池
第12章纤程

//2010.11.16
第……
[/Quote]


4.1.3 fdwCreate 参数
BOOL CreateProcess(
PCTSTR pszApplicationName, //1.指定新进程要使用的可执行文件的名称
PTSTR pszCommandLine, //2.指定要传给新进程的命令行字符串
PSECURITY_ATTRIBUTES psaProcess, //3.为进程对象指定安全属性 ..可以NULL
PSECURITY_ATTRIBUTES psaThread, //4.为线程内核对象指定安全属性 ..可以NULL
BOOL bInheritHandles, //5.TRUE->可继承.....FALSE->不可继承
DWORD fdwCreate, //6.标识影响新进程创建方式的标志(flag)
PVOID pvEnvironment,
PCTSTR pszCurDir,
PSTARTUPINFO psiStartInfo,
PPROCESS_INFORMATION ppiProcInfo);




4.2.3 pvEnvironment 参数
BOOL CreateProcess(
PCTSTR pszApplicationName, //1.指定新进程要使用的可执行文件的名称
PTSTR pszCommandLine, //2.指定要传给新进程的命令行字符串
PSECURITY_ATTRIBUTES psaProcess, //3.为进程对象指定安全属性 ..可以NULL
PSECURITY_ATTRIBUTES psaThread, //4.为线程内核对象指定安全属性 ..可以NULL
BOOL bInheritHandles, //5.TRUE->可继承.....FALSE->不可继承
DWORD fdwCreate, //6.标识影响新进程创建方式的标志(flag)
PVOID pvEnvironment, //7.pvEnvironment参数指向一个内存块,
//其中包含了新进程要使用的环境字符串。
PCTSTR pszCurDir,
PSTARTUPINFO psiStartInfo,
PPROCESS_INFORMATION ppiProcInfo);



pvEnvironment参数指向一个内存块,
其中包含了新进程要使用的环境字符串。大多数时候,为这个参数传入的值都是NULL,
这将导致子进程继承其父进程使用的一组环境字符串。

GetEnvironmentStrings函数:
PVOID GetEnvironmentStrings();

此函数获取主调进程正在使用的环境字符串数据块的地址。可以将这个函数返回的地址用作
CreateProcess函数的pvEnvironment参数的值。

如果你为pvEnvironment参数传入NULL值,CreateProcess函数就会这样做。
不再需要这个内存块的时候,应该调用FreeEnvironmentStrings函数来释放它:
BOOL FreeEnvironmentStrings(PTSTR pszEnvironmentBlock);



4.2.4 pszCurDir 参数
BOOL CreateProcess(
PCTSTR pszApplicationName, //1.指定新进程要使用的可执行文件的名称
PTSTR pszCommandLine, //2.指定要传给新进程的命令行字符串
PSECURITY_ATTRIBUTES psaProcess, //3.为进程对象指定安全属性 ..可以NULL
PSECURITY_ATTRIBUTES psaThread, //4.为线程内核对象指定安全属性 ..可以NULL
BOOL bInheritHandles, //5.TRUE->可继承.....FALSE->不可继承
DWORD fdwCreate, //6.标识影响新进程创建方式的标志(flag)
PVOID pvEnvironment, //7.pvEnvironment参数指向一个内存块,
//其中包含了新进程要使用的环境字符串。
//为NULL,导致子进程继承其父进程使用的一组环境字符串。
PCTSTR pszCurDir, //8.允许父进程设置子进程的当前驱动器和目录
//为NULL,则新进程的工作目录与生成新进程的应用程序一样
PSTARTUPINFO psiStartInfo,
PPROCESS_INFORMATION ppiProcInfo);


如果这个参数pszCurDir不为NULL,则pszCurDir必须指向一个用0来终止的字符串,
其中包含了你希望的工作驱动器和目录。注意,必须在路径中指定一个盘符(驱动器号)。


4.2.5 psiStartInfo 参数
BOOL CreateProcess(
PCTSTR pszApplicationName, //1.指定新进程要使用的可执行文件的名称
PTSTR pszCommandLine, //2.指定要传给新进程的命令行字符串
PSECURITY_ATTRIBUTES psaProcess, //3.为进程对象指定安全属性 ..可以NULL
PSECURITY_ATTRIBUTES psaThread, //4.为线程内核对象指定安全属性 ..可以NULL
BOOL bInheritHandles, //5.TRUE->可继承.....FALSE->不可继承
DWORD fdwCreate, //6.标识影响新进程创建方式的标志(flag)
PVOID pvEnvironment, //7.pvEnvironment参数指向一个内存块,
//其中包含了新进程要使用的环境字符串。
//为NULL,导致子进程继承其父进程使用的一组环境字符串。
PCTSTR pszCurDir, //8.允许父进程设置子进程的当前驱动器和目录
//为NULL,则新进程的工作目录与生成新进程的应用程序一样
PSTARTUPINFO psiStartInfo, //9.指向一个STARTUPINFO结构或STARTUPINFOEX结构
PPROCESS_INFORMATION ppiProcInfo);


psiStartInfo指向一个STARTUPINFO结构或STARTUPINFOEX结构:
typedef struct _STARTUPINFO
{
DWORD cb; //1.包含STARTUPINFO结构中的字节数。充当版本控制
PSTR lpReserved; //2.保留。必须初始化为NULL。
PSTR lpDesktop; //3.标识要在上面启动应用程序的桌面的名称
PSTR lpTitle; //4.指定控制台窗口的窗口标题。
//如果lpTitle被设置为NULL,就将执行体文件的名称作为窗口标题。
DWORD dwX; //5.
DWORD dwY; //6.
DWORD dwXSize; //7.
DWORD dwYSize; //8.
DWORD dwXCountChars; //9.
DWORD dwYCountChars; //10.
DWORD dwFillAttribute; //11.指定子进程的控制台窗口所用的文本和背景色。
DWORD dwFlags; //12.
WORD wShowWindow; //13.指定应用程序的主窗口如何显示。
WORD cbReserved2; //14.保留。必须被初始化为0
PBYTE lpReserved2; //15.保留。必须被初始化为NULL。
HANDLE hStdInput; //16.
HANDLE hStdOutput;
HANDLE hStdError;
} STARTUPINFO, *LPSTARTUPINFO;


Windows在创建新进程的时候使用这个结构的成员。
大多数应用程序都希望生成的应用程序只是使用默认值。
最起码要将此结构中的所有成员初始化为0,
并将cb成员设为此结构的大小,如下所示:

STARTUPINFO si = { sizeof(si) };
CreateProcess(...,&si,...);


如果没有把结构的内容清零,则成员将包含主调线程的堆栈上的垃圾数据。
把这种垃圾传给CreateProcess,会造成新进程有时能创建,有时则不能,具体取决于垃圾的内容。

因此,必须将这个结构中的未使用的成员清零,确保CreateProcess始终都能正常地工作。




4.2.6 ppiProcInfo 参数
BOOL CreateProcess(
PCTSTR pszApplicationName, //1.指定新进程要使用的可执行文件的名称
PTSTR pszCommandLine, //2.指定要传给新进程的命令行字符串
PSECURITY_ATTRIBUTES psaProcess, //3.为进程对象指定安全属性 ..可以NULL
PSECURITY_ATTRIBUTES psaThread, //4.为线程内核对象指定安全属性 ..可以NULL
BOOL bInheritHandles, //5.TRUE->可继承.....FALSE->不可继承
DWORD fdwCreate, //6.标识影响新进程创建方式的标志(flag)
PVOID pvEnvironment, //7.pvEnvironment参数指向一个内存块,
//其中包含了新进程要使用的环境字符串。
//为NULL,导致子进程继承其父进程使用的一组环境字符串。
PCTSTR pszCurDir, //8.允许父进程设置子进程的当前驱动器和目录
//为NULL,则新进程的工作目录与生成新进程的应用程序一样
PSTARTUPINFO psiStartInfo, //9.指向一个STARTUPINFO结构或STARTUPINFOEX结构
PPROCESS_INFORMATION ppiProcInfo);//10.指向你必须分配的一个PROCESS_INFORMATION结构


ppiProcInfo参数指向你必须分配的一个PROCESS_INFORMATION结构,CreateProcess函数
在返回之前,会初始化这个结构的成员。该结构如下所示:
typedef struct _PROCESS_INFORMATION
{
HANDLE hProcess;
HANDLE hThread;
DWORD dwProcessId;
DWORD dwThreadId;
} PROCESS_INFORMATION;


如前所述,创建一个新的进程,会导致系统创建一个进程内核对象和一个线程内核对象。
在创建时,系统会为每个对象指定一个初始的使用计数1。
然后,就在CreateProcess返回之前,它会使用完全访问权限来打开进程对象和线程对象,
并将各自的与进程相关的(相对于进程的)句柄放入PROCESS_INFORMATION结构的
hProcess和hThread成员中。
当CreateProcess在内部打开这些对象时,每个对象的使用计数就变为2。


这意味着系统要想释放进程对象,进程必须终止(使用计数递减1),
而且父进程必须调用CloseHandle(使用计数再次递减1,变成0)。
类似地,要想释放线程对象,线程必须终止,而且父进程必须关闭到线程对象的句柄
//要想进一步了解如何释放线程对象,请参见4.3节“子进程”。

注意
应用程序运行期间,必须关闭到子进程及其主线程的句柄,以避免资源泄漏。
当然,系统会在你的进程终止后自动清理这种泄漏。
但是,如果是一个编写精妙的软件,
肯定会在进程不再需要访问一个子进程及其主线程的时候,
则必须显式地调用CloseHandle来关闭这些句柄。

许多开发人员都有这样的一个误解:
关闭到一个进程或线程的句柄,会强迫系统杀死此进程或线程。
但这是大谬不然的。
关闭句柄只是告诉系统你对进程或线程的统计数据不再感兴趣了。
进程或线程会继续执行,直至自行终止。


创建一个进程内核对象或线程内核对象时,系统会为此对象分配一个独一无二的标识符,
系统中没有别的进程内核对象 或别的线程内核对象会有相同的ID编号。


可以使用GetCurrentProcessId来得到当前进程的ID,
使用GetCurrentThreadId来获得当前正在运行的线程的ID。
另外,还可以使用GetProcessId来获得与指定句柄对应的一个进程的ID,
使用GetThreadId来获得与指定句柄对应的一个线程的ID。


个别情况下,你的应用程序可能想确定它的父进程。
但是,你首先应该知道的是,只有在一个子进程生成的那一瞬间,才存在一个父-子关系。
到子进程开始执行代码之前的那一刻,Windows就已经不认为存在任何父-子关系了。
ToolHelp函数允许进程通过PROCESSENTRY32结构查询其父进程。
在此结构内部有一个th32ParentProcessID成员;根据文档,它能返回父进程的ID。


如果你的应用程序需要与它的“创建者”通信,最好不要使用ID。
应该定义一个更持久的通信机制,比如内核对象、窗口句柄等等。


要保证一个进程或线程ID不被重用,惟一的办法就是保证进程或线程对象不被销毁。
为此,在创建了一个新进程或线程之后,不关闭到这些对象的句柄即可。
等到应用程序不再使用ID的时候,再调用CloseHandle来释放内核对象。
但是,一旦调用了CloseHandle,再使用或依赖进程ID就不安全了。这一点务必牢记。
对于子进程,不用做任何事情,就能保证父进程或线程ID的有效性,
除非父进程为它自己的进程或线程对象复制了句柄,并允许子进程继承这些句柄
//3.3.5节。




4.2 终止进程
待续。
v_JULY_v 2010-11-17
  • 打赏
  • 举报
回复
[Quote=引用 23 楼 v_july_v 的回复:]
引用 22 楼 v_july_v 的回复:
第Ⅱ部分 完成编程任务
本部分内容包括
第4章进程
第5章作业
第6章线程基础
第7章线程进度安排、优先级和线程亲和性
第8章用户模式下的线程同步
第9章线程与内核对象的同步
第10章同步和异步设备I/O
第11章 Windows线程池
第12章纤程

//2010.11.16
第4章 进程
本章内容包括:
4.1 编写第……
[/Quote]

4.2 CreateProcess 函数
我们用CreatePrecess来创建一个进程。
BOOL CreateProcess(
PCTSTR pszApplicationName,
PTSTR pszCommandLine,
PSECURITY_ATTRIBUTES psaProcess,
PSECURITY_ATTRIBUTES psaThread,
BOOL bInheritHandles,
DWORD fdwCreate,
PVOID pvEnvironment,
PCTSTR pszCurDir,
PSTARTUPINFO psiStartInfo,
PPROCESS_INFORMATION ppiProcInfo);


一个线程调用CreateProcess时,系统将创建一个进程内核对象,其初始使用计数为1.
进程内核对象不是进程本身,而是操作系统用来管理这个进程的一个小型数据结构--
可以把进程内核对象想象成由进程统计信息构成的一个小型数据结构。

然后,系统为新进程创建一个虚拟地址空间,并将可执行文件(和所有不要的DLL)的代码及数据
加载到进程的地址空间。

然后,系统为新进程的主线程创建一个线程内核对象(其使用计数为1)。
和进程内核对象一样,线程内核对象也是一个小型数据结构,操作系统用它来管理这个线程。

这个主线程一开始就会执行C/C++运行时的启动例程,它是有链接器设为应用程序入口的,
最终会调用WinMain,wWinMain,main,或wmain函数。
如果系统成功的创建了新进程和主线程,CreateProcess将返回TRUE。

CreateProcess在进程完全初始化好之前就返回TRUE。这意味着操作系统加载程序尚未尝试
定位所有必要的DLL,如果一个DLL找不到或者不能正确初始化,进程就会终止。
CreatProcess返回TRUE,所以父进程不会注意到任何初始化问题。

接下来,深入讨论CreateProcess的各路参数:
BOOL CreateProcess(
PCTSTR pszApplicationName, //1.指定新进程要使用的可执行文件的名称
PTSTR pszCommandLine, //2.指定要传给新进程的命令行字符串
PSECURITY_ATTRIBUTES psaProcess,
PSECURITY_ATTRIBUTES psaThread,
BOOL bInheritHandles,
DWORD fdwCreate,
PVOID pvEnvironment,
PCTSTR pszCurDir,
PSTARTUPINFO psiStartInfo,
PPROCESS_INFORMATION ppiProcInfo);


4.2.1 pszApplicationName 和pszCommandLine 参数
第2个参数.此参数pszCommandLine的类型为PTSTR。
这意味着CreateProcess期望我们传入的是一个非“常量字符串”的地址。
在内部,CreateProcess实际上会修改我们传给它的命令行字符串。
但在CreateProcess返回之前,它会将这个字符串还原为原来的形式。

如果命令行字符串包含在文件映射的只读部分,就会引起访问违规。
以下代码就会导致访问违规,因为Microsoft的C/C++编译器 把"NOTEPAD" 字符串放在只读内存中。
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
CreateProcess(NULL,
TEXT("NOTEPAD"),
NULL,NULL,
FALSE,0,NULL,NULL,
&si,π);


CreateProcess试图修改字符串时,会引起一个访问冲突
(Microsoft C/C++编译器的早期版本把字符串放在可读/写内存中。
所以对CreateProcess函数的调用不会引起访问冲突)。

解决这个问题的最佳方式是:
在调用CreateProcess之前,把常量字符串复制到一个临时缓冲区,
如下所示:

STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
TCHAR szCommandLine[] = TEXT("NOTEPAD"); //把常量字符串复制到一个临时缓冲区
CreateProcess(NULL,szCommandLine,NULL,NULL,
FALSE,0,NULL,NULL,&si,π);


目前,Microsoft最应该做的一件事情就是修复CreateProcess,
使它自己就能创建字符串的一个临时拷贝,从而使我们得到解放。
顺带提一下,如果在Windows Vista上调用CreateProcess函数的ANSI版本,就不会发生访问冲突,
因为会创建命令行字符串的一个临时拷贝。
BOOL CreateProcess(
PCTSTR pszApplicationName, //1.指定新进程要使用的可执行文件的名称
PTSTR pszCommandLine, //2.指定要传给新进程的命令行字符串
PSECURITY_ATTRIBUTES psaProcess,
PSECURITY_ATTRIBUTES psaThread,
BOOL bInheritHandles,
DWORD fdwCreate,
PVOID pvEnvironment,
PCTSTR pszCurDir,
PSTARTUPINFO psiStartInfo,
PPROCESS_INFORMATION ppiProcInfo);



可以使用pszCommandLine参数来指定一个完整的命令行,供CreateProcess用于创建新进程。
当CreateProcess解析pszCommandLine字符串时,它会检查字符串中的第一个标记(token),
并假定此标记是你想运行的执行体文件的名称。
如果执行体文件的名称没有扩展名,就会默认是.exe扩展名。
CreateProcess还会按照以下顺序搜索执行体。

1. 主调进程.EXE文件所在的目录
2. 主调进程的当前目录
3. Windows系统目录,即GetSystemDirectory返回的System32子文件夹
4. Windows目录
5. PATH环境变量中列出的目录


4.2.2 psaProcess,psaThread 和bInheritHandles 参数
BOOL CreateProcess(
PCTSTR pszApplicationName, //1.指定新进程要使用的可执行文件的名称
PTSTR pszCommandLine, //2.指定要传给新进程的命令行字符串
PSECURITY_ATTRIBUTES psaProcess, //3.为进程对象指定安全属性 ..可以NULL
PSECURITY_ATTRIBUTES psaThread, //4.为线程内核对象指定安全属性 ..可以NULL
BOOL bInheritHandles, //5.TRUE->可继承.....FALSE->不可继承
DWORD fdwCreate,
PVOID pvEnvironment,
PCTSTR pszCurDir,
PSTARTUPINFO psiStartInfo,
PPROCESS_INFORMATION ppiProcInfo);


为了创建一个新的进程,系统必须创建一个进程内核对象和一个线程内核对象(用于进程的主
线程)。
由于这些都是内核对象,所以父进程有机会将安全属性关联到这两个对象上。
可以分别使用psaProcess和psaThread参数为进程对象和线程对象指定你希望的安全性。
可以为这两个参数传递NULL;
在这种情况下,系统将为这两个内核对象指定默认的安全描述符。

也可以分配并初始化两个SECURITY_ATTRIBUTES结构,以便创建你自己的安全权限,
并将它们分配给进程对象和线程对象。

为psaProcess和psaThread参数使用SECURITY_ATTRIBUTES结构的另一个原因是:
这两个对象句柄可由父进程将来生成的任何子进程继承(第3章讨论了内核对象句柄的继承机制)。
//第3章:为了创建一个可继承的句柄,
//父进程必须分配并初始化一个SECURITY_ATTRIBUTES结构,
//并将这个结构的地址传给具体的Create函数。

/************************************************************
Module name: Inherit.c
Notices:Copyright(c)2000 Jeffrey Richter

// 内核对象句柄继承性的一个示例
************************************************************/
#include <Windows.h>

int WINAPI WinMain (HINSTANCE hinstExe,HINSTANCE,
PSTR pszCmdLine,int nCmdShow)
{

//Prepare a STARTUPINFO structure
//for spawning processes.
STARTUPINFO si = { sizeof(si) };
SECURITY_ATTRIBUTES saProcess,saThread;
PROCESS_INFORMATION piProcessB,piProcessC;
TCHAR szPath[MAX_PATH];

//Prepare to spawn Process B from Process A.
//The handle identifying the new process
//object should be inheritable.

saProcess.nLength = sizeof(saProcess);
saProcess.lpSecurityDescriptor = NULL;
saProcess.bInheritHandle = TRUE;
//假设现在由Process A来创建Process B,它调用CreateProcess,
//并为,psaProcess参数传入一个SECURITY_ATTRIBUTES结构的地址(在这个结构中,

//bInheritHandle成员被设为TRUE)。

//这样,Process B的进程对象句柄是可继承的。


//The handle identifying the new thread
//object should NOT be inheritable.

saThread.nLength = sizeof(saThread);
saThread.lpSecurityDescriptor = NULL;
saThread.bInheritHandle = FALSE;
//在同一个调用中,psaThread 参数指向另一个SECURITY_ATTRIBUTES结构,
//该结构的bInheritHandle成员被设为FALSE。

//这样,Process B的主线程对象句柄是不可继承的。

//Spawn Process B.
lstrcpy(szPath,TEXT("ProcessB"));

CreateProcess(NULL,szPath,
&saProcess,&saThread,
FALSE,0,NULL,NULL,&si,
&piProcessB);
//系统创建Process B时,会同时分配一个进程内核对象和一个线程内核对象,
//并在ppiProcInfo(最后一个参数)指向的一个结构中,将句柄返回给Process A。
//现在,利用返回的这些句柄,Process A就可以操纵新建的进程对象和线程对象。

//The pi structure contains two handles
//relative to Process A:
//hProcess,which identifies Process B's process
//object and is inheritable; and hThread,
//which identifies Process B's primary thread
//object and is NOT inheritable.

//Prepare to spawn Process C from Process A.
//Since NULL is passed for the psaProcess and
//psaThread parameters,the handles to Process C's
//process and primary thread objects default
//to "noninheritable."

//If Process A were to spawn another process,
//this new process would NOT inherit handles
//to Process C's process and thread objects.

//Because TRUE is passed for the bInheritHandles
//parameter,Process C will inherit the handle that
//identifies Process B's process object but will
//not inherit a handle to Process B's primary
//thread object.

lstrcpy(szPath,TEXT("ProcessC"));

CreateProcess(NULL,szPath,NULL,NULL,
TRUE,0,NULL,NULL,&si,&piProcessC);
//现在,假设Process A再次调用CreateProcess来创建Process C。
//Process A可以决定是否允许Process C操纵Process A能访问的一些内核对象。

//bInheritHandles参数便是针对这个用途而提供的。
//如果bInheritHandles设为TRUE,Process C将继承Process A中的所有可继承的句柄。


//////////////////////////////////////////
//在本例中,Process B的进程对象句柄是可继承的。
//Process B的主线程对象的句柄则是不可继承的,
//不管传给CreateProcess 的bInheritHandles 参数值是多少。

//另外, 如果 Process A 调用CreateProcess,并为bInheritHandles参数传入FALSE,
//则Process C不会继承Process A当前所用的任何一个句柄。

return(0);
}
加载更多回复(29)

64,637

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧