YJX_Driver_012_为DDK_HelloWorld添加设备例程
1、
【00:50】vs2003编译环境,它有一个功能vc6没有,稳定性 比 VC6高一些,另外 它是中文的 而非汉化的
【01:15】将 第10课 的代码copy过来
【01:42】VC6的工程 转换为 vs2003 的工程
【01:52】vs2003 --> 项目 --> 属性 --> "配置管理器..." --> 新建一个配置 --> 【366】"项目配置名(C)" 填为 "check" -->>
【439】"解决方案窗口" 选中"mini_ddk",然后 菜单栏 --> 项目 --> 属性 --> C/C++ --> 常规 中,(1)、"调试信息格式"选为"C7 兼容(/Z7)",(2)、"取消显示启动版权标志" 选为 "否",(3)、"警告等级" 选为 "3级(/W3)",(4)、"将警告视为错误" 选为 "是(/WX)"
【493】项目 --> 属性 --> C/C++ --> 优化 中,"优化"选为"禁用(/Od)"
【505】项目 --> 属性 --> C/C++ --> 预处理器 中,我们参考 第7课的配置,填入"WIN32=100;_X86_=1;WINVER=0x501;DBG=1"
【567】项目 --> 属性 --> C/C++ --> 代码生成 中,"运行时库"选为"多线程调试(/MTd)"
【590】项目 --> 属性 --> C/C++ --> 高级 中,(1)、"调用约定"选为"__stdcall(/Gz)"(ZC: 其他选项分别为"__cdecl(/Gd)" 和 "__fastcall(/Gr)"),(2)、"编译为"选为"编译为C代码(/TC)"
【649】项目 --> 属性 --> 链接器 --> 常规 中,(1)、"输出文件"由"$(OutDir)/$(ProjectName).exe"改为"$(OutDir)/$(ProjectName).sys",(2)、"启用增量链接"改为"否(/INCREMENTAL:NO)"
【678】项目 --> 属性 --> 链接器 --> System 中,(1)、"堆栈保留大小"由"0"改为"0x400000"(填入的是16进制数,转到下一行后,vs2003会自动转为10进制数),(2)、"堆栈提交大小"由"0"改为"0x1000"
ZC: 记得在哪本书上看到过,内核中的程序堆栈都比较小,嵌套不能太深,这里是在强制指定本驱动的堆栈大小吗?使得本驱动能够使用较大的堆栈?
【738】项目 --> 属性 --> 链接器 --> 优化 中,"Windows98 优化"改为"否(/OPT:NOWIN98)"
【760】项目 --> 属性 --> 链接器 --> 高级 中,(1)、"基址"填入"0x10000",(2)、"入口点"填入"DriverEntry"
【798】项目 --> 属性 --> 链接器 --> 输入 中,"附加依赖项"填入"ntoskrnl.lib"
【833】这样设置基本完毕。
【840】项目 --> 属性 --> 链接器 --> 命令行 中,"附加选项(D):"填入"/Driver /system:native"(ZC: 听他的意思,"/system:native"是指“内核的”?)
【886】项目 --> 属性 --> 链接器 --> System 中,"子系统"由"未设置"改为"控制台(/SUBSYSTEM:CONSOLE)"
【903】重新生成解决方案 mini_ddk, OK,可以正常的生成驱动了
【930】注意,这里只是正常的生成了驱动,并不是说这个驱动就能正常的运行,这是 我们的参数设置所导致的,如果没有设置的好的话 有可能导致蓝屏。比如说我们驱动 装载/卸载 的时候 出现 蓝屏 或 不稳定的现象,后面给出解决的办法
【1033】我们这里(对vs2003)进行配置,主要是为了方便我们在IDE环境里面编辑程序
ZC: 搞了这么多,难道只是为了写代码方便?编译 还是用 ddk的自带命令行?
【1111】创建设备的具体步骤
“
1、用 RtlInitUnicodeString 初始化设备名称(ZC: 字符串)指针
2、用 IoCreateDevice创建设备,如果不成功 则返回
3、用 IoCreateSymlicLink创建符号链接,创建成功返回 STATUS_SUCCESS,创建不成功 则调用IoDeleteDevice删除设备
”
ZC: 一直没明白,干嘛要创建设备?它是干嘛用的?貌似是用于和上层通信的
【1220】http://msdn.microsoft.com/en-us/library/default.aspx
ZC: 貌似这个地址的内容变化了...
【1723】写代码测试
#pragma INITCODE // 【3015】指 代码运行后 就从内存中释放掉,减少资源占用
NTSTATUS CreateMyDevice(IN PDRIVER_ONJECT _pDriverObject)
{
NTSTATUS stauts;
PDEVICE_OBJECT pDevObj;/*用来返回创建设备*/
// 创建设备名称
UNICODE_STRING devName;
UNICODE_STRING symLinkName;
RtlInitUnicodeString(&devName, L"\\Device\\yjxDDK_Device"); // 对devName初始化
// 创建设备
stauts = IoCreateDevice(_pDriverObject,\
0,\ // 【2245】扩展结构的大小。创建的设备的扩展指针的大小(DEVICE_OBJECT中的一个成员)
&devName,\
FILE_DEVICE_UNKNOWN,\
0, TRUE,\
&pDevObj);
if (! NT_SUCCESS(stauts))
{
if (stauts == STATUS_INSUFFICIENT_RESOURCES)
KdPrint(("资源不足 STATUS_INSUFFICIENT_RESOURCES"));
else if (stauts == STATUS_OBJECT_NAME_EXISTS)
KdPrint(("指定对象名存在"));
else if (stauts == STATUS_OBJECT_NAME_COLLISION)
KdPrint(("对象名有冲突"));
KdPrint(("设备创建 失败"));
return stauts;
}
KdPrint(("设备创建 成功"));
pDevObj->Flags != DO_BUFFERED_IO;
// 创建符号链接
RtlInitUnicodeString(&symLinkName, L"\\??\\yjx888");
stauts = IoCreateSymbolLink(&symLinkName, &devName);
if (! NT_SUCCESS(stauts))
{
IoDeleteDevice(pDevObj);
return stauts;
}
return STATUS_SUCCESS;
}
【2348】DEVICE_OBJECT 位于 ntddk.h中,wdm.h中也存在该结构的定义
_DEVICE_OBJECT
【2403】PVOID _DEVICE_OBJECT.DeviceExtension; //指向一个自定义结构(编程人员可以自己定义该结构内容)
【2528】FILE_DEVICE_UNKNOWN 指定创建设备的类型
【2720】ZC: 独占的设备 什么意思?
【3195】#define INITCODE code_seg("INIT")
#define PAGECODE code_seg("PAGE") // 这里的 "PAGECODE"这个名字是可以随便取的
【3240】表示 当内存不足时(或者 相应的内存 没有用到的时候),可以被置换到虚拟内存(硬盘)中
【3438】L"\\Device\\yjxDDK_Device" 中
前面的部分"\\Device\\" 是不能变的
后面的部分"yjxDDK_Device" 是可以变化的
【3577】符号链接 中 前面部分"\\??\\" 也是不能变化的,后面能变化
【3593】如果前面部分变化了,会报错,类似于: 驱动的格式/设备的格式 不正确,这个设备不能够被正常的加载
【4150】编译一下,用的是 vs2003编译的"重新生成解决方案",成功了
【4348】设备对象 是内核态 里面才能使用的,符号链接 暴露给 用户层使用
【4675】用DDK来编译一下(ZC: 还是用 DDK来编译...)
【4702】用 vs2003 编译出来的驱动,并非一定稳定 有可能会蓝屏 保险起见用DDK来编译一下
【4960】光写 函数CreateMyDevice(...) 是没有任何作用的,我们要把它 加到 入口函数里面去
NTSTATUS DriverEntry(PDRIVER_OBJECT _pDrvierObject, PUNICODE_STRING B)
{
KdPrint(("驱动成功被加载...OK+++++++++"));
CreateMyDevice(_pDrvierObject);
_pDrvierObject->DriverUnload = DDK_Unload;
return 1;
}
【5202】用DDK重新编译一下
【5295】打开 DebugView、DriverMonitor
【5433】DriverMonitor 中报错信息(ZC:貌似是路径里面不能有 中文/空格 之类的?)
【5497】用 WinObj 查看一下
【5503】左侧 选择的是 "Driver",在 右侧 查看 是否已经有我们刚刚加载的驱动
【5560】ZC: 此时,可以看到,他 双击的是"360AntiARP",弹出来的对话框是"Unable to open \Driver\360AntiARP",可以猜想 这里的 列"Name" 显示的就是 驱动的设备名称的 后半部分。又∵ 在这里找不到"yjxDDK_Device",∴ 个人觉得 应该说明 驱动刚才没有加载成功
【5577】左侧 选择 "Device",又 换回 "Driver" 了...
【5645】把名字改一下,再加载 (ZC: 该说明名字?驱动设备名?.sys文件的名称?)
【5655】直接改的是 .sys的文件名... "DDK_HelloWorld.sys"改为"oWorld1.sys"
说可能已经存在了一个叫"DDK_HelloWorld.sys" 的驱动。∵一个驱动只允许一个实例
【5753】此时,加载 成功了,有调试信息输出
【5780】再用 WinOBJ.exe 查看一下
ZC: 看到 列"Name" 中有名为 "OWorld1"(ZC: 这里首字母是大写的) 的一条记录了。说明上面的我的猜想是不对的,这里的列"Name" 显示的就是 .sys的文件名,于是刚才也不是 中文路径的问题。疑问:列"Name"中 也没有"DDK_HelloWorld"啊,为何之前加载 "DDK_HelloWorld.sys"会不成功?
【5970】说 WinOBJ.exe显示的不是很详细
【6005】DDK中自带有工具,显示的驱动信息更为详细
开始 --> Development Kits --> Windows DDK 3790.1830 --> Tools --> Device Tree
【6073】ZC: 这里左侧 显示的也是 .sys的文件名
【6240】点击"Device Tree"的工具栏上面的 按钮"P",以PDO的方式来看一下(ZC: PDO是啥?啥意思?)
【6335】这里,找到了 我们的符号链接
【6460】找到的是 "[RootLEGACY_YJX_888]",我们没有加入 下划线,∴肯定不是这个
【6590】ZC: 找到这里,没找到类似"??yjx888??"的项,他也不找了,直接退出"Device Tree"...
【6630】DriverMonitor 中 "STOP"掉驱动,再次"GO"的时候 肯定会报错。为何会有出错信息呢
【6672】驱动没有成功的卸载掉,需要重命名.sys文件(ZC: 为何没有成功卸载?不是有卸载例程了吗?)
【6685】改名 "oWorld1.sys"改为"11oWorld1.sys"
【6708】此时 加载驱动,"GO"之后 有"设备名有冲突"等 的信息打印出来
【6740】因为 设备被创建出来之后,没有被正常的删掉
【6840】继续编程
【6930】下一节课再讲 如何在卸载例程中删除 设备(名称) 和 符号链接,这样才能成功的卸载驱动对象
2、