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

会话管理器进程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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/573726.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

信息安全技术网络安全等级保护定级指南_行业标准 |报业网络安全等级保护定级参考指南V2.0发布,明确保护对象、定级要求...

近期,中国新闻技术工作者联合会正式发布《报业网络安全等级保护定级参考指南V2.0》。该指南由中国新闻技术工作者联合会组织网络安全领域的专家、报业技术专家以及业务专家经过多次调研、学习、探讨后,在原《报业网络安全等级保护定级参考指南V1.0》的基…

数学作图工具_科研论文作图系列-从PPT到AI (一)

导语:之前的推送中,小编给大家介绍过几款科研作图软件,包括统计分析软件Origin和Prism,图像处理软件ImageJ等等。从本期开始,小编将和大家一起继续学习科研论文作图。重点介绍图像的处理和排版,用到的工具主…

优启通怎么重装系统win10_重装系统失败?小编教你安全给神舟战神GX9 Pro重装win10系统方法...

神舟战神GX9 Pro 上市于2016年1月,虽然现在已经停产,但是还是有不少用户依旧十分喜爱这款笔记本。这款笔记本的性能完全对得起它的售价,很多用户都反馈其比外星人电脑要好。对于爱玩游戏的用户而言,对它17.3英寸的显示屏简直欲罢不…

20135202闫佳歆--week 8 实验:理解进程调度时机跟踪分析进程调度与进程切换的过程--实验及总结...

week 8 实验:理解进程调度时机跟踪分析进程调度与进程切换的过程 1.环境搭建: rm menu -rf git clone https://github.com/megnning/menu.git cd menu ls make rootfs qemu -kernel ../linux-3.18.6/arch/x86/boot/bzImage -initrd ../rootfs.img -s -S …

java jni技术_JNI技术简介

JNI(Java Native Interface)提供一种Java字节码调用C/C的解决方案,JNI描述的是一种技术。NDK(Native Development Kit)Android NDK 是一组允许您将 C 或 C(“原生代码”)嵌入到 Android 应用中的工具,NDK描述的是工具集。 能够在 Android 应用中使用原生…

java web redis_java web redis使用(二)

上篇中已经安装好redis,然后下面就说怎么在java web中用客户端来使用regis使用jedis java客户端一:一个简单的示例代码:public static void main(String[] args) {Jedis jedis new Jedis( "147.151.240.234" , 6379 );jedis.set("foo&…

mysql 主从_搭建mysql主从并编写监控主从状态脚本

要求:两台centos7虚拟机分为主和从安装mysqlyum -y install mysql mysql-server关闭防火墙service iptables stopsetenforce 0上面的主从都做。修改主的配置文件vi /etc/my.cnf#添加server-id1log-binmysqlbinrelay-logrelays之后保存退出重启mysql服务service …

Java核心技术点之动态代理

本篇博文会从代理的概念出发,介绍Java中动态代理技术的使用,并进一步探索它的实现原理。由于个人水平有限,叙述中难免出现不清晰或是不准确的地方,希望大家可以指正,谢谢大家:) 一、概述 1. 什么…

shell入门之expr的使用

在expr中加减乘除的使用,脚本例如以下: #!/bin/sh #a test about expr v1expr 5 6 echo "$v1" echo expr 3 5 echo expr 6 / 2 echo expr 9 \* 5 echo expr 9 - 6 执行效果 转载于:https://www.cnblogs.com/bhlsheji/p/5401458.html

java中子线程与主线程通信_Android笔记(三十二) Android中线程之间的通信(四)主线程给子线程发送消息...

之前的例子都是我们在子线程(WorkerThread)当中处理并发送消息,然后在主线程(UI线程)中获取消息并修改UI,那么可以不可以在由主线程发送消息,子线程接收呢?我们按照之前的思路写一下代码:packagecn.lixyz.handlertest;…

java开源笔记软件下载_开发常用软件笔记 - ZhaoQian's Blog - OSCHINA - 中文开源技术交流社区...

notepad使用快捷键CtrlH打开“替换对话框”,在每行的开头添加内容。 勾选左下角的“正则表达式”选项 在“查找目标”里输入上尖号“^”,上尖号代表每行的开头 在“替换为”里输入“private String”。然后点"全部替换"按钮,这样每…

极光推送指定用户推送_App用户都睡着了?是时候用推送和活动唤醒一波了!

想要运营好一款App,引流、留存、促活三大环节必不可少。引流解决了用户来的问题,留存解决了用户留下来的问题,而促活解决的是让一部分新注册用户以及许久没有动静的老用户,在平台中再次活跃起来。今天,我们就来聊聊关于…

oracle awr报告生成_分享AWR报告的生成和简单分析方法

生成AWR报告方法:第一步:数据库压力测试卡开始时:生成第一个快照:Sql>exec dbms_workload_repository.create_snapshot();第二步:数据库压力测试结束时:生成第二个快照Sql>exec dbms_workload_reposi…

安卓开发 登录用户信息缓存_在Linux上使用finger命令查询登录用户信息

请关注本头条号,每天坚持更新原创干货技术文章。如需学习视频,请在微信搜索公众号“智传网优”直接开始自助视频学习1. 前言本文主要讲解finger命令的作用和日常使用案例。finger命令是一个用户信息查询命令,它给出了所有登录用户的详细信息。…

POJ 1065 Wooden Sticks

http://blog.csdn.net/acdreamers/article/details/7626671 学习一下Dilworth定理 推荐一篇写得很好博客 要求最少的覆盖&#xff0c;按照Dilworth定理 最少链划分 最长反链长度 所以最少系统 最长导弹高度上升序列长度。 之前写的LIS模板不对。。。。。。 1 #include<cst…

python 对象_Python小课堂面向对象

Python3 面向对象Python从设计之初就已经是一门面向对象的语言&#xff0c;正因为如此&#xff0c;在Python中创建一个类和对象是很容易的。本章节我们将详细介绍Python的面向对象编程。如果你以前没有接触过面向对象的编程语言&#xff0c;那你可能需要先了解一些面向对象语言…

使用jemalloc优化java_Jemalloc优化MySQL和Nginx

Redis 2.4版本之后&#xff0c;默认使用jemalloc来做内存管理&#xff1b;tengine也整合jemalloc。jemalloc从各方评测的结果可见与google tcmalloc都不相伯仲&#xff0c;皆为内存管理器领域最高水平。如下图&#xff1a;最左边的就是glibc的malloc&#xff0c;最右边的就是je…

【代码升级】【iCore3 双核心板】例程二十八:FSMC实验——读写FPGA

实验指导书及代码包下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1i6WL51V 密码&#xff1a;1mk4 iCore3 购买链接&#xff1a; https://item.taobao.com/item.htm?id524229438677 转载于:https://www.cnblogs.com/xiaomagee/p/5409024.html

sqlserver连接字符串_【自学C#】|| 笔记 39 SQL server 连接数据库

一、ADO.NET数据库操作 任何一个应用程序都离不开数据的存储&#xff0c;数据可以在内存中存储&#xff0c;但只能在程序运行时存取&#xff0c;无法持久保存。数据还可以在磁盘中以文件的形式存储&#xff0c;但文件的管理和查找又十分烦琐无法胜任大数量的存储。将数据存储…

Android Studio、 补充知识以及主要组件

转载于:https://www.cnblogs.com/arxk/p/5410597.html