关于win7的session0隔离的总结

      

      微软做这个session隔离的原因我就不追查了,反正让人有蛋蛋的忧伤。

      在vista以前的系统,后台服务和当前用户进程都运行在同一个session中(本地系统登录时的第一个session中),只有从远端登录的时候会建立新的session。

      在vista以后的系统,系统启动后,后台服务运行在session0中,第一个登录的用户运行在session1当中,后续登录的有session1...sessionn等。session之间当然是有隔离措施的,是什么样的机制不去深究;目前需要突破的是,在不同的session程序之间不能按旧的方式进行通信,具体表现在:

      1. 不同session之间不能通过窗口互发消息;

      2. 一个session中不能直接使用另一个session的显示资源,比如不能直接在session0中向session1中弹出窗口;

      3. 一个session中不能直接使用另一个session的显示资源,不能读写session1中的文件;

      4. 不同session之间不能直接共享内核对象的访问权;

      这是实际中会遇到的问题,下面一一解答;

      1. 对于session中不能互发消息,这没什么好说的,不能就是不能,在vista后在不同session中不要想着发窗口消息通信就对了;

      2. 对于简单的反馈消息窗口可以使用WTSSendMessage函数来向指定的session发送一个消息要求显示窗口,而session是哪个可以用过WTSGetActiveConsoleSessionId函数来取得当前活动的sessionId;这些函数的用法在这里可以搜索到http://msdn.microsoft.com/en-us/library/aa383842(v=vs.85).aspx ;对于一些功能比较复杂的窗口,或者说服务需要在session1中重新打开一个程序,则需要获取session1的sessionId,拿到其访问令牌,然后使用访问令牌调用CreateProcessAdUser来在session1创建一个程序。在官网的例子中有这两个内容,其中创建进程有复制句柄以及创建环境块的步骤,而我在实践中没有加这两个步骤,调用CreateProcessAdUser时使用空的环境块,也没有出什么问题;目前未确认是否必须创建使用环境块。

    3. 对于在session0中不能读写session1用户的配置文件以及用户其他资源的情况,需要先用WTSGetActiveConsoleSessionId获取session1用户的sessionId,再通过WTSQueryUserToken函数使用sessionId取得这个用户的token令牌,然后用ImpersonateLoggedOnUser函数使用这个用户令牌来登录到这个用户session,再做一些需要这个用户session才能做的事情,做完以后把token关闭然后调用RevertToSelf返回原来的session0。这个过程是比较繁杂容易出错的。

    这个内容在官网里没有提到,但在实际工作中是用到的,需要熟练掌握。

    4. 不同的session中不能共享内核对象,是因为不同的session中创建命名内核对象时如果名字前不加Global的话,会默认是Local形式创建命名对象,不在session中共享,导致不能被别的session访问;如果使用了Global标记创建的话,是全局可见的;所以结论就是:如果想跨session使用命名内核对象(通常我们做进程通信都需要使用Event,FileMap这些内核对象),就应该在对象命名前加上Global。

    以上内容,第2和第4项可以在微软官网上找到对应的说明和例子:http://msdn.microsoft.com/zh-cn/library/ee663074.aspx 动手做完实验,理解能更深刻。


更详细的说明请参考微软官方的白皮书:http://msdn.microsoft.com/zh-cn/library/ee663077.aspx

了解更多关于Session 0 隔离机制,阅读Windows Vista 中的驱动和服务的Session 0 隔离机制的影响:http://www.microsoft.com/whdc/system/vista/services.mspx 这个文档里面罗列了vista中这些session隔离带来的影响以及解决方法的理论,但是没有实践代码。

你可能感兴趣的:(windows核心编程)