会话管理器进程SMSS.exe是系统启动后的第一个用户态进程,负责启动和监护windows子系统进程:CSRSS.exe和登陆管理进程:WinLogon

SMSS.exe从注册表中查询子系统exe文件的位置,并且启动它

CSRSS是windows子系统进程,自NT4以后窗口管理和GDI的主体实现被移出了CSRSS放到了win32k.sys中。

CSRSS监管着所有windows线程和进程,每个进程在创建后都要到这里登记才能运行,退出时也要报告注销。(维护了Windows子系统层面上的记录结构)

CSRSS具有桌面管理、终端登录、控制台管理、HardError报告等方面的重要作用。

为了适应恶劣环境下的错误提示的需要,Windows定义了硬错误提示机制。

硬错误本意是硬件有关错误,后来泛指严重的错误。

硬错误可以在用户态使用也可以在内核态使用。

硬错误的核心处理函数是内核中的ExpRaiseHardError函数。

在我们看这个函数的源码前,先想一想,发送硬错误消息,首先要的是找到发送硬错误的端口。

这个端口怎么找?是通过一系列的设置和标志位来判断的。  

如下是具体的程序内容

  1 NTSTATUS
  2 ExpRaiseHardError (
  3     IN NTSTATUS ErrorStatus,
  4     IN ULONG NumberOfParameters,
  5     IN ULONG UnicodeStringParameterMask,
  6     IN PULONG_PTR Parameters,
  7     IN ULONG ValidResponseOptions,
  8     OUT PULONG Response
  9     )
 10 {
 11     PTEB Teb;
 12     PETHREAD Thread;
 13     PEPROCESS Process;
 14     ULONG_PTR MessageBuffer[PORT_TOTAL_MAXIMUM_MESSAGE_LENGTH/sizeof(ULONG_PTR)];
 15     PHARDERROR_MSG m;
 16     NTSTATUS Status;
 17     HANDLE ErrorPort;
 18     KPROCESSOR_MODE PreviousMode;
 19     BOOLEAN DoingShutdown;
 20
 21     PAGED_CODE();
 22     //要发送的消息结构
 23     m = (PHARDERROR_MSG)&MessageBuffer[0];
 24     PreviousMode = KeGetPreviousMode();
 25
 26     DoingShutdown = FALSE;
 27     //如果参数要求关机,就检查是否有关机权限
 28     if (ValidResponseOptions == OptionShutdownSystem) {
 29
 30         //
 31         // Check to see if the caller has the privilege to make this call.
 32         //
 33
 34         if (!SeSinglePrivilegeCheck (SeShutdownPrivilege, PreviousMode)) {
 35             return STATUS_PRIVILEGE_NOT_HELD;
 36         }
 37
 38         ExReadyForErrors = FALSE;
 39         HardErrorState = SHUTDOWN;
 40         DoingShutdown = TRUE;
 41     }
 42
 43     Thread = PsGetCurrentThread();
 44     Process = PsGetCurrentProcess();
 45
 46     //
 47     // If the default handler is not installed, then
 48     // call the fatal hard error handler if the error
 49     // status is error
 50     //
 51     // Let GDI override this since it does not want to crash the machine
 52     // when a bad driver was loaded via MmLoadSystemImage.
 53     //
 54
 55     if ((Thread->CrossThreadFlags & PS_CROSS_THREAD_FLAGS_HARD_ERRORS_DISABLED) == 0) {
 56         //如果满足这个标志位说明用户态HardError系统还没有准备好,只能在内核态去提示这个HardError了
 57         if (NT_ERROR(ErrorStatus) && (HardErrorState == STARTING || DoingShutdown)) {
 58         //而所谓的在内核态提示HardError就是执行这个函数了,实质上就是一个KeBugCheckEx,也就是说想着内核态提示HardError只能是通过抛出蓝屏
 59             ExpSystemErrorHandler (
 60                 ErrorStatus,
 61                 NumberOfParameters,
 62                 UnicodeStringParameterMask,
 63                 Parameters,
 64                 (BOOLEAN)((PreviousMode != KernelMode) ? TRUE : FALSE));
 65         }
 66     }
 67
 68     //
 69     // If the process has an error port, then if it wants default
 70     // handling, use its port. If it disabled default handling, then
 71     // return the error to the caller. If the process does not
 72     // have a port, then use the registered default handler.
 73     //
 74
 75     ErrorPort = NULL;
 76     //这个就是通过各种标志位来判断硬错误端口是什么了。对于一个进程来说只有异常端口和调试端口两个东西,并没有单独指定硬错误端口的结构。
 77     if (Process->ExceptionPort) {
 78         //异常端口存在时
 79         if (Process->DefaultHardErrorProcessing & 1) {
 80             //这个标志位存在时,异常端口就是硬错误端口
 81             ErrorPort = Process->ExceptionPort;
 82         } else {
 83
 84             //
 85             // If error processing is disabled, check the error override
 86             // status.
 87             //
 88
 89             if (ErrorStatus & HARDERROR_OVERRIDE_ERRORMODE) {
 90                 //满足这个条件的话,也是异常端口
 91                 ErrorPort = Process->ExceptionPort;
 92             }
 93         }
 94     } else {
 95         if (Process->DefaultHardErrorProcessing & 1) {
 96             ErrorPort = ExpDefaultErrorPort;
 97         } else {
 98
 99             //
100             // If error processing is disabled, check the error override
101             // status.
102             //
103
104             if (ErrorStatus & HARDERROR_OVERRIDE_ERRORMODE) {
105                 ErrorPort = ExpDefaultErrorPort;
106             }
107         }
108     }
109     //虽然上面比较的那么热闹。。但是ExpDefaultErrorPort和ExeceptionPort的值其实是一样的
110     //都是CSRSS进程的\Windows\ApiPort端口。这是一个LPC端口对象
111
112     if ((Thread->CrossThreadFlags&PS_CROSS_THREAD_FLAGS_HARD_ERRORS_DISABLED) != 0) {
113         ErrorPort = NULL;
114     }
115     //设置了禁止硬错误就把ErrorPort清零
116     if ((ErrorPort != NULL) && (!IS_SYSTEM_THREAD(Thread))) {
117         Teb = (PTEB)PsGetCurrentThread()->Tcb.Teb;
118         try {
119             if (Teb->HardErrorMode & RTL_ERRORMODE_FAILCRITICALERRORS) {
120                 ErrorPort = NULL;
121             }
122         } except (EXCEPTION_EXECUTE_HANDLER) {
123             ;
124         }
125     }
126
127     if (ErrorPort == NULL) {
128         *Response = (ULONG)ResponseReturnToCaller;
129         return STATUS_SUCCESS;
130     }
131     //自己给自己发异常?出现问题了
132     if (Process == ExpDefaultErrorPortProcess) {
133         if (NT_ERROR(ErrorStatus)) {
134             ExpSystemErrorHandler (ErrorStatus,
135                                    NumberOfParameters,
136                                    UnicodeStringParameterMask,
137                                    Parameters,
138                                    (BOOLEAN)((PreviousMode != KernelMode) ? TRUE : FALSE));
139         }
140         *Response = (ULONG)ResponseReturnToCaller;
141         Status = STATUS_SUCCESS;
142         return Status;
143     }
144
145     m->h.u1.Length = HARDERROR_API_MSG_LENGTH;
146     m->h.u2.ZeroInit = LPC_ERROR_EVENT;
147     m->Status = ErrorStatus & ~HARDERROR_OVERRIDE_ERRORMODE;
148     m->ValidResponseOptions = ValidResponseOptions;
149     m->UnicodeStringParameterMask = UnicodeStringParameterMask;
150     m->NumberOfParameters = NumberOfParameters;
151
152     if (Parameters != NULL) {
153         try {
154             RtlCopyMemory (&m->Parameters,
155                            Parameters,
156                            sizeof(ULONG_PTR)*NumberOfParameters);
157         } except (EXCEPTION_EXECUTE_HANDLER) {
158         }
159     }
160
161     KeQuerySystemTime(&m->ErrorTime);
162     //执行发送函数
163     Status = LpcRequestWaitReplyPortEx (ErrorPort,
164                                         (PPORT_MESSAGE) m,
165                                         (PPORT_MESSAGE) m);
166
167     if (NT_SUCCESS(Status)) {
168         switch (m->Response) {
169             //作为一个返回值
170             case ResponseReturnToCaller :
171             case ResponseNotHandled :
172             case ResponseAbort :
173             case ResponseCancel :
174             case ResponseIgnore :
175             case ResponseNo :
176             case ResponseOk :
177             case ResponseRetry :
178             case ResponseYes :
179             case ResponseTryAgain :
180             case ResponseContinue :
181                 break;
182             default:
183                 m->Response = (ULONG)ResponseReturnToCaller;
184                 break;
185         }
186         *Response = m->Response;
187     }
188
189     return Status;
190 }

这个函数把硬错误信息发送到了CSRSS进程的\Windows\ApiPort端口上去。

接下来就是看CSRSS进程是怎么接受并处理这个硬错误消息的。

CSRSS进程中专门启用了一个线程来监听并处理\Windows\ApiPort端口的内容

CsrApiRequestThread就是这个专门用来监听的工作线程

PORT_MESSAGE是发送的LPC端口的数据结构。

CSRSS负责后续的处理工作,并进行用户层面的弹出提示。

转载于:https://www.cnblogs.com/Ox9A82/p/5383818.html

《软件调试》读书笔记:第13章 硬错误和蓝屏相关推荐

  1. PMP读书笔记(第13章)

    大家好,我是烤鸭:     今天做一个PMP的读书笔记. 第十三章 项目相关方管理 项目相关方管理 项目相关方管理的核心概念 项目相关方管理的趋势和新兴实践 裁剪考虑因素 在敏捷或适应型环境中需要考虑 ...

  2. 《逆向工程核心原理》读书笔记——第13章 PE文件格式

    第13章 PE文件格式 13.1 介绍 13.2.PE文件格式 13.2.1基本结构 13.2.2 VA&RVA 13.3.2 DOS存根 13.3.3 NT头 13.3.4 NT头中的文件头 ...

  3. UnixLinux大学教程 读书笔记【1-3章】

    Bash:Bourne-again shell,所有linux系统中的默认shell.程序名称:bash Shell:通过充当命令处理器以及解释命令的脚本,提供Unix基本界面的程序. 操作系统:运行 ...

  4. Javascript设计模式与开发实践读书笔记(1-3章)

    第一章 面向对象的Javascript 1.1 多态在面向对象设计中的应用   多态最根本好处在于,你不必询问对象"你是什么类型"而后根据得到的答案调用对象的某个行为--你只管调用 ...

  5. 《Javascript高级程序设计》读书笔记(1-3章)

    第一章 JavaScript简介 1.1 JavaScript简史 略 1.2 JavaScript实现 虽然 JavaScript 和 ECMAScript 通常都被人们用来表达相同的含义,但 Ja ...

  6. 《大话设计模式》读书笔记-第13章 建造者模式

    1.建造者模式(Builder),又叫生成器模式,它是将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的比奥斯.如果我们用了建造者模式,那么用户就只需指定需要建造的类型就可以得到它们 ...

  7. 《Spring实战》读书笔记-第3章 高级装配

    <Spring实战>是学习Spring框架的一本非常经典的书籍,之前阅读了这本书,只是在书本上写写画画,最近整理了一下<Spring实战>的读书笔记,通过博客的方式进行记录分享 ...

  8. PMP读书笔记(第9章)

    大家好,我是烤鸭:     今天做一个PMP的读书笔记. 第九章 项目资源管理 项目资源管理 项目资源管理的核心概念 项目资源管理的趋势和新兴实践 裁剪考虑因素 在敏捷或适应型环境中需要考虑的因素 9 ...

  9. PMP读书笔记(第2章)

    大家好,我是烤鸭:     今天做一个PMP的读书笔记. 第二章 项目运行环境 2.1 概述 2.2 事业环境因素 2.2.1 组织内部的事业环境因素 2.2.2 组织外部的事业环境因素 2.3 组织 ...

最新文章

  1. php 函数导航,PHP经典分页导航函数
  2. 部署项目到阿里云服务器上遇到的问题
  3. php 正则获取某个div,php正则匹配html中带class的div并选取其中内容的方法
  4. Spring MVC 返回NULL时客户端用$.getJSON的问题
  5. SQL Server CLR 启用、部署
  6. php配置实例,php mailto配置实例
  7. excel乘法公式怎么输入_python吊打Excel?那是你不会用!
  8. mysql能将查询结果与表左查询,MySQL查询与结构
  9. LINUX编译OPENJDK:The tested endian intarget (big) differs from the endian expected to be found in the
  10. Android下图片或按钮等可拖动到任意位置的效果实现源码
  11. vax_patch.exe谁有这个文件,可以免费分享一下嘛?
  12. 文件上传服务器方法,向服务器上传文件方法
  13. FA-PEG-NHS 叶酸PEG活性酯
  14. 节拍器在学习音乐过程中起到什么作用?-小星星节拍器怎么样?
  15. SWMM排水管网水力、水质建模及在海绵城市与水环境保护中的应用
  16. 网络模型可视化工具-netron
  17. FCOS:Fully Convolutional One-Stage Object Detection 论文翻译(非解读)
  18. 深度学习基础笔记——前向传播与反向传播
  19. 解决oracle导出dmp时 904错误
  20. android 模拟器输入中文

热门文章

  1. Git初学札记(五)————Branch分支管理
  2. go 字符串替换_Go语言爱好者周刊:第 64 期 — goup 这个工具了解下
  3. java 串的顺序存储_算法入门之串的顺序存储表示
  4. java存钱_用Java编写银行存钱取钱
  5. eq值 推荐算法_C++实现十种排序算法
  6. 深入jvm虚拟机第三版源码_深入JVM虚拟机,阿里架构师直言,这份文档真的是JVM最深解读...
  7. 大学计算机基础知识判断题,大学计算机基础学习知识判断题.doc
  8. 计算机网络项目化实训教程,计算机网络项目实训教程
  9. Spring Boot EasyUI edatagrid 扩展
  10. python界面设计实例qt_pyqt的最小示例qtreeview和qt设计