Windows核心编程笔记(2)

6 进程实例句柄

6.1 每一个EXE或者DLL被加载到内存中后,都会被赋予一个独一无二的句柄(HINSTANCE),该句柄在WinMain函数调用时传入。获取应用程序相关信息(资源、路径)时,有的需要传入HINSTANC有的需要传入HMODULE,实际上HINSTANC与HMODULE完全是一回事,这是16位Windows系统上不同数据类型造成的。

WinMain函数的第一个参数:实例句柄是如何传递进来的呢?查看crtexe.c源码,我们会看到如下代码

	#ifdef WPRFLAG
            mainret = wWinMain(
#else  /* WPRFLAG */
            mainret = WinMain(
#endif  /* WPRFLAG */
                       (HINSTANCE)&__ImageBase,
                       NULL,
                       lpszCommandLine,
                       StartupInfo.dwFlags & STARTF_USESHOWWINDOW
                        ? StartupInfo.wShowWindow
                        : SW_SHOWDEFAULT
                      );
#else  /* _WINMAIN_ */

Crt在这里调用我们的WinMain函数,传入的实例句柄是:__ImageBase的地址,转到其定义位置

extern "C" IMAGE_DOS_HEADER __ImageBase;

实际上实例句柄就是这个PE文件加载到内存后的DOS头的地址,CRT源码都是可见的,在VS安装路径下VC\crt\src\大家可以看下。

6.2 GetModuleHandle(PCTSTR pszModule)的两大注意点:

1、该API只检查主调用进程的地址空间,如果pszModule没有被主进程加载,即使其他进程加载了pszModule也会调用失败,返回NULL;

2、在进程的DLL中调用该函数,返回的HMODULE是该EXE的内存基地址而非该DLL的内存基地址。

7 终止进程

四种方式:

1、主进程入口函数返回(推荐方式、最佳方式);

2、进程中一个线程调用ExitProcess;

3、其他进程调用TerminateProcess;

4、进程中所有线程都自然死亡(几乎不可能发生)。

7.1 主进程入口函数返回,进程终止过程

但主进程WinMain函数返回后,会回到C运行库启动代码,然后正确清理进程使用的所有C运行时资源。释放完这些资源后,C运行时启动代码将显示调用ExitProcess,并将进程的WinMain函数返回值传给它。于是,所有进程中运行的其他进程都会终止。

任何时候都不应该显示调用ExitProcess,否则很有可能导致自定义的C++对象得不到正确的释放。

7.2 TerminateProcess终止进程

1、只有在无法通过其他方法终止进程时,才应使用该函数;

2、被终止的进程无法知道自己将要被终止,终止后虽然进程没有机会自己执行清理工作,但是系统会在进程终止后进行彻底得清理;

3、TerminateProcess函数是异步的,函数返回后并不表示进程已经终止,可以通过WaitForSingleObject来等待判断。

7.3 进程终止运行时,执行的步骤

1、终止进程中遗留的任何线程;

2、释放进程分配的所有用户对象和GDI对象,关闭所有的内核对象,若内核对象引用计数为0则销毁;

3、进程的退出码从STILL_ACTIVE变为传给ExitProcess或者TerminateProcess的参数;

4、进程的内核对象状态变为已触发状态;

5、进程的内核对象引用计数减一,引用计数为0,则销毁内核对象。

8 进程提权

8.1 Windows只允许在进程边界上进行权限提升,一旦进程启动后,再要求更多的权限已经太迟了。一个未提升权限的进程可以生成另一个提升了权限的进程,后者将包含一个COM服务器,这个新进程将保持活跃状态。这样,未提升权限的进程就可以向已提升权限的进程发送IPC(Inter-Process Communication)调用,而不必为了提升权限再开一个新实例然后终止自己。

8.2 手动提权方式

ShellExecuteEx函数,SHELLEXECUTEINFO 结构中lpVerb指定为"runas",同时在lpFile指定一个拥有权限的可执行文件路径。如果用户拒绝提升权限,返回FALSE,GetLastError()返回ERROR_CANCELLED。进程使用提升后的权限运行时,其所创建的所有子进程都会具有相同权限,无需再用ShellExecuteEx提权。

未完待续。

时间: 2024-10-11 08:47:31

Windows核心编程笔记(2)的相关文章

Windows核心编程笔记(1)

最近工作比较闲了,一直没来得及看的核心编程最近开始看了,分享下笔记. 1.内核句柄用完不释放一定会造成内存泄漏吗? 不一定,内核句柄在进程退出时会被系统释放掉(遍历内核句柄表,只要每个句柄指向的内核对象的引用计数为0,内核就会销毁该对象,适用于所有的内核对象.资源(GDI对象在内).内存块): 2.内核对象如何关闭? 调用CloseHandle(),内核会查找该进程的句柄表,如果没找到该句柄,返回FALSE(Debug下抛出异常);如果找到,则使该句柄指向的内核对象引用计数减一,若引用计数为0,

Windows核心编程笔记(7)----内核模式下的线程同步

1.内核对象同步与用户模式下同步对比 使用内核对象的唯一缺点就是性能,调用内核对象函数时,调用线程必须从用户模式切换到内核模式,这种切换是相当 耗时的. 内核对象(进程.线程.作业)要么处于触发态,要么处于未触发状态.进程内核对象在创建时总是处于未触发状态, 当进程终止时,操作系统会自动使进程内核对象变成触发状态.当进程内核对象处于触发状态后,将永远保持这种状态, 再也不能变回未触发状态. 2.等待内核对象 WaitForSingleObject等待单个内核对象,WaitForMultipleO

Windows核心编程笔记(6)----用户模式下的线程同步

1.原子锁 使用InterlockedExchangeAdd函数来实现原子增长,InterlockedExchange\InterlockedExchangePointer用来交换两个变 量的值,InterlockedCompareExchange对比数值,相等则交换(对应的InterlockedCompareExchangePointer).对应的 还有64位函数. InterlockedIncrement\InterlockedDecrement是比较老的函数,只能增加或递减1,Interl

Windows核心编程笔记(5)----线程调度,优先级

1.操作系统线程调度过程 每个线程都有一个上下文CONTEXT结构体,保存在线程的内核对象中,这个上下文中保存了线程上一次执行时CPU寄存器 的状态.每隔固定时间,Windows会查看所有当前存在的线程内核对象,其中只有一些是可调度的.Windows在可调度的 线程中选择一个,并将上次保存到线程上下文中的数据载入CPU寄存器中.(上下文切换) CPU时间片到后,Windows移出这个线程,把CPU寄存器信息保存到线程上下文中,切换到另一个线程,如此循环. 2.线程的挂起和恢复 调用CreateP

Windows核心编程笔记(3)--作业

/*1.如果进程已经与一个作业相关联,就无法将当前进程及其任何子进程从作业中移除,这个安全特性可以保证 /* 进程无法摆脱对它施加的限制. /*2.在调试程序时,调试器是从资源管理器启动的,程序会从调试器继承带"PCA"前缀的作业.因此,调试程序 /* 时总是显示进程已经加入了作业.使用命令行来运行程序时就不会有这个问题了. /*3.关闭一个作业对象,并不会终止作业内所有的进程.作业对象实际上只是加了一个删除标记,只有在作业中 /* 所有进程都终止后,才会自动销毁. /*4.可以向作业

Windows核心编程笔记(4)----线程

1.进程与线程 进程是惰性的,从来不执行任何东西,它只是一个线程的容器.线程必定是在某个进程的上下文中创建的, 而且其生命周期都在该进程中.因为句柄表是针对每一个进程的,因此同一个进程中的多个线程可以共享 内核对象句柄.进程运行需要占用许多的内存资源(加载DLL等),进程只需要一个内核对象和一个进程栈, 无需占用多少内存. 2.终止线程的几种方式: 2.1线程函数返回(强烈推荐) 2.2通过ExitThread函数杀死自己(自杀,不推荐) 终止线程运行,操作系统清理线程使用的系统资源,但是C/C

【转】《windows核心编程》读书笔记

这篇笔记是我在读<Windows核心编程>第5版时做的记录和总结(部分章节是第4版的书),没有摘抄原句,包含了很多我个人的思考和对实现的推断,因此不少条款和Windows实际机制可能有出入,但应该是合理的.开头几章由于我追求简洁,往往是很多单独的字句,后面的内容更为连贯. 海量细节. 第1章    错误处理 1.         GetLastError返回的是最后的错误码,即更早的错误码可能被覆盖. 2.         GetLastError可能用于描述成功的原因(CreatEvent)

《Windows核心编程》读书笔记 上

[C++]<Windows核心编程>读书笔记 这篇笔记是我在读<Windows核心编程>第5版时做的记录和总结(部分章节是第4版的书),没有摘抄原句,包含了很多我个人的思考和对实现的推断,因此不少条款和Windows实际机制可能有出入,但应该是合理的.开头几章由于我追求简洁,往往是很多单独的字句,后面的内容更为连贯. 海量细节. 第1章    错误处理 1.         GetLastError返回的是最后的错误码,即更早的错误码可能被覆盖. 2.         GetLas

C++Windows核心编程读书笔记

转自:http://www.makaidong.com/%E5%8D%9A%E5%AE%A2%E5%9B%AD%E6%96%87/71405.shtml "C++Windows核心编程读书笔记": 关键词:c++windows 核心 编程 读书笔记 这篇笔记是我在读<windows核心编程>第5版时做的记录和总结(部分章节是第4版的书),没有摘抄原句,包含了很多我个人的思考和对实现的推断,因此不少条款和windows实际机制可能有出入,但应该是合理的.开头几章由于我追求简洁