在最新版的WDK框架里,我们新建了Windows Driver KMDF模型之后默认使用的TraceEvents来打印输出的,这套输出机制叫WPP,我们可以在DriverEntry函数里看到它的初始化代码:

WPP_INIT_TRACING(DriverObject, RegistryPath);
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");

如果想要使用TraceEvents需要在WPP_INIT_TRACING之后才能使用,它们依赖于Trace.h文件,一般默认生成KMDF时Visual Studio会自动生成这个头文件,里面包含了WPP的相关定义。

如果没有可以新建一个Trace.h头文件,并输入如下内容:

这段代码取自微软官方封装的WPP代码。

/*++Module Name:Trace.hAbstract:Header file for the debug tracing related function defintions and macros.Environment:Kernel mode--*///
// Define the tracing flags.
//
// Tracing GUID - 16803b14-05e0-4215-9336-06418469d132
//#define WPP_CONTROL_GUIDS                                              \WPP_DEFINE_CONTROL_GUID(                                           \KMDFDriver1TraceGuid, (16803b14,05e0,4215,9336,06418469d132), \\WPP_DEFINE_BIT(MYDRIVER_ALL_INFO)                              \WPP_DEFINE_BIT(TRACE_DRIVER)                                   \WPP_DEFINE_BIT(TRACE_DEVICE)                                   \WPP_DEFINE_BIT(TRACE_QUEUE)                                    \)                             #define WPP_FLAG_LEVEL_LOGGER(flag, level)                                  \WPP_LEVEL_LOGGER(flag)#define WPP_FLAG_LEVEL_ENABLED(flag, level)                                 \(WPP_LEVEL_ENABLED(flag) &&                                             \WPP_CONTROL(WPP_BIT_ ## flag).Level >= level)#define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) \WPP_LEVEL_LOGGER(flags)#define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) \(WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= lvl)//
// WPP orders static parameters before dynamic parameters. To support the Trace function
// defined below which sets FLAGS=MYDRIVER_ALL_INFO, a custom macro must be defined to
// reorder the arguments to what the .tpl configuration file expects.
//
#define WPP_RECORDER_FLAGS_LEVEL_ARGS(flags, lvl) WPP_RECORDER_LEVEL_FLAGS_ARGS(lvl, flags)
#define WPP_RECORDER_FLAGS_LEVEL_FILTER(flags, lvl) WPP_RECORDER_LEVEL_FLAGS_FILTER(lvl, flags)//
// This comment block is scanned by the trace preprocessor to define our
// Trace function.
//
// begin_wpp config
// FUNC Trace{FLAGS=MYDRIVER_ALL_INFO}(LEVEL, MSG, ...);
// FUNC TraceEvents(LEVEL, FLAGS, MSG, ...);
// end_wpp
//

最下面这段是伪指令,给编译器看的,目的就是生成Trace宏函数

//
// This comment block is scanned by the trace preprocessor to define our
// Trace function.
//
// begin_wpp config
// FUNC Trace{FLAGS=MYDRIVER_ALL_INFO}(LEVEL, MSG, ...);
// FUNC TraceEvents(LEVEL, FLAGS, MSG, ...);
// end_wpp
//

然后在你的源文件中包含"Trace.h"头文件,包含好了我们在修改一下配置,让Visual Stuio知道Trace对应的描述文件是哪个,我们打开项目配置开始配置:

一、在Wpp Tracing中将Run Wpp Tracing设置为Yes,开启Trace日志功能

二、将Function And Macro Options中的Enable Infight Trace Recorder设置为yes,开启追踪功能,让日志输出到内核记录日志里去,这样就能用一些软件去读这个记录日志里读到我们的通过Trace打印的日志了。

三、在File Options中的Scan Configuration Data里输入我们刚刚创建的文件名,告诉编译器描述Trace文件是哪个。

包含了之后在你的文件中包含"driver.tmh"就可以了,这里的名称以你包含Trace.h的文件名称为例,在编译时编译器会自动编译Trace.h中的伪指令并生成对应的.tmh文件。

tmh文件里就包含了TraceEvents宏函数声明和实现

在使用TraceEvents函数之前需要先初始化,在你的DriverEvent里将它初始化:

WPP_INIT_TRACING(DriverObject, RegistryPath);

这里介绍一下TraceEvents的宏函数的使用方法:

TraceEvents(LEVEL, FLAGS, STR,...);

LEVEL表示信息模式级别,可以取以下值:

#define TRACE_LEVEL_NONE        0   // Tracing is not on
#define TRACE_LEVEL_CRITICAL    1   // Abnormal exit or termination
#define TRACE_LEVEL_FATAL       1   // Deprecated name for Abnormal exit or termination
#define TRACE_LEVEL_ERROR       2   // Severe errors that need logging
#define TRACE_LEVEL_WARNING     3   // Warnings such as allocation failure
#define TRACE_LEVEL_INFORMATION 4   // Includes non-error cases(e.g.,Entry-Exit)
#define TRACE_LEVEL_VERBOSE     5   // Detailed traces from intermediate steps
#define TRACE_LEVEL_RESERVED6   6
#define TRACE_LEVEL_RESERVED7   7
#define TRACE_LEVEL_RESERVED8   8
#define TRACE_LEVEL_RESERVED9   9

FLAGS表示标志,即当前打印的发生在哪个标志上,当我们创建一个KMDF框架时一般分为三个文件:

Device.c 设备文件,在加载驱动时会调用,用于创建设备,比如Linux驱动加载以后会在Dev下创建一个设备文件

Driver.c   驱动文件,驱动代码

Queue.c   驱动退出相关代码

这三个分别对应不同事件时产生的,Device.c会在创建设备时被调用,而Driver.c则是驱动代码,用于驱动设备时会被调用,Queue.c则是在收尾时会被调用。

在打印时应针对不同的情况设置不同的FLAGS,所以FLAGS支持如下几个选项:

MYDRIVER_ALL_INFO:所有,通用设备信息

TRACE_DRIVER:驱动标志,表示当前处于驱动事件阶段

TRACE_DEVICE:设备标志,表示当前处于设备事件阶段

TRACE_QUEUE:收尾标志,表示当前设备驱动将进行uninstall

有时使用这些标志可能会出现未定义的情况,可以忽略,你build之后不会报错,这个原因可能是编译器生成tmh文件时缓存没有更新过来。

最后演示一下用法:

TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "Hello Word!");

可变参数,可以像Printf一样使用

TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "Hello Word!%d",1);

当我们编译好并生成sys之后我们想要调试怎么办?

WDK提供了一个工具:traceview.exe,注意TraceEvents打印的只能用这款软件DbgView查看不到的。

你到WDK的安装目录下进入Tools-x64(x86)下能找到这款软件。

然后选中File-Create New Log Session,然后选择PDB调试的方式,我们生成的sys一般都附带了PDB文件,里面包含了调试信息,sys驱动文件路径等等。

选择你的PDB之后点击OK

然后点击Next

最后点击Finish,如果想保存Log可以选中Log Trace Event Data To File

最后我们设置事件等级,双击Level

因为我们里面使用的是TRACE_LEVEL_INFORMATION,所以选中Information

最后FLags全都选中,然后点击OK就可以了

到这一步日志系统就准备好了,那么就剩最后一步,就是加载驱动。

WDK自带了一个devcon.exe的工具,但是用起来不是那么方便,这里我使用的是另外一个加载的工具,Windows也提供了SC加载服务的API函数,大家可以利用这些函数实现自己的加载工具。

我使用的是:DriverMonitor,同时也有:KmdManager,这两款加载工具目前还是不错的。

以下是这两款软件的截图,同时附上下载地址:SysLoader驱动加载程序,用于调试驱动-WindowsServer文档类资源-CSDN下载:

DriverMonitor:

KmdManager:

这里我使用的是DriverMonitor,以管理员权限打开它,然后选择:File-Open Driver...

选择你的Driver

然后点击GO图标会开始调用驱动代码,DriverCreate函数是在加载驱动时调用的,当点击GO图标时调用的驱动代码是DriverEntry函数。

当我们执行的时候它报了一个错误:

翻译过来就是Windows无法验证数字签名,这个是在Win7以后的系统都需要数字签名,如何申请签名这个后面说,先教大家在调试时解决这个问题,大家可以在Win10的Setting界面进入高级选项,关闭数字签名,具体可以Web搜索一下Win10关闭数字签名

然后就可以了

同时在TraceView中可以看到对应的输出:

当我们想删除驱动时可以点击X图标就可以了

Windows Driver开发_TraceEvents调试以及加载驱动的方法相关推荐

  1. rd450linux系统,RD450 板载r110i raid 安装RHEL 6.5 x64 加载驱动的方法(UEFI引导模式)...

    CentOS 6.5 x64通用.所有联想服务器 R110i的raid卡通用. 因为联想没有CentOS系统的驱动,可以用RedHat的驱动,找到对应的版本,我用过可以. 本方法按照RD450 OS安 ...

  2. Windows Phone开发之路(14) 加载位图

    除了文本之外,位图是Silverlight程序中最常见的对象之一,通常我们将其定义为与图形显示设备的像素相对应的二维比特(bit)数组. Windows原生的位图文件的扩展名是bmp,但是近年它已不占 ...

  3. iOS开发UI中懒加载的使用方法

    1.懒加载基本 懒加载--也称为延迟加载,即在需要的时候才加载(效率低,占用内存小).所谓懒加载,写的是其getter方法.说的通俗一点,就是在开发中,当程序中需要利用的资源时.在程序启动的时候不加载 ...

  4. Windows 10搜索框一直搜索/加载的解决方法

    重装了win10系统后,发现搜索框输入完内容就一直在加载,什么东西也搜索不到. 神奇的是切换到Administrator账户使用起来就没有问题.于是把自己账户权限改到最高,但问题并没有解决. 百度给了 ...

  5. Windows Driver开发_NT Driver框架:The driver is not in a state to accept this command

    通常我们可以使用一些驱动加载工具来改变我们驱动的行为,如加载驱动时执行入口函数与卸载函数,这里是我用当我们点击Start时会调用DriverEvent函数,并且正常加载 但当我们点击Stop卸载时确报 ...

  6. iOS开发UI篇—懒加载

    iOS开发UI篇-懒加载 1.懒加载基本 懒加载--也称为延迟加载,即在需要的时候才加载(效率低,占用内存小).所谓懒加载,写的是其get方法. 注意:如果是懒加载的话则一定要注意先判断是否已经有了, ...

  7. 成功解决:将后缀.pyx格式文件(linux环境)编译成pyd文件(windows环境下)实现python编程加载或导入

    成功解决:将后缀.pyx格式文件(linux环境)编译成pyd文件(windows环境下)实现python编程加载或导入 目录 解决问题 解决思路 解决方法 解决问题 .pyx格式文件,在window ...

  8. Chrome 调试动态加载的js

    今天有个同事问到我用chrome调试动态加载js的问题,这个问题之前遇到过,只是时间有点长了,有些忘记.在这里做一下记录: 在要调试的源码的后面加上 //@ sourceURL= debug.js 注 ...

  9. 通过安装和配置AD域解决Windows Server 2016的IIS无法加载SMB文件卷文件的问题

    通过安装和配置AD域解决Windows Server 2016的IIS无法加载SMB文件卷文件的问题 1. 问题描述 通过客户反馈我们发现Windows Server 2016的IIS无法加载SMB文 ...

最新文章

  1. Python Json存储与读取
  2. 几张旧照片,用傻瓜拍的,翻出来凑数 (续)
  3. android 调用java接口_android调用java的web service接口
  4. java super用法_Java基础面试题汇总
  5. Python AttributeError: 'module' object has no attribute 'posseg'
  6. 自己在win10中添加ADO控件步骤总结
  7. 数据科学 IPython 笔记本 7.15 高性能 Pandas
  8. 自适应滤波器原理第四版计算机实验,自适应滤波器原理(中文第4版)答案
  9. Python框架篇之Django(基本流程、命令行、配置文件)
  10. 怎么用bat关闭远程协助计算机,Windows批处理请求远程协助
  11. slqite3库查询数据处理方式_SQLite数据库使用 常用命令
  12. RazorSQL for Mac:查看和编辑二进制数据和图像
  13. R语言系列:分布一致性和离散一致性检验
  14. 清华大学c语言程序设计课件,c语言清华大学课件
  15. 飞机遭遇时空乱流离奇穿越到30年前
  16. 服务器怎么查看c盘大文件在哪里,怎么快速查找系统中的大文件?
  17. 笔记本搜不到WiFi是什么原因
  18. 用stata计算同比增长率的两种方法
  19. sap crm button_如何安装SAP软件?
  20. 六方面的学习,帮你走上业务架构师之路

热门文章

  1. int 最大值_十行代码说清楚:leetcode 队列的最大值
  2. js怎么给div加滑动条 vue给弹出层加滑动条(一分钟学会用js加滚动条)
  3. java future 返回值_Java--Callable与返回值future
  4. 基于hadoop构建对象存储系统_基于Hadoop企业私有云存储平台的构建
  5. python read函数参数_最新Pandas.read_excel()全参数详解(案例实操,如何利用python导入excel)...
  6. sql重复数据只保留一条_一条SQL完成跨数据库实例Join查询
  7. android beam 第三方 aar,NFC通讯之Beam方式
  8. linux中dir命令,详解Linux系统中ls和dir命令的组合使用
  9. python 检查域名是否可以访问_糖尿病人是否都要做喝糖水的检查?结果可以说明胰岛功能水平吗?...
  10. 计算机骗局案例,骗局揭秘 | 卖你一台假电脑,再送你一个假鲁大师