关于《竹林蹊径 深入浅出Windows驱动开发》第一个例子在Win7下蓝屏
2016-04-05 15:16
274 查看
在尝试运行《竹林蹊径 深入浅出Windows驱动开发》的第一个例子-HelloDRIVER时,在XP下没有问题,但在Win7下却发生蓝屏,蓝屏发生点在于卸载函数DriverUnload。
先看看卸载驱动的代码
很通用的卸载驱动例程,按道理是不会出现问题的,从dump文件进行进一步分析,定位到deviceObject = deviceObject->NextDevice;这一句蓝屏,复制操作会导致蓝屏?什么鬼,再看下调用堆栈
原来还没到赋值语句,在处于IoDeleteSymbolicLink阶段就发生蓝屏了,于是就断点调试看下IoDeleteSymbolicLink的参数linkName是否正常,一调试发现memory can't access,
为什么会出现内存不可访问,于是追溯到DriverEntry,下面看下这个函数里面做了什么操作
重点在于这两句
RtlInitUnicodeString(&symbolicLink, L"\\??\\HelloDRIVER");
deviceExtension->SymbolicLink = symbolicLink;
在网上查找资料RtlInitUnicodeString并没有动态分配内存,而是指向应用,而由于
#pragma alloc_text(INIT, DriverEntry)
DriverEntry函数是运行完后就退出内存,所以 RtlInitUnicodeString(&deviceName, L"\\Device\\HelloDRIVER");这个赋值方式不可靠。
解决方案:
在头文件或者函数外声明一个全局变量来存储符号链接,如
WCHAR linkNameBuffer[] = L"\\??\\HelloDRIVER";
然后再在函数内
RtlInitUnicodeString(&symbolicLink, linkNameBuffer);
即可解决读取符号链接不可访问的问题。
总结:
1.Win7会出现蓝屏,而XP不会,可能涉及到IoDeleteSymbolicLink里面的实现,会判断字符串的合法性问题
2.INIT和PAGE的区别,在驱动加载入口函数要注意字符串变量的生命周期
3.学会利用windbg进行调试分析
先看看卸载驱动的代码
VOID DriverUnload ( __in PDRIVER_OBJECT DriverObject ) { PDEVICE_OBJECT deviceObject; UNICODE_STRING linkName; KdPrint(("Enter HelloDRIVER DriverUnload!\n")); deviceObject = DriverObject->DeviceObject; while(NULL != deviceObject) { PDEVICE_EXTENSION deviceExtesion = (PDEVICE_EXTENSION)deviceObject->DeviceExtension; // 删除符号链接与设备 linkName = deviceExtesion->SymbolicLink; IoDeleteSymbolicLink(&linkName); deviceObject = deviceObject->NextDevice; IoDeleteDevice(deviceExtesion->DeviceObject); } KdPrint(("End of HelloDRIVER DriverUnload!\n")); }
很通用的卸载驱动例程,按道理是不会出现问题的,从dump文件进行进一步分析,定位到deviceObject = deviceObject->NextDevice;这一句蓝屏,复制操作会导致蓝屏?什么鬼,再看下调用堆栈
原来还没到赋值语句,在处于IoDeleteSymbolicLink阶段就发生蓝屏了,于是就断点调试看下IoDeleteSymbolicLink的参数linkName是否正常,一调试发现memory can't access,
为什么会出现内存不可访问,于是追溯到DriverEntry,下面看下这个函数里面做了什么操作
NTSTATUS DriverEntry ( __in PDRIVER_OBJECT DriverObject, __in PUNICODE_STRING RegistryPath ) { NTSTATUS status; PDEVICE_OBJECT deviceObject; PDEVICE_EXTENSION deviceExtension; UNICODE_STRING symbolicLink; UNICODE_STRING deviceName; ULONG i; KdPrint(("Enter HelloDRIVER DriverEntry!\n")); UNREFERENCED_PARAMETER(RegistryPath); RtlInitUnicodeString(&deviceName, L"\\Device\\HelloDRIVER"); // 处理派遣例程 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) { DriverObject->MajorFunction[i] = DefaultDispatch; } DriverObject->DriverUnload = DriverUnload; DriverObject->MajorFunction[IRP_MJ_CREATE] = DefaultDispatch; DriverObject->MajorFunction[IRP_MJ_CLOSE] = DefaultDispatch; DriverObject->MajorFunction[IRP_MJ_READ] = DefaultDispatch; DriverObject->MajorFunction[IRP_MJ_WRITE] = DefaultDispatch; // 创建设备 status = IoCreateDevice( DriverObject, sizeof(DEVICE_EXTENSION), &deviceName, FILE_DEVICE_UNKNOWN, 0, TRUE, &deviceObject); if(!NT_SUCCESS(status)) { return status; } deviceObject->Flags = DO_BUFFERED_IO; deviceExtension = (PDEVICE_EXTENSION)deviceObject->DeviceExtension; deviceExtension->DeviceObject = deviceObject; deviceExtension->DeviceName = deviceName; RtlInitUnicodeString(&symbolicLink, L"\\??\\HelloDRIVER"); deviceExtension->SymbolicLink = symbolicLink; // 创建符号链接 status = IoCreateSymbolicLink(&symbolicLink, &deviceName); if(!NT_SUCCESS(status)) { IoDeleteDevice(deviceObject); return status; } KdPrint(("End of HelloDRIVER DriverEntry!\n")); return status; }
重点在于这两句
RtlInitUnicodeString(&symbolicLink, L"\\??\\HelloDRIVER");
deviceExtension->SymbolicLink = symbolicLink;
在网上查找资料RtlInitUnicodeString并没有动态分配内存,而是指向应用,而由于
#pragma alloc_text(INIT, DriverEntry)
DriverEntry函数是运行完后就退出内存,所以 RtlInitUnicodeString(&deviceName, L"\\Device\\HelloDRIVER");这个赋值方式不可靠。
解决方案:
在头文件或者函数外声明一个全局变量来存储符号链接,如
WCHAR linkNameBuffer[] = L"\\??\\HelloDRIVER";
然后再在函数内
RtlInitUnicodeString(&symbolicLink, linkNameBuffer);
即可解决读取符号链接不可访问的问题。
总结:
1.Win7会出现蓝屏,而XP不会,可能涉及到IoDeleteSymbolicLink里面的实现,会判断字符串的合法性问题
2.INIT和PAGE的区别,在驱动加载入口函数要注意字符串变量的生命周期
3.学会利用windbg进行调试分析
相关文章推荐
- iOS中浅淡UIApplication单例
- Oracle 11g JSON库小于1的小数输出出错BUG 修复《JSON_UTIL_PKG》
- linux内核参数注释与优化
- linux内核参数注释与优化
- 浅谈 PHP 中的多种加密技术及代码示例
- 深入了解android平台的jni(一)
- MySQLBackup 使用说明
- 详解mysql备份恢复的三种实现方式
- 测试333
- 在hadoop下的多个文件合并
- mybatis源码分析 Exctor的执行代码
- python学习笔记(unittest)
- android RadioGroup的使用
- 为什么要用数据库连接池
- Qt QtcpSocket 发送文件(包括数据块总大小)
- View的滑动之侧滑菜单的实现
- DPDK和DNS服务器关系
- [安卓开发笔记一]Android开发配置opencv环境超详细教程
- Python中使用struct模块打包二进制数据
- python Web