Windows驱动中的Crash回调

来源:互联网 发布:java c s 开发框架 编辑:程序博客网 时间:2024/06/14 10:04
              

 没事不写博客,手就有点痒,不知道干嘛?总感觉今天有点什么事没做一样。所以,现在又开始写了。感觉自己已经对其他

的东西,没有兴趣。一开电脑,首先看下新闻,然后看下公司的邮箱。然后,就是下载点东东。就没事情了。今天写什么了,就写点

关于Windows驱动的CRASH回调函数的一些用法。

 我们知道CRASH,是Windows系统产生了无法恢复的错误,导致整个系统无法进行下去,而没有办法的一种选择。表项形式,

就是我们日常电脑中看到的蓝屏。其中的原因是多方面的,可能是内存访问越界,硬件问题,超时机制,中断机制等。我们有时候需

要捕捉这种信息,然后,给用户一种提示,或者反馈给开发人员,系统出现了严重的错误。这里,我们要用到CRASH的回调机制。这

里,主要有2个函数。KeRegisterBugCheckCallback和KeRegisterBugCheckReasonCallback。
 
 先看第一个:
 
        BOOLEAN KeRegisterBugCheckCallback(
        IN PKBUGCHECK_CALLBACK_RECORD  CallbackRecord,
      IN PKBUGCHECK_CALLBACK_ROUTINE  CallbackRoutine,
      IN PVOID  Buffer,
      IN ULONG  Length,
      IN PUCHAR  Component
     );
 
 这个函数很简单;
 
 第一个是CallbackRecord,这个感觉没什么用,感觉就是个枚举类别。需要使用移动非分页内存来初始化。MSDN上面说是指

向KBUGCHECK_CALLBACK_RECORD或者KBUGCHECK_REASON_CALLBACK_RECORD结构体的指针,由于这个结构体WINDOWS没有公开,所以一般

我没有管它。这个分配好空间的指针,需要使用 KeInitializeCallbackRecord函数来调用。
 
 第二个就是回调函数的地址。我们来看一下这个回调函数。

 VOID  BugCheckCallback(
      IN PVOID Buffer,
      IN ULONG Length
     );

        Buffer 感觉是DUMP的指针,Length 是大小,后续我验证后再确定。因为这个函数是在生成了DUMP以后来调用的。

        第三个参数:一个指向非分页空间的指针。
 
 第四个参数:空间的大小。
 
 第无个参树:可有可无,如果要填可以把设备驱动的名字写进去。

        再看一下第二个函数:
 
 NTKERNELAPI BOOLEAN  KeRegisterBugCheckReasonCallback (
      IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord,
      IN PKBUGCHECK_REASON_CALLBACK_ROUTINE CallbackRoutine,
      IN KBUGCHECK_CALLBACK_REASON Reason,
      IN PUCHAR Component
     );

 第一个参数:跟上面一样CallbackRecord,这个感觉没什么用,感觉就是个枚举类别。需要使用移动非分页内存来初始化。

MSDN上面说是指向KBUGCHECK_CALLBACK_RECORD或者KBUGCHECK_REASON_CALLBACK_RECORD结构体的指针,由于这个结构体WINDOWS没有

公开,所以一般我没有管它。这个分配好空间的指针,需要使用 KeInitializeCallbackRecord函数来调用。

        第二个参数:这里就不一样了,有两种回调函数的形式。
 
 VOID BugcheckDumpIoCallback (
      IN KBUGCHECK_CALLBACK_REASON Reason,
      IN PKBUGCHECK_REASON_CALLBACK_RECORD Record,
      IN OUT PVOID ReasonSpecificData,
      IN ULONG ReasonSpecificDataLength
     );

 VOID BugCheckSecondaryDumpDataCallback (
      IN KBUGCHECK_CALLBACK_REASON Reason,
     IN PKBUGCHECK_REASON_CALLBACK_RECORD Record,
      IN OUT PVOID ReasonSpecificData,
      IN ULONG ReasonSpecificDataLength
     );

 这两种形式,是有第三个参数决定的。
 
 第三个参数:可以取值KbCallbackDumpIo 来取回调的BugcheckDumpIoCallback这个形式,或者取

KbCallbackSecondaryDumpData指定回调函数的BugCheckSecondaryDumpDataCallback 这中类型。
 
 第四个参数:跟上面一样,可有可无,如果要填可以把设备驱动的名字写进去。

 再看一下回调函数的参数:

 第一个参数:可以取值KbCallbackDumpIo 来取回调的BugcheckDumpIoCallback这个形式,或者取

KbCallbackSecondaryDumpData指定回调函数的BugCheckSecondaryDumpDataCallback 这中类型。

        第二个参数:PKBUGCHECK_REASON_CALLBACK_RECORD Record这个参数,这个是什么了,一看就知道,就一个指向

KBUGCHECK_REASON_CALLBACK_RECORD的指针,但是很可惜,微软也没有公开这个结构体。感觉是记录回调函数的指针。
 
 第三个参树:指向下面结构体的指针。
 
 typedef struct _KBUGCHECK_DUMP_IO {
    IN ULONG64 Offset;
    IN PVOID Buffer;
    IN ULONG BufferLength;
    IN KBUGCHECK_DUMP_IO_TYPE Type;
 } KBUGCHECK_DUMP_IO, *PKBUGCHECK_DUMP_IO;

        typedef enum _KBUGCHECK_DUMP_IO_TYPE {
    KbDumpIoInvalid,
    KbDumpIoHeader,
    KbDumpIoBody,
    KbDumpIoSecondaryData,
    KbDumpIoComplete
 } KBUGCHECK_DUMP_IO_TYPE;

 第四个参数:就是系统传下来的KBUGCHECK_DUMP_IO的buffer的大小。如果是BugCheckSecondaryDumpDataCallback,这个大

小固定为sizeof(KBUGCHECK_DUMP_IO).

 这里需要说明的,KbDumpIoSecondaryData这个类型就是专为BugCheckSecondaryDumpDataCallback准备的。
 
 KeRegisterBugCheckReasonCallback 这个回调函数是,系统在生成DUMP文件的过程中调用的,

(KeRegisterBugCheckCallback是在生成后调用的),在生成的时候,会同步调用这个回调函数多次。
也就是会将DUMP的所有内容都传到这个函数中来。我们可以通过Buffer,以及KBUGCHECK_DUMP_IO_TYPE来完成整个DUMP文件的备份,

或保护。
 
 还有一点需要注意的是,这两个回调函数的优先级非常高,我之前试过好像是15。所以很多函数都不能调用。一般可以调用

读写硬件寄存器的函数。比如READ/WRITE_REGISTER_XXX,或者READ/WRITE_IO_PORT_XXX系列函数。
 
 禁止进行做的事情有:
 
 1,分配内存(已经崩溃当然不行)。
 
 2,进入分页内存(当然不行,优先级太高)。
 
 3,使用同步机制(当然不行,优先级太高)。

 4, 调用那些必须值IRQL等于或小于DISPATCH_LEVEL优先级的函数。
 
 


 
       
 
       

   

原创粉丝点击