导读:
发信人: shamanfeng (杀闏), 信区: MSDN
标 题: [合集] 学习写一个Hello World驱动
发信站: BBS 水木清华站 (Fri Nov 26 09:34:21 2004), 站内
☆─────────────────────────────────────☆
hellguard (小四★北渡北汉江⊙) 于 (Wed Jun 11 15:44:48 2003) 提到:
学习笔记,没有技术含量,高手勿Ctrl-F了
日期: 2003-06-10 21:50
更新:
--------------------------------------------------------------------------
目录:
☆ 概述
☆ 编写hello.c文件
☆ 编写dirs文件
☆ 编写sources文件
☆ 编写makefile文件
☆ 编译产生hello.sys文件
☆ 编写hello.inf文件
☆ 安装hello.inf文件
☆ 卸载hello.sys及相关设置
☆ 察看KdPrint输出
☆ 使用DriverMonitor
☆ 参考资源
--------------------------------------------------------------------------
☆ 概述
在<<MSDN系列(1)--学习使用"/Device/PhysicalMemory">>中,我首次接触了Windows
内核,并演习了通过调用门从Ring 3进入Ring 0,进而获取一些内核空间的信息。这
种方式利弊岂有之,总的来说弊大于利。
听说现在Windows驱动和Unix下LKM、KLD一样,允许动态加载/卸载。过去我们在Unix
下常利用类似技术进行Kernel Hacking,今天我来学习如何在Windows下做同样的事。
拣空看了三本书([1]、[2]、[3])的个别章节,感觉举步维艰,想说"Hello World"不
容易。
我安装了EWindows XP SP1、VC 7、Windows DDK 2600.1106、ActivePerl 5.6.1、
Compuware SoftICE Release 2.7、VMware Workstation 3.2,以方便此次学习过程。
如果你碰巧也有类似环境,并且也是此道初学者的话,后面的许多步骤将相当容易重
现。
下面是学习笔记。为了简捷起见,并没有时刻指明某项操作是在开发机还是在测试机
进行,但你务必清楚区分开发机、测试机上应该进行的操作。
☆ 编写hello.c文件
--------------------------------------------------------------------------
/*
* For x86/EWindows XP SP1 & VC 7 & Windows DDK 2600.1106
* build -cZ -x86
*/
/************************************************************************
* *
* Head File *
* *
************************************************************************/
#include <wdm.h>
/************************************************************************
* *
* Macro *
* *
************************************************************************/
#define PRIVATEDRIVERNAME "PRIVATE_HELLO_WORLD"
/************************************************************************
* *
* Function Prototype *
* *
************************************************************************/
/************************************************************************
* *
* Static Global Var *
* *
************************************************************************/
/************************************************************************/
/*
* DriverEntry is the first routine called after a driver is loaded, and
* is responsible for initializing the driver.
*
* you'll find a list of NTSTATUS status codes in the DDK header
* ntstatus.h (/WINDDK/2600.1106/inc/ddk/wxp/)
*/
NTSTATUS DriverEntry ( IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
CHAR privatedrivername[] = PRIVATEDRIVERNAME;
/*
* 这是无效的用户空间地址
*/
PVOID p = ( PVOID )1;
/*
* kernel-mode functions and the functions in your driver use the
* __stdcall calling convention when compiled for an x86 computer.
* This shouldn't affect any of your programming, but it's something
* to bear in mind when you're debugging
*/
/*
* This routine is defined in ntddk.h, wdm.h, and ndis.h.
* A call to this macro requires double parentheses.
*/
KdPrint(( "%s - Entering DriverEntry()/n", privatedrivername ));
__try
{
KdPrint(( "%s - You should see this message[1]/n", privatedrivername ));
/*
* 由于1未对齐在4字节边界上,引发SYSTEM_DATATYPE_MISALIGNMENT异常。
* Do not use this routine on kernel-mode addresses.
*/
ProbeForWrite( p, 4, 4 );
KdPrint(( "%s - You shouldn't see this message[1]/n", privatedrivername ));
}
__except ( EXCEPTION_EXECUTE_HANDLER )
{
KdPrint(( "%s - __except{}/n", privatedrivername ));
}
KdPrint(( "%s - Kept control after exception/n", privatedrivername ));
__try
{
KdPrint(( "%s - You should see this message[2]/n", privatedrivername ));
__leave;
KdPrint(( "%s - You shouldn't see this message[2]/n", privatedrivername ));
}
__finally
{
KdPrint(( "%s - __finally{}/n", privatedrivername ));
}
KdPrint(( "%s - Exiting DriverEntry()/n", privatedrivername ));
/*
* 故意失败返回
*/
return( STATUS_UNSUCCESSFUL );
} /* end of DriverEntry */
/************************************************************************/
--------------------------------------------------------------------------
用户空间编程,main()、WinMain()是总入口点。与之类似,DriverEntry()是驱动程
序总入口点,它的两个形参对于目前阶段的我来说并不重要。其最后故意失败返回,
使我可以不考虑绝大多数复杂情况,而专注于如何编译驱动程序、加载驱动程序,观
察驱动程序调试输出信息。同样的技巧在Unix系统使用过。
与用户空间的结构化异常处理(SEH)相比,内核空间的SEH主要致力于捕捉内核代码访
问无效用户空间地址产生的异常,它无法捕捉除以零、内核代码访问无效内核空间地
址产生的异常。
hello.c中由于1未对齐在4字节边界上,ProbeForWrite( p, 4, 4 )引发相应异常。
SEH机制使程序继续保持控制权。对于__try{}/__finally{},若因return、continue、
break、goto等语句提前离开__try{},将导致一次开销可观的"局部展开"。__leave
语句用于避免不必要的"局部展开"。
KdPrint(())的用法与printf()类似,注意调用该宏时必须指定两层圆括号。
☆ 编写dirs文件
与用户空间编程不同,只有hello.c不足以产生hello.sys,至少还需要三个文件:
dirs、sources、makefile
DDK文档"Running the Build Utility"小节对此有详细解释。build根据dirs文件遍
历目录树,在子目录中发现dirs时继续遍历,发现sources时build开始为调用nmake
做准备。nmake使用makefile,最终调用cl进行真正的编译。
假设将来的目录/文件布局是这样的:
hello/ --+-- dirs
|
+-- code/ --+-- hello.c
|
+-- sources
|
+-- makefile
这里只列举了手工创建的目录/文件,不包括编译过程产生的目录/文件。
此时dirs文件内容很简单,就一行:
--------------------------------------------------------------------------
DIRS=code
--------------------------------------------------------------------------
☆ 编写sources文件
--------------------------------------------------------------------------
#
# Use the TARGETNAME macro to specify the name of the library to be built.
# Do not include the file name extension
#
TARGETNAME=hello
#
# All build products (such as .exe, .dll, and .lib files) will be placed
# in this directory
#
TARGETPATH=obj
#
# Use the TARGETTYPE macro to specify the type of product being built.
# TARGETTYPE gives the Build utility clues about some of the input files
# that it should expect. You must include this macro in your sources file.
#
TARGETTYPE=DRIVER
#
# Use the USE_PDB macro if your debug symbolic files will use a VC4 PDB.
# This is the default in the Windows XP build environment.
#
USE_PDB=1
#
# Use the INCLUDES macro to indicate the location of the headers to be
# included in your build
#
INCLUDES=
#
# Use the MSC_WARNING_LEVEL macro to set the warning level to use on the
# compiler. The default is /W3.
#
# After your code builds without errors, you might want to change
# MSC_WARNING_LEVEL to /W3 /WX. Setting this value causes warnings to show
# as errors.
#
MSC_WARNING_LEVEL=-W3 -WX
#
# The SOURCES macro specifies the files to be compiled. The SOURCES macro
# is required by the Build utility. This macro must be placed in your
# sources file. All files specified by this macro must reside in the
# directory containing the sources file.
#
SOURCES=hello.c
--------------------------------------------------------------------------
必要的解释我都放在sources文件里了。单独多解释一下TARGETPATH,BUILD_ALT_DIR
的值会被追加在TARGETPATH之后。假设进入了"Win XP Checked Build Environment":
> set BUILD_ALT_DIR
BUILD_ALT_DIR=chk_wxp_x86
此时在hello/下执行build -cZ -x86,产生的目录/文件布局如下:
hello/ --+-- buildchk_wxp_x86.log
|
+-- dirs
|
+-- code/ --+-- hello.c
|
+-- hello.inf
|
+-- sources
|
+-- makefile
|
+-- objchk_wxp_x86/ --+-- _objects.mac
|
+-- i386/ --+-- hello.sys
|
+-- hello.obj
|
+-- hello.pdb
如果你嫌BUILD_ALT_DIR对于目前阶段太碍眼,可以删除该环境变量:
> set BUILD_ALT_DIR=
此时在hello/下执行build -cZ -x86,产生的目录/文件布局如下:
hello/ --+-- build.log
|
+-- dirs
|
+-- code/ --+-- hello.c
|
+-- hello.inf
|
+-- sources
|
+-- makefile
|
+-- obj/ --+-- _objects.mac
|
+-- i386/ --+-- hello.sys
|
+-- hello.obj
|
+-- hello.pdb
☆ 编写makefile文件
--------------------------------------------------------------------------
!INCLUDE $(NTMAKEENV)/makefile.def
--------------------------------------------------------------------------
J:/source/driver/hello> set NTMAKEENV
NTMAKEENV=J:/WINDDK/2600~1.110/bin
☆ 编译产生hello.sys文件
在dirs文件所在目录里执行"build -cZ -x86":
J:/source/driver/hello> build -cZ -x86
BUILD: Adding /Y to COPYCMD so xcopy ops won't hang.
BUILD: Compile and Link for i386
BUILD: Examining j:/source/driver/hello directory tree for files to compile.
BUILD: Compiling j:/source/driver/hello/code directory
Compiling - code/hello.c for i386
BUILD: Linking j:/source/driver/hello/code directory
Linking Executable - code/obj/i386/hello.sys for i386
BUILD: Done
2 files compiled
1 executable built
J:/source/driver/hello>
☆ 编写hello.inf文件
; ------------------------------------------------------------------------
;
; Copyright to satisfy the CHKINF utility
;
[Version]
Signature = "$Windows NT$"
Class = %ClassName%
;
; For a new device setup class, the INF must specify a newly generated
; ClassGuid value
;
; 用/WINDDK/2600.1106/tools/other/i386/guidgen.exe生成
;
ClassGuid = {EABDB9DF-F09D-44ba-81E5-551C2ABC1FA9}
Provider = %INFCreator%
DriverVer = 06/10/2003,1.00.1993.9
; ------------------------------------------------------------------------
[ClassInstall32.ntx86]
AddReg = ClassInstall32Reg
[ClassInstall32Reg]
HKR,,,,%ClassName%
; ------------------------------------------------------------------------
[Manufacturer]
%INFCreator% = HelloWorldSection
; ------------------------------------------------------------------------
[HelloWorldSection]
%DESCRIPTION% = DDInstall,*HWD1993
; ------------------------------------------------------------------------
[SourceDisksNames.x86]
1 = %DiskDescription%,,,
[SourceDisksFiles.x86]
hello.sys = 1
[DestinationDirs]
DefaultDestDir = 10,system32/drivers
FileList = 10,system32/drivers
; ------------------------------------------------------------------------
[DDInstall.ntx86]
Copyfiles = FileList
[FileList]
hello.sys,,,0x00000002
; ------------------------------------------------------------------------
[DDInstall.ntx86.Services]
AddService = HelloWorld,0x00000002,ServiceInstall
[ServiceInstall]
DisplayName = %FriendlyName% ; friendly name
ServiceType = 0x00000001 ; SERVICE_KERNEL_DRIVER
StartType = 0x3 ; SERVICE_DEMAND_START
ErrorControl = 0x1 ; SERVICE_ERROR_NORMAL
ServiceBinary = %10%/system32/drivers/hello.sys
; ------------------------------------------------------------------------
[DDInstall.ntx86.HW]
AddReg = DDInstallRegHW
[DDInstallRegHW]
HKR,,HelloWorldInfo,,%DESCRIPTION%
; ------------------------------------------------------------------------
[Strings]
ClassName = "HelloWorldClass"
INFCreator = "The Hello World Software"
DESCRIPTION = "The Hello World Driver"
DiskDescription = "The Hello World Software Disk"
FriendlyName = "Hello World"
; ------------------------------------------------------------------------
DDK文档详细解释了如何编写INF文件。不过个人觉得DDK文档适合在阅读一份现成的
INF文件时当作手册查看。如果妄图在没有样板INF文件的情况下通过查看DDK文档来
从头写一份新INF文件,至少初学者不要有这样的念头。为了写这么点破烂,我费劲
坏了。
用/WINDDK/2600.1106/tools/other/i386/guidgen.exe生成ClassGuid。
执行如下命令对hello.inf文件提前进行一些检查:
/WINDDK/2600.1106/tools/chkinf> chkinf.bat hello.inf
在/WINDDK/2600.1106/tools/chkinf/htm/目录里生成分析报告:
--------------------------------------------------------------------------
Line 7: (E22.1.1081) Directive: CatalogFile required (and must not be blank) in section [Version] for WHQL digital signature.
Line 9: (E22.1.1310) Class HelloWorldClass (ClassGUID {EABDB9DF-F09D-44ba-81E5-551C2ABC1FA9}) is unrecognized.
--------------------------------------------------------------------------
第一个错误因为我没有指定"CatalogFile.ntx86 = ...",目前阶段也没法指定。第
二个错误因为ClassGuid是新创建的。
刚开始写hello.inf文件时,分析报告里还有不少错误、警告信息。应该在某注释行
中包含"Copyright"单词,否则分析报告里有"No Copyright information found."警
告信息。
知道为什么要安装ActivePerl 5.6.1么,chkinf.bat需要Perl解释器的支持!
Walter Oney的光盘([1])需要安装,他的安装过程会在这里增加相关内容:
HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Class
不清楚他这么做的好处何在,说实话,挺烦这手的。不喜欢安装这些人提供的随书光
盘,它们使我丧失了深入了解问题本质的机会,这也是我没有安装DriverStudio中其
它开发工具的原因。由于源代码已经在那里,我没有执行setup.exe,只是直接编译
并试图安装其中的某些例子程序:
> fastinst.exe xxx.inf
结果得到一个对话框式的错误提示,ERROR_SECTION_NOTFOUND。setupapi.log中看到:
--------------------------------------------------------------------------
找不到 [ClassInstall32] 段。
--------------------------------------------------------------------------
chkinf.bat xxx.inf的分析报告里有相应警告信息:
--------------------------------------------------------------------------
Custom defined Classes should have a [ClassInstall32] section.
--------------------------------------------------------------------------
最初的hello.inf没有下面这部分内容,自然会遇上同样的问题:
--------------------------------------------------------------------------
[ClassInstall32.ntx86]
AddReg = ClassInstall32Reg
[ClassInstall32Reg]
HKR,,,,%ClassName%
--------------------------------------------------------------------------
此外,注意这一节:
--------------------------------------------------------------------------
[DDInstall.ntx86]
Copyfiles = FileList
--------------------------------------------------------------------------
刚开始多根据DDK文档写成"CopyFiles = ...",结果在/windows/setupapi.log中看
到:
--------------------------------------------------------------------------
在 "hello.inf" 的 [FileList] 段分析 "Copyfiles" 失败。 错误 0xe0000102: 在 INF 中找不到所需的行。
--------------------------------------------------------------------------
这个错误导致hello.sys未被复制到/windows/system32/drivers/目录下。按大小写
敏感方式修改成现在使用的样子就解决了。如果用"fastinst.exe hello.inf"进行安
装,不会遇到该问题,我怀疑这是MS的一个小BUG。
经验就是,安装过程出了问题先看setupapi.log文件。
顺便提一下,DDK提供了GenInf工具,这是一个垃圾工具,即使对初学者也如此。测
试使用了一次,强烈建议大家当它不存在。Art Baker委婉地表述了类似观点([3])。
☆ 安装hello.inf文件
Walter Oney的fastinst.exe果然便捷,不过个人建议在试图了解更多细节的时候还
是少依赖它为妙。
控制面板->添加硬件->是,硬件已联接好->添加新的硬件设备->
安装我手动从列表选择的硬件(高级)->显示所有设备->从磁盘安装->完成
由于hello.c最后故意失败返回,安装虽然完成,但加载驱动必然失败。在设备管理
器中可以看到黄色惊叹号,表示无法成功加载驱动程序。
这次安装过程导致如下一些动作:
1)
--------------------------------------------------------------------------
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Class/{EABDB9DF-F09D-44BA-81E5-551C2ABC1FA9}]
"Class"="HelloWorldClass"
@="HelloWorldClass"
[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Class/{EABDB9DF-F09D-44BA-81E5-551C2ABC1FA9}/0000]
"InfPath"="oem5.inf"
"InfSection"="DDInstall"
"InfSectionExt"=".NTx86"
"ProviderName"="The Hello World Software"
"DriverDateData"=hex:00,40,43,3c,e3,2e,c3,01
"DriverDate"="6-10-2003"
"DriverVersion"="1.0.1993.9"
"MatchingDeviceId"="*hwd1993"
"DriverDesc"="The Hello World Driver"
--------------------------------------------------------------------------
2)
--------------------------------------------------------------------------
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Enum/Root/UNKNOWN]
[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Enum/Root/UNKNOWN/0000]
"ClassGUID"="{EABDB9DF-F09D-44BA-81E5-551C2ABC1FA9}"
"ConfigFlags"=dword:00000004
"Driver"="{EABDB9DF-F09D-44BA-81E5-551C2ABC1FA9}//0000"
"Class"="HelloWorldClass"
"Mfg"="The Hello World Software"
"HardwareID"=hex(7):2a,00,68,00,77,00,64,00,31,00,39,00,39,00,33,00,00,00,00,/
00
"Service"="HelloWorld"
"DeviceDesc"="The Hello World Driver"
"Capabilities"=dword:00000000
[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Enum/Root/UNKNOWN/0000/Device Parameters]
"HelloWorldInfo"="The Hello World Driver"
[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Enum/Root/UNKNOWN/0000/LogConf]
[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Enum/Root/UNKNOWN/0000/Control]
--------------------------------------------------------------------------
3)
--------------------------------------------------------------------------
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/HelloWorld]
"Type"=dword:00000001
"Start"=dword:00000003
"ErrorControl"=dword:00000001
"ImagePath"=hex(2):73,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,64,00,/
72,00,69,00,76,00,65,00,72,00,73,00,5c,00,68,00,65,00,6c,00,6c,00,6f,00,2e,/
00,73,00,79,00,73,00,00,00
"DisplayName"="Hello World"
[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/HelloWorld/Security]
"Security"=hex:01,00,14,80,90,00,00,00,9c,00,00,00,14,00,00,00,30,00,00,00,02,/
00,1c,00,01,00,00,00,02,80,14,00,ff,01,0f,00,01,01,00,00,00,00,00,01,00,00,/
00,00,02,00,60,00,04,00,00,00,00,00,14,00,fd,01,02,00,01,01,00,00,00,00,00,/
05,12,00,00,00,00,00,18,00,ff,01,0f,00,01,02,00,00,00,00,00,05,20,00,00,00,/
20,02,00,00,00,00,14,00,8d,01,02,00,01,01,00,00,00,00,00,05,0b,00,00,00,00,/
00,18,00,fd,01,02,00,01,02,00,00,00,00,00,05,20,00,00,00,23,02,00,00,01,01,/
00,00,00,00,00,05,12,00,00,00,01,01,00,00,00,00,00,05,12,00,00,00
[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/HelloWorld/Enum]
"0"="ROOT//UNKNOWN//0000"
"Count"=dword:00000001
"NextInstance"=dword:00000001
"INITSTARTFAILED"=dword:00000001
--------------------------------------------------------------------------
4) 复制hello.sys到/windows/system32/drivers/目录下。
在setupapi.log中可以看到如下内容:
--------------------------------------------------------------------------
[2003/06/11 14:06:31 1780.404]
#-198 处理的命令行: "/system32/rundll32.exe" shell32.dll,Control_RunDLL "/system32/hdwwiz.cpl",添加硬件
#I140 正在安装设备类别: "HelloWorldClass" {EABDB9DF-F09D-44ba-81E5-551C2ABC1FA9}。
#I141 类别安装已结束,没有出错。
[2003/06/11 14:06:32 1780.407 Driver Install]
#-124 正在做“仅复制”安装 "ROOT/UNKNOWN/0000"。
#-198 处理的命令行: "/system32/rundll32.exe" shell32.dll,Control_RunDLL "/system32/hdwwiz.cpl",添加硬件
#E360 驱动程序 "The Hello World Driver" 的一个未经过签署或签署不正确的文件 "hello.inf" 将得到安装(策略=忽略)。 错误 0xe000022f: 第三方 INF 不包含数字签名信息。
#-024 正在将文件 "hello.sys" 复制到 "/system32/drivers/hello.sys"。
#E360 驱动程序 "The Hello World Driver" 的一个未经过签署或签署不正确的文件 "hello.inf" 将得到安装(策略=忽略)。 错误 0xe000022f: 第三方 INF 不包含数字签名信息。
#-166 设备安装函数: DIF_REGISTER_COINSTALLERS。
#I056 注册了共同安装程序。
#-166 设备安装函数: DIF_INSTALLINTERFACES。
#-011 正在从 "hello.inf" 安装段 [DDInstall.NTx86.Interfaces]。
#I054 安装接口。
#-166 设备安装函数: DIF_INSTALLDEVICE。
#I123 进行 "ROOT/UNKNOWN/0000" 的完整安装。
#E360 驱动程序 "The Hello World Driver" 的一个未经过签署或签署不正确的文件 "hello.inf" 将得到安装(策略=忽略)。 错误 0xe000022f: 第三方 INF 不包含数字签名信息。
#I163 设备未开始: 设备有问题: 0x25: CM_PROB_FAILED_DRIVER_ENTRY.
#I121 "ROOT/UNKNOWN/0000" 的设备安装成功完成。
--------------------------------------------------------------------------
如果在资源管理器中右键选中hello.inf,点击菜单里的"安装",不知为何,毫无动
静。注册表、drivers目录、setupapi.log均无变化,活见鬼了。目前我还不懂这里
的窍道,以后再来理解。
HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet只是到ControlSet<nnn>的符号链接,
HKEY_LOCAL_MACHINE/SYSTEM/Select用于具体确定是到谁的符号链接。启动时F8菜单
有一个选项对应最近一次成功引导所用设置,就是由LastKnownGood决定的。参看[4]
的5.2.6小节。
☆ 卸载hello.sys及相关设置
1)
手工卸载很简单,在注册表中删除上述三处内容,在drivers目录中删除hello.sys。
2)
也可以执行"sc delete HelloWorld":
> sc delete HelloWorld
[SC] DeleteService SUCCESS
设备管理器中倒是看不到相应显示了。注册表中残留了一点内容:
--------------------------------------------------------------------------
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Class/{EABDB9DF-F09D-44BA-81E5-551C2ABC1FA9}]
"Class"="HelloWorldClass"
@="HelloWorldClass"
--------------------------------------------------------------------------
并且drivers/hello.sys也未删除。
3)
还有一种方式,通过设备管理器卸载,比"sc delete HelloWorld"干得活还要少些,
注册表中"HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/HelloWorld"
还在。
个人建议用第二种方式,结合一些手动操作。
这样仔细地手工折腾一趟之后,想必对驱动的安装/卸载有了初步认识吧。反正我是
感觉学到不少东西。
☆ 察看KdPrint输出
从Unix转过来的兄弟们不要幻想有uprintf()这样的内核函数可用。只有类似Linux下
printk()的KdPrint输出。有很多办法察看这个输出,这次我用DebugView([5])。在
Capture菜单里勾中Capture kernel、Pass-Through、Capture Events即可。扔到一
边别理它。
添加硬件过程最终会尝试加载hello.sys,DriverEntry()被调用,在DebugView中可
以看到KdPrint输出,确认SEH起作用了。
安装结束后如想再次进入DriverEntry(),可以执行"net start HelloWorld"。
☆ 使用DriverMonitor
Compuware DriverStudio Release 2.7中提供了DriverMonitor。在File菜单里选择
"Open Driver"打开hello.sys,选择"Start Driver"调用DriverEntry(),直接看到
KdPrint输出信息。如果同时启动了DebugView,两边都可看到,此时可以顺带加强对
Pass-Through设置的理解。
好处在于不必编写hello.inf就可测试hello.sys。"Open Driver"时会临时在注册表
中设置一些内容:
--------------------------------------------------------------------------
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/Hello]
"Type"=dword:00000001
"Start"=dword:00000003
"ErrorControl"=dword:00000001
"ImagePath"=hex(2):5c,00,3f,00,3f,00,5c,00,63,00,3a,00,5c,00,6f,00,6e,00,6c,00,/
79,00,74,00,65,00,6d,00,70,00,5c,00,68,00,65,00,6c,00,6c,00,6f,00,5c,00,68,/
00,65,00,6c,00,6c,00,6f,00,2e,00,73,00,79,00,73,00,00,00
"DisplayName"="Hello"
[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/Hello/Security]
"Security"=hex:01,00,14,80,90,00,00,00,9c,00,00,00,14,00,00,00,30,00,00,00,02,/
00,1c,00,01,00,00,00,02,80,14,00,ff,01,0f,00,01,01,00,00,00,00,00,01,00,00,/
00,00,02,00,60,00,04,00,00,00,00,00,14,00,fd,01,02,00,01,01,00,00,00,00,00,/
05,12,00,00,00,00,00,18,00,ff,01,0f,00,01,02,00,00,00,00,00,05,20,00,00,00,/
20,02,00,00,00,00,14,00,8d,01,02,00,01,01,00,00,00,00,00,05,0b,00,00,00,00,/
00,18,00,fd,01,02,00,01,02,00,00,00,00,00,05,20,00,00,00,23,02,00,00,01,01,/
00,00,00,00,00,05,12,00,00,00,01,01,00,00,00,00,00,05,12,00,00,00
[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/Hello/Enum]
"Count"=dword:00000000
"NextInstance"=dword:00000000
"INITSTARTFAILED"=dword:00000001
--------------------------------------------------------------------------
因此可以"net start Hello"激发KdPrint输出。在File菜单里选择"Remove Service
Entry"将删除上述内容,退出DriverMonitor前应该执行该操作。
DriverMonitor不会做其它操作,比如不会复制hello.sys到drivers目录下,也不影
响设备管理器。
好,我这次目的达到了,现在对编译、安装、卸载Windows驱动有了感性认识,顺带
学习了一些工具的使用,希望对你也有所帮助。下次就不知道什么时候开始第三次学
习了,正经工作是编写扫描器插件以及Unix漏洞跟踪分析,想学点Windows不容易,
还好不是太苦闷。
☆ 参考资源
[ 1] <<Programming the Microsoft Windows Driver Model>> - Walter Oney
[ 2] <<Windows NT Device Driver Development>> - P. Viscarola, W. Mason
[ 3] <<The Windows 2000 Device Driver Book, Second Edition>> - Art Baker, Jerry Lozano
[ 4] <<Inside Microsoft Windows 2000 Third Edition>> - David A. Solomon, Mark E. Russinovich
[ 5] DebugView
http://www.sysinternals.com
☆─────────────────────────────────────☆
cygwin (梦醒⊙崇尚暴力) 于 (Wed Jun 11 17:01:07 2003) 提到:
【 在 soycola (酱油可乐) 的大作中提到: 】
: 标 题: Re: 学习写一个Hello World驱动
: 发信站: BBS 水木清华站 (Wed Jun 11 16:15:09 2003), 转信
:
: 这个是wdm版的hello world,这个过程掩盖了很多实质问题。
:
: 我的理解wdm为了支持设备的即插即用引入了复杂的驱动安装
: 过程,即必须编写inf文件并使用新设备向导,反观nt驱动,
: 只要调用几个service control manager的api就可以完成安装,
: 究其本质原因,应当是nt4的driver-centered的驱动模型和
: win 2000的device centered驱动模型之间的区别。nt4的驱动
: 模型说白了就是linux采用的模型,nt4的net start就是linux的
: 的insmod,nt4的net stop就是linux的rmmod。当然nt4在执行
: net start之前必须执行一个轻量级的安装工作(主要是createservice
: ),而这个createservice的过程在linux下面只是将驱动的.o
: 文件拷贝到相关路径中即可(我自己的理解,请小四兄指正)。
: 当然nt4的这个‘服务式’驱动模型和linux的驱动模型也有区别,
: nt4中的服务可以是用户态的,换句话说,nt4的服务约等于
: linux的核心模块+linux的daemon程序,而wdm驱动则约等于
: nt4核心态驱动+pnp支持+电源管理支持。
你所说的nt4方案也可以2k下用啊
只要打开service manager
加入服务,启动服务
就搞定了
:
: 所以,如果说nt4的驱动模式更接近于linux,则那些ms fans不妨可以
: 认为windows的wdm比linux先进。
:
: btw,对于小四兄的应用,我想大部分情况下应该只是一个nt4核心
: 态驱动就够了,不需要wdm支持。对这种程序,写一个hello
: world其实更简单。我一会儿转一个过来大家审查一下。
: 【 在 hellguard (小四★北渡北汉江⊙) 的大作中提到: 】
: : 学习笔记,没有技术含量,高手勿Ctrl-F了
: : 日期: 2003-06-10 21:50
: : 更新:
: : --------------------------------------------------------------------------
: : 目录:
: : ☆ 概述
: : ☆ 编写hello.c文件
: : ☆ 编写dirs文件
: : ☆ 编写sources文件
: : ☆ 编写makefile文件
: : ☆ 编译产生hello.sys文件
: : ...................
:
: --
:
: ※ 来源:·BBS 水木清华站 smth.org·[FROM: 61.51.240.205]
☆─────────────────────────────────────☆
cygwin (梦醒⊙崇尚暴力) 于 (Wed Jun 11 17:12:01 2003) 提到:
这我就不懂了
filemon的那个驱动不是wdm的?
【 在 soycola (酱油可乐) 的大作中提到: 】
: wdm驱动这样做是不行的,嘿嘿,wdm驱动都是按需加载的,有设备才
: 加载(所以才能实现pnp),所以它那个StartupType统统是3:demand_start
: ,除了一些启动时需要加载的驱动以外。2k为了兼容nt,wdm驱动仍然
: 保留了服务这个概念,但是由于我在上面说的原因,我们应当认识到
: 服务这个driver center的东西本质上和wdm这种device centered的架构
: 是不甚融洽的。
☆─────────────────────────────────────☆
cygwin (梦醒⊙崇尚暴力) 于 (Wed Jun 11 17:21:35 2003) 提到:
我只写过一回驱动
所以对这些了解不多
刚才在driverdev找kmd,
发现只有一篇文章,还是提问的
驱动除了vxd(win9x),wdm,kmd还有没有其它类型?
而wdm与kmd又有何居别?
【 在 soycola (酱油可乐) 的大作中提到: 】
: 小四所说‘想说hello不容易’是因为kmd的驱动编译环境实在
: 复杂,相信每个写过驱动的人都有体会,至于安装复杂还在其次。
: 我回的帖子主要是两个意思,1是可以用那个极简单的makefile解决
: 编译复杂的问题(ddk的那个build程序是微软自己用来编译win2k
: 的,所以考虑了很多细节,至于我们用它则属于牛刀宰鸡),2是
: 可以回避复杂的安装,直接用nt4的那个方案,因为小四用的程序
: 估计只是一个KMD。
反正我知道它的这个程序肯定可以用nt4的那种方式加载。
☆─────────────────────────────────────☆
hellguard (小四★北渡北汉江⊙) 于 (Wed Jun 11 17:46:17 2003) 提到:
【 在 soycola (酱油可乐) 的大作中提到: 】
> 我想大部分情况下应该只是一个nt4核心
> 态驱动就够了,不需要wdm支持。对这种程序,写一个hello
> world其实更简单。我一会儿转一个过来大家审查一下。
这个我明白,的确是不需要WDM,不过是顺手逮着学学。那我就等着学
你那个例子啦。主要是市面上的书直奔硬件而去,我想找个Hello World
而不得,只好自己瞎折腾一回,见笑见笑。
Linux的驱动模型我并不熟悉更多,只是从前写过LLKM而已。我所
接触的FKLD、SLKM都是伪设备驱动,真要讨论涉及物理的驱动,我
一点经验都没有的。
☆─────────────────────────────────────☆
hellguard (小四★北渡北汉江⊙) 于 (Wed Jun 11 17:47:57 2003) 提到:
好,多谢,我回头学学
【 在 soycola (酱油可乐) 的大作中提到: 】
: 诺,就是这个,很久以前在driverdev贴的,自己挺臭美的所以就转过来了呵呵。
: /*++
: hello.c
: --*/
: #define _X86_
: #include <ddk/ntddk.h>
: #pragma comment(linker, "/entry:DriverEntry /subsystem:native /base:0x10000 /driver")
: #pragma comment(lib, "wdm.lib")
: VOID _stdcall Unload(IN PDRIVER_OBJECT DriverObject)
: {
: DbgPrint("Bye bye!/n");
: ...................
☆─────────────────────────────────────☆
hellguard (小四★北渡北汉江⊙) 于 (Wed Jun 11 17:56:00 2003) 提到:
发现听你讲这些挺省事的啊,虽然不搞这些东西,听你讲讲
也有收获,
上次你们提到
A New Interface for Driver Writing -- The Windows Driver Framework
在OSR主站上有这篇,
http://www.osronline.com/article.cfm?id=212
我转在Driver版了,已经换行处理过
【 在 soycola (酱油可乐) 的大作中提到: 】
: 98就不说了。只说wdm和kmd,我能想到的最精确的描述就是:
: KMD(kernel mode driver)是‘驱动程序为中心’驱动架构
: 下的产物WDM驱动是设备中心的驱动架构下的产物。不过这么
: 说可能过于概括。在KMD时代,驱动程序处于主导地位,发现
: 并枚举总线和设备、找到或分配设备的资源占用情况、创建
: 设备对象并提供环境子系统可以访问的符号链接等,都是驱动
: 程序的工作。驱动告诉os说这里有个设备,驱动告诉os说这个
: 设备的io、mem、dma、irq,驱动创建一个设备对象然后扔给os说
: 给你个设备,然后os才知道有个设备;
: 而在WDM时代就不一样了,设备翻身做了主人,在总线驱动和控
: 制器驱动(注1)的帮助下,os自己就知道当前计算机上链接有哪些设
: ...................
☆─────────────────────────────────────☆
netfun (netfun) 于 (Tue Jun 17 15:41:30 2003) 提到:
WDM是Microsoft为了统一9x系列与NT系列而引入的驱动模型,实际上pnp与power只是
她的两个需求而已,这可以从Windows Driver Model的命名可以看到。
在NT系列中WDM构建于NT Legacy KMD(Kernel Mode Driver NT4)的基础上,并不是不
甚融洽的。而正是由于PNP与Power的引入才使Driver的安装发生了根本的变革,使其复杂
的多,但是pnp driver的安装仍是基于最基本的services的概念,正是由于安装的复杂,
microsoft引入了setupapi.dll用于这部分任务,而setupapi.dll则是对services的封
装,当然实际上整个过程是非常复杂的,从内核态引入root bus(/driver/pnpmanager
这是一个ntoskrnl.exe buildin driver)到device node等等。这一切的基础都是KMD。
Microsoft并没有鄙弃KMD,WDM是KMD发展而来的。
【 在 soycola (酱油可乐) 的大作中提到: 】
: wdm驱动这样做是不行的,嘿嘿,wdm驱动都是按需加载的,有设备才
: 加载(所以才能实现pnp),所以它那个StartupType统统是3:demand_start
: ,除了一些启动时需要加载的驱动以外。2k为了兼容nt,wdm驱动仍然
: 保留了服务这个概念,但是由于我在上面说的原因,我们应当认识到
: 服务这个driver center的东西本质上和wdm这种device centered的架构
: 是不甚融洽的。
本文转自
http://smth.edu.cn/bbsanc.php?path=%2Fgroups%2Fcomp.faq%2FMSDN%2Fdiscuss%2FM.1101432861.80
发信人: shamanfeng (杀闏), 信区: MSDN
标 题: [合集] 学习写一个Hello World驱动
发信站: BBS 水木清华站 (Fri Nov 26 09:34:21 2004), 站内
☆─────────────────────────────────────☆
hellguard (小四★北渡北汉江⊙) 于 (Wed Jun 11 15:44:48 2003) 提到:
学习笔记,没有技术含量,高手勿Ctrl-F了
日期: 2003-06-10 21:50
更新:
--------------------------------------------------------------------------
目录:
☆ 概述
☆ 编写hello.c文件
☆ 编写dirs文件
☆ 编写sources文件
☆ 编写makefile文件
☆ 编译产生hello.sys文件
☆ 编写hello.inf文件
☆ 安装hello.inf文件
☆ 卸载hello.sys及相关设置
☆ 察看KdPrint输出
☆ 使用DriverMonitor
☆ 参考资源
--------------------------------------------------------------------------
☆ 概述
在<<MSDN系列(1)--学习使用"/Device/PhysicalMemory">>中,我首次接触了Windows
内核,并演习了通过调用门从Ring 3进入Ring 0,进而获取一些内核空间的信息。这
种方式利弊岂有之,总的来说弊大于利。
听说现在Windows驱动和Unix下LKM、KLD一样,允许动态加载/卸载。过去我们在Unix
下常利用类似技术进行Kernel Hacking,今天我来学习如何在Windows下做同样的事。
拣空看了三本书([1]、[2]、[3])的个别章节,感觉举步维艰,想说"Hello World"不
容易。
我安装了EWindows XP SP1、VC 7、Windows DDK 2600.1106、ActivePerl 5.6.1、
Compuware SoftICE Release 2.7、VMware Workstation 3.2,以方便此次学习过程。
如果你碰巧也有类似环境,并且也是此道初学者的话,后面的许多步骤将相当容易重
现。
下面是学习笔记。为了简捷起见,并没有时刻指明某项操作是在开发机还是在测试机
进行,但你务必清楚区分开发机、测试机上应该进行的操作。
☆ 编写hello.c文件
--------------------------------------------------------------------------
/*
* For x86/EWindows XP SP1 & VC 7 & Windows DDK 2600.1106
* build -cZ -x86
*/
/************************************************************************
* *
* Head File *
* *
************************************************************************/
#include <wdm.h>
/************************************************************************
* *
* Macro *
* *
************************************************************************/
#define PRIVATEDRIVERNAME "PRIVATE_HELLO_WORLD"
/************************************************************************
* *
* Function Prototype *
* *
************************************************************************/
/************************************************************************
* *
* Static Global Var *
* *
************************************************************************/
/************************************************************************/
/*
* DriverEntry is the first routine called after a driver is loaded, and
* is responsible for initializing the driver.
*
* you'll find a list of NTSTATUS status codes in the DDK header
* ntstatus.h (/WINDDK/2600.1106/inc/ddk/wxp/)
*/
NTSTATUS DriverEntry ( IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
CHAR privatedrivername[] = PRIVATEDRIVERNAME;
/*
* 这是无效的用户空间地址
*/
PVOID p = ( PVOID )1;
/*
* kernel-mode functions and the functions in your driver use the
* __stdcall calling convention when compiled for an x86 computer.
* This shouldn't affect any of your programming, but it's something
* to bear in mind when you're debugging
*/
/*
* This routine is defined in ntddk.h, wdm.h, and ndis.h.
* A call to this macro requires double parentheses.
*/
KdPrint(( "%s - Entering DriverEntry()/n", privatedrivername ));
__try
{
KdPrint(( "%s - You should see this message[1]/n", privatedrivername ));
/*
* 由于1未对齐在4字节边界上,引发SYSTEM_DATATYPE_MISALIGNMENT异常。
* Do not use this routine on kernel-mode addresses.
*/
ProbeForWrite( p, 4, 4 );
KdPrint(( "%s - You shouldn't see this message[1]/n", privatedrivername ));
}
__except ( EXCEPTION_EXECUTE_HANDLER )
{
KdPrint(( "%s - __except{}/n", privatedrivername ));
}
KdPrint(( "%s - Kept control after exception/n", privatedrivername ));
__try
{
KdPrint(( "%s - You should see this message[2]/n", privatedrivername ));
__leave;
KdPrint(( "%s - You shouldn't see this message[2]/n", privatedrivername ));
}
__finally
{
KdPrint(( "%s - __finally{}/n", privatedrivername ));
}
KdPrint(( "%s - Exiting DriverEntry()/n", privatedrivername ));
/*
* 故意失败返回
*/
return( STATUS_UNSUCCESSFUL );
} /* end of DriverEntry */
/************************************************************************/
--------------------------------------------------------------------------
用户空间编程,main()、WinMain()是总入口点。与之类似,DriverEntry()是驱动程
序总入口点,它的两个形参对于目前阶段的我来说并不重要。其最后故意失败返回,
使我可以不考虑绝大多数复杂情况,而专注于如何编译驱动程序、加载驱动程序,观
察驱动程序调试输出信息。同样的技巧在Unix系统使用过。
与用户空间的结构化异常处理(SEH)相比,内核空间的SEH主要致力于捕捉内核代码访
问无效用户空间地址产生的异常,它无法捕捉除以零、内核代码访问无效内核空间地
址产生的异常。
hello.c中由于1未对齐在4字节边界上,ProbeForWrite( p, 4, 4 )引发相应异常。
SEH机制使程序继续保持控制权。对于__try{}/__finally{},若因return、continue、
break、goto等语句提前离开__try{},将导致一次开销可观的"局部展开"。__leave
语句用于避免不必要的"局部展开"。
KdPrint(())的用法与printf()类似,注意调用该宏时必须指定两层圆括号。
☆ 编写dirs文件
与用户空间编程不同,只有hello.c不足以产生hello.sys,至少还需要三个文件:
dirs、sources、makefile
DDK文档"Running the Build Utility"小节对此有详细解释。build根据dirs文件遍
历目录树,在子目录中发现dirs时继续遍历,发现sources时build开始为调用nmake
做准备。nmake使用makefile,最终调用cl进行真正的编译。
假设将来的目录/文件布局是这样的:
hello/ --+-- dirs
|
+-- code/ --+-- hello.c
|
+-- sources
|
+-- makefile
这里只列举了手工创建的目录/文件,不包括编译过程产生的目录/文件。
此时dirs文件内容很简单,就一行:
--------------------------------------------------------------------------
DIRS=code
--------------------------------------------------------------------------
☆ 编写sources文件
--------------------------------------------------------------------------
#
# Use the TARGETNAME macro to specify the name of the library to be built.
# Do not include the file name extension
#
TARGETNAME=hello
#
# All build products (such as .exe, .dll, and .lib files) will be placed
# in this directory
#
TARGETPATH=obj
#
# Use the TARGETTYPE macro to specify the type of product being built.
# TARGETTYPE gives the Build utility clues about some of the input files
# that it should expect. You must include this macro in your sources file.
#
TARGETTYPE=DRIVER
#
# Use the USE_PDB macro if your debug symbolic files will use a VC4 PDB.
# This is the default in the Windows XP build environment.
#
USE_PDB=1
#
# Use the INCLUDES macro to indicate the location of the headers to be
# included in your build
#
INCLUDES=
#
# Use the MSC_WARNING_LEVEL macro to set the warning level to use on the
# compiler. The default is /W3.
#
# After your code builds without errors, you might want to change
# MSC_WARNING_LEVEL to /W3 /WX. Setting this value causes warnings to show
# as errors.
#
MSC_WARNING_LEVEL=-W3 -WX
#
# The SOURCES macro specifies the files to be compiled. The SOURCES macro
# is required by the Build utility. This macro must be placed in your
# sources file. All files specified by this macro must reside in the
# directory containing the sources file.
#
SOURCES=hello.c
--------------------------------------------------------------------------
必要的解释我都放在sources文件里了。单独多解释一下TARGETPATH,BUILD_ALT_DIR
的值会被追加在TARGETPATH之后。假设进入了"Win XP Checked Build Environment":
> set BUILD_ALT_DIR
BUILD_ALT_DIR=chk_wxp_x86
此时在hello/下执行build -cZ -x86,产生的目录/文件布局如下:
hello/ --+-- buildchk_wxp_x86.log
|
+-- dirs
|
+-- code/ --+-- hello.c
|
+-- hello.inf
|
+-- sources
|
+-- makefile
|
+-- objchk_wxp_x86/ --+-- _objects.mac
|
+-- i386/ --+-- hello.sys
|
+-- hello.obj
|
+-- hello.pdb
如果你嫌BUILD_ALT_DIR对于目前阶段太碍眼,可以删除该环境变量:
> set BUILD_ALT_DIR=
此时在hello/下执行build -cZ -x86,产生的目录/文件布局如下:
hello/ --+-- build.log
|
+-- dirs
|
+-- code/ --+-- hello.c
|
+-- hello.inf
|
+-- sources
|
+-- makefile
|
+-- obj/ --+-- _objects.mac
|
+-- i386/ --+-- hello.sys
|
+-- hello.obj
|
+-- hello.pdb
☆ 编写makefile文件
--------------------------------------------------------------------------
!INCLUDE $(NTMAKEENV)/makefile.def
--------------------------------------------------------------------------
J:/source/driver/hello> set NTMAKEENV
NTMAKEENV=J:/WINDDK/2600~1.110/bin
☆ 编译产生hello.sys文件
在dirs文件所在目录里执行"build -cZ -x86":
J:/source/driver/hello> build -cZ -x86
BUILD: Adding /Y to COPYCMD so xcopy ops won't hang.
BUILD: Compile and Link for i386
BUILD: Examining j:/source/driver/hello directory tree for files to compile.
BUILD: Compiling j:/source/driver/hello/code directory
Compiling - code/hello.c for i386
BUILD: Linking j:/source/driver/hello/code directory
Linking Executable - code/obj/i386/hello.sys for i386
BUILD: Done
2 files compiled
1 executable built
J:/source/driver/hello>
☆ 编写hello.inf文件
; ------------------------------------------------------------------------
;
; Copyright to satisfy the CHKINF utility
;
[Version]
Signature = "$Windows NT$"
Class = %ClassName%
;
; For a new device setup class, the INF must specify a newly generated
; ClassGuid value
;
; 用/WINDDK/2600.1106/tools/other/i386/guidgen.exe生成
;
ClassGuid = {EABDB9DF-F09D-44ba-81E5-551C2ABC1FA9}
Provider = %INFCreator%
DriverVer = 06/10/2003,1.00.1993.9
; ------------------------------------------------------------------------
[ClassInstall32.ntx86]
AddReg = ClassInstall32Reg
[ClassInstall32Reg]
HKR,,,,%ClassName%
; ------------------------------------------------------------------------
[Manufacturer]
%INFCreator% = HelloWorldSection
; ------------------------------------------------------------------------
[HelloWorldSection]
%DESCRIPTION% = DDInstall,*HWD1993
; ------------------------------------------------------------------------
[SourceDisksNames.x86]
1 = %DiskDescription%,,,
[SourceDisksFiles.x86]
hello.sys = 1
[DestinationDirs]
DefaultDestDir = 10,system32/drivers
FileList = 10,system32/drivers
; ------------------------------------------------------------------------
[DDInstall.ntx86]
Copyfiles = FileList
[FileList]
hello.sys,,,0x00000002
; ------------------------------------------------------------------------
[DDInstall.ntx86.Services]
AddService = HelloWorld,0x00000002,ServiceInstall
[ServiceInstall]
DisplayName = %FriendlyName% ; friendly name
ServiceType = 0x00000001 ; SERVICE_KERNEL_DRIVER
StartType = 0x3 ; SERVICE_DEMAND_START
ErrorControl = 0x1 ; SERVICE_ERROR_NORMAL
ServiceBinary = %10%/system32/drivers/hello.sys
; ------------------------------------------------------------------------
[DDInstall.ntx86.HW]
AddReg = DDInstallRegHW
[DDInstallRegHW]
HKR,,HelloWorldInfo,,%DESCRIPTION%
; ------------------------------------------------------------------------
[Strings]
ClassName = "HelloWorldClass"
INFCreator = "The Hello World Software"
DESCRIPTION = "The Hello World Driver"
DiskDescription = "The Hello World Software Disk"
FriendlyName = "Hello World"
; ------------------------------------------------------------------------
DDK文档详细解释了如何编写INF文件。不过个人觉得DDK文档适合在阅读一份现成的
INF文件时当作手册查看。如果妄图在没有样板INF文件的情况下通过查看DDK文档来
从头写一份新INF文件,至少初学者不要有这样的念头。为了写这么点破烂,我费劲
坏了。
用/WINDDK/2600.1106/tools/other/i386/guidgen.exe生成ClassGuid。
执行如下命令对hello.inf文件提前进行一些检查:
/WINDDK/2600.1106/tools/chkinf> chkinf.bat hello.inf
在/WINDDK/2600.1106/tools/chkinf/htm/目录里生成分析报告:
--------------------------------------------------------------------------
Line 7: (E22.1.1081) Directive: CatalogFile required (and must not be blank) in section [Version] for WHQL digital signature.
Line 9: (E22.1.1310) Class HelloWorldClass (ClassGUID {EABDB9DF-F09D-44ba-81E5-551C2ABC1FA9}) is unrecognized.
--------------------------------------------------------------------------
第一个错误因为我没有指定"CatalogFile.ntx86 = ...",目前阶段也没法指定。第
二个错误因为ClassGuid是新创建的。
刚开始写hello.inf文件时,分析报告里还有不少错误、警告信息。应该在某注释行
中包含"Copyright"单词,否则分析报告里有"No Copyright information found."警
告信息。
知道为什么要安装ActivePerl 5.6.1么,chkinf.bat需要Perl解释器的支持!
Walter Oney的光盘([1])需要安装,他的安装过程会在这里增加相关内容:
HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Class
不清楚他这么做的好处何在,说实话,挺烦这手的。不喜欢安装这些人提供的随书光
盘,它们使我丧失了深入了解问题本质的机会,这也是我没有安装DriverStudio中其
它开发工具的原因。由于源代码已经在那里,我没有执行setup.exe,只是直接编译
并试图安装其中的某些例子程序:
> fastinst.exe xxx.inf
结果得到一个对话框式的错误提示,ERROR_SECTION_NOTFOUND。setupapi.log中看到:
--------------------------------------------------------------------------
找不到 [ClassInstall32] 段。
--------------------------------------------------------------------------
chkinf.bat xxx.inf的分析报告里有相应警告信息:
--------------------------------------------------------------------------
Custom defined Classes should have a [ClassInstall32] section.
--------------------------------------------------------------------------
最初的hello.inf没有下面这部分内容,自然会遇上同样的问题:
--------------------------------------------------------------------------
[ClassInstall32.ntx86]
AddReg = ClassInstall32Reg
[ClassInstall32Reg]
HKR,,,,%ClassName%
--------------------------------------------------------------------------
此外,注意这一节:
--------------------------------------------------------------------------
[DDInstall.ntx86]
Copyfiles = FileList
--------------------------------------------------------------------------
刚开始多根据DDK文档写成"CopyFiles = ...",结果在/windows/setupapi.log中看
到:
--------------------------------------------------------------------------
在 "hello.inf" 的 [FileList] 段分析 "Copyfiles" 失败。 错误 0xe0000102: 在 INF 中找不到所需的行。
--------------------------------------------------------------------------
这个错误导致hello.sys未被复制到/windows/system32/drivers/目录下。按大小写
敏感方式修改成现在使用的样子就解决了。如果用"fastinst.exe hello.inf"进行安
装,不会遇到该问题,我怀疑这是MS的一个小BUG。
经验就是,安装过程出了问题先看setupapi.log文件。
顺便提一下,DDK提供了GenInf工具,这是一个垃圾工具,即使对初学者也如此。测
试使用了一次,强烈建议大家当它不存在。Art Baker委婉地表述了类似观点([3])。
☆ 安装hello.inf文件
Walter Oney的fastinst.exe果然便捷,不过个人建议在试图了解更多细节的时候还
是少依赖它为妙。
控制面板->添加硬件->是,硬件已联接好->添加新的硬件设备->
安装我手动从列表选择的硬件(高级)->显示所有设备->从磁盘安装->完成
由于hello.c最后故意失败返回,安装虽然完成,但加载驱动必然失败。在设备管理
器中可以看到黄色惊叹号,表示无法成功加载驱动程序。
这次安装过程导致如下一些动作:
1)
--------------------------------------------------------------------------
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Class/{EABDB9DF-F09D-44BA-81E5-551C2ABC1FA9}]
"Class"="HelloWorldClass"
@="HelloWorldClass"
[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Class/{EABDB9DF-F09D-44BA-81E5-551C2ABC1FA9}/0000]
"InfPath"="oem5.inf"
"InfSection"="DDInstall"
"InfSectionExt"=".NTx86"
"ProviderName"="The Hello World Software"
"DriverDateData"=hex:00,40,43,3c,e3,2e,c3,01
"DriverDate"="6-10-2003"
"DriverVersion"="1.0.1993.9"
"MatchingDeviceId"="*hwd1993"
"DriverDesc"="The Hello World Driver"
--------------------------------------------------------------------------
2)
--------------------------------------------------------------------------
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Enum/Root/UNKNOWN]
[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Enum/Root/UNKNOWN/0000]
"ClassGUID"="{EABDB9DF-F09D-44BA-81E5-551C2ABC1FA9}"
"ConfigFlags"=dword:00000004
"Driver"="{EABDB9DF-F09D-44BA-81E5-551C2ABC1FA9}//0000"
"Class"="HelloWorldClass"
"Mfg"="The Hello World Software"
"HardwareID"=hex(7):2a,00,68,00,77,00,64,00,31,00,39,00,39,00,33,00,00,00,00,/
00
"Service"="HelloWorld"
"DeviceDesc"="The Hello World Driver"
"Capabilities"=dword:00000000
[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Enum/Root/UNKNOWN/0000/Device Parameters]
"HelloWorldInfo"="The Hello World Driver"
[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Enum/Root/UNKNOWN/0000/LogConf]
[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Enum/Root/UNKNOWN/0000/Control]
--------------------------------------------------------------------------
3)
--------------------------------------------------------------------------
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/HelloWorld]
"Type"=dword:00000001
"Start"=dword:00000003
"ErrorControl"=dword:00000001
"ImagePath"=hex(2):73,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,64,00,/
72,00,69,00,76,00,65,00,72,00,73,00,5c,00,68,00,65,00,6c,00,6c,00,6f,00,2e,/
00,73,00,79,00,73,00,00,00
"DisplayName"="Hello World"
[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/HelloWorld/Security]
"Security"=hex:01,00,14,80,90,00,00,00,9c,00,00,00,14,00,00,00,30,00,00,00,02,/
00,1c,00,01,00,00,00,02,80,14,00,ff,01,0f,00,01,01,00,00,00,00,00,01,00,00,/
00,00,02,00,60,00,04,00,00,00,00,00,14,00,fd,01,02,00,01,01,00,00,00,00,00,/
05,12,00,00,00,00,00,18,00,ff,01,0f,00,01,02,00,00,00,00,00,05,20,00,00,00,/
20,02,00,00,00,00,14,00,8d,01,02,00,01,01,00,00,00,00,00,05,0b,00,00,00,00,/
00,18,00,fd,01,02,00,01,02,00,00,00,00,00,05,20,00,00,00,23,02,00,00,01,01,/
00,00,00,00,00,05,12,00,00,00,01,01,00,00,00,00,00,05,12,00,00,00
[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/HelloWorld/Enum]
"0"="ROOT//UNKNOWN//0000"
"Count"=dword:00000001
"NextInstance"=dword:00000001
"INITSTARTFAILED"=dword:00000001
--------------------------------------------------------------------------
4) 复制hello.sys到/windows/system32/drivers/目录下。
在setupapi.log中可以看到如下内容:
--------------------------------------------------------------------------
[2003/06/11 14:06:31 1780.404]
#-198 处理的命令行: "/system32/rundll32.exe" shell32.dll,Control_RunDLL "/system32/hdwwiz.cpl",添加硬件
#I140 正在安装设备类别: "HelloWorldClass" {EABDB9DF-F09D-44ba-81E5-551C2ABC1FA9}。
#I141 类别安装已结束,没有出错。
[2003/06/11 14:06:32 1780.407 Driver Install]
#-124 正在做“仅复制”安装 "ROOT/UNKNOWN/0000"。
#-198 处理的命令行: "/system32/rundll32.exe" shell32.dll,Control_RunDLL "/system32/hdwwiz.cpl",添加硬件
#E360 驱动程序 "The Hello World Driver" 的一个未经过签署或签署不正确的文件 "hello.inf" 将得到安装(策略=忽略)。 错误 0xe000022f: 第三方 INF 不包含数字签名信息。
#-024 正在将文件 "hello.sys" 复制到 "/system32/drivers/hello.sys"。
#E360 驱动程序 "The Hello World Driver" 的一个未经过签署或签署不正确的文件 "hello.inf" 将得到安装(策略=忽略)。 错误 0xe000022f: 第三方 INF 不包含数字签名信息。
#-166 设备安装函数: DIF_REGISTER_COINSTALLERS。
#I056 注册了共同安装程序。
#-166 设备安装函数: DIF_INSTALLINTERFACES。
#-011 正在从 "hello.inf" 安装段 [DDInstall.NTx86.Interfaces]。
#I054 安装接口。
#-166 设备安装函数: DIF_INSTALLDEVICE。
#I123 进行 "ROOT/UNKNOWN/0000" 的完整安装。
#E360 驱动程序 "The Hello World Driver" 的一个未经过签署或签署不正确的文件 "hello.inf" 将得到安装(策略=忽略)。 错误 0xe000022f: 第三方 INF 不包含数字签名信息。
#I163 设备未开始: 设备有问题: 0x25: CM_PROB_FAILED_DRIVER_ENTRY.
#I121 "ROOT/UNKNOWN/0000" 的设备安装成功完成。
--------------------------------------------------------------------------
如果在资源管理器中右键选中hello.inf,点击菜单里的"安装",不知为何,毫无动
静。注册表、drivers目录、setupapi.log均无变化,活见鬼了。目前我还不懂这里
的窍道,以后再来理解。
HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet只是到ControlSet<nnn>的符号链接,
HKEY_LOCAL_MACHINE/SYSTEM/Select用于具体确定是到谁的符号链接。启动时F8菜单
有一个选项对应最近一次成功引导所用设置,就是由LastKnownGood决定的。参看[4]
的5.2.6小节。
☆ 卸载hello.sys及相关设置
1)
手工卸载很简单,在注册表中删除上述三处内容,在drivers目录中删除hello.sys。
2)
也可以执行"sc delete HelloWorld":
> sc delete HelloWorld
[SC] DeleteService SUCCESS
设备管理器中倒是看不到相应显示了。注册表中残留了一点内容:
--------------------------------------------------------------------------
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Class/{EABDB9DF-F09D-44BA-81E5-551C2ABC1FA9}]
"Class"="HelloWorldClass"
@="HelloWorldClass"
--------------------------------------------------------------------------
并且drivers/hello.sys也未删除。
3)
还有一种方式,通过设备管理器卸载,比"sc delete HelloWorld"干得活还要少些,
注册表中"HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/HelloWorld"
还在。
个人建议用第二种方式,结合一些手动操作。
这样仔细地手工折腾一趟之后,想必对驱动的安装/卸载有了初步认识吧。反正我是
感觉学到不少东西。
☆ 察看KdPrint输出
从Unix转过来的兄弟们不要幻想有uprintf()这样的内核函数可用。只有类似Linux下
printk()的KdPrint输出。有很多办法察看这个输出,这次我用DebugView([5])。在
Capture菜单里勾中Capture kernel、Pass-Through、Capture Events即可。扔到一
边别理它。
添加硬件过程最终会尝试加载hello.sys,DriverEntry()被调用,在DebugView中可
以看到KdPrint输出,确认SEH起作用了。
安装结束后如想再次进入DriverEntry(),可以执行"net start HelloWorld"。
☆ 使用DriverMonitor
Compuware DriverStudio Release 2.7中提供了DriverMonitor。在File菜单里选择
"Open Driver"打开hello.sys,选择"Start Driver"调用DriverEntry(),直接看到
KdPrint输出信息。如果同时启动了DebugView,两边都可看到,此时可以顺带加强对
Pass-Through设置的理解。
好处在于不必编写hello.inf就可测试hello.sys。"Open Driver"时会临时在注册表
中设置一些内容:
--------------------------------------------------------------------------
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/Hello]
"Type"=dword:00000001
"Start"=dword:00000003
"ErrorControl"=dword:00000001
"ImagePath"=hex(2):5c,00,3f,00,3f,00,5c,00,63,00,3a,00,5c,00,6f,00,6e,00,6c,00,/
79,00,74,00,65,00,6d,00,70,00,5c,00,68,00,65,00,6c,00,6c,00,6f,00,5c,00,68,/
00,65,00,6c,00,6c,00,6f,00,2e,00,73,00,79,00,73,00,00,00
"DisplayName"="Hello"
[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/Hello/Security]
"Security"=hex:01,00,14,80,90,00,00,00,9c,00,00,00,14,00,00,00,30,00,00,00,02,/
00,1c,00,01,00,00,00,02,80,14,00,ff,01,0f,00,01,01,00,00,00,00,00,01,00,00,/
00,00,02,00,60,00,04,00,00,00,00,00,14,00,fd,01,02,00,01,01,00,00,00,00,00,/
05,12,00,00,00,00,00,18,00,ff,01,0f,00,01,02,00,00,00,00,00,05,20,00,00,00,/
20,02,00,00,00,00,14,00,8d,01,02,00,01,01,00,00,00,00,00,05,0b,00,00,00,00,/
00,18,00,fd,01,02,00,01,02,00,00,00,00,00,05,20,00,00,00,23,02,00,00,01,01,/
00,00,00,00,00,05,12,00,00,00,01,01,00,00,00,00,00,05,12,00,00,00
[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/Hello/Enum]
"Count"=dword:00000000
"NextInstance"=dword:00000000
"INITSTARTFAILED"=dword:00000001
--------------------------------------------------------------------------
因此可以"net start Hello"激发KdPrint输出。在File菜单里选择"Remove Service
Entry"将删除上述内容,退出DriverMonitor前应该执行该操作。
DriverMonitor不会做其它操作,比如不会复制hello.sys到drivers目录下,也不影
响设备管理器。
好,我这次目的达到了,现在对编译、安装、卸载Windows驱动有了感性认识,顺带
学习了一些工具的使用,希望对你也有所帮助。下次就不知道什么时候开始第三次学
习了,正经工作是编写扫描器插件以及Unix漏洞跟踪分析,想学点Windows不容易,
还好不是太苦闷。
☆ 参考资源
[ 1] <<Programming the Microsoft Windows Driver Model>> - Walter Oney
[ 2] <<Windows NT Device Driver Development>> - P. Viscarola, W. Mason
[ 3] <<The Windows 2000 Device Driver Book, Second Edition>> - Art Baker, Jerry Lozano
[ 4] <<Inside Microsoft Windows 2000 Third Edition>> - David A. Solomon, Mark E. Russinovich
[ 5] DebugView
http://www.sysinternals.com
☆─────────────────────────────────────☆
cygwin (梦醒⊙崇尚暴力) 于 (Wed Jun 11 17:01:07 2003) 提到:
【 在 soycola (酱油可乐) 的大作中提到: 】
: 标 题: Re: 学习写一个Hello World驱动
: 发信站: BBS 水木清华站 (Wed Jun 11 16:15:09 2003), 转信
:
: 这个是wdm版的hello world,这个过程掩盖了很多实质问题。
:
: 我的理解wdm为了支持设备的即插即用引入了复杂的驱动安装
: 过程,即必须编写inf文件并使用新设备向导,反观nt驱动,
: 只要调用几个service control manager的api就可以完成安装,
: 究其本质原因,应当是nt4的driver-centered的驱动模型和
: win 2000的device centered驱动模型之间的区别。nt4的驱动
: 模型说白了就是linux采用的模型,nt4的net start就是linux的
: 的insmod,nt4的net stop就是linux的rmmod。当然nt4在执行
: net start之前必须执行一个轻量级的安装工作(主要是createservice
: ),而这个createservice的过程在linux下面只是将驱动的.o
: 文件拷贝到相关路径中即可(我自己的理解,请小四兄指正)。
: 当然nt4的这个‘服务式’驱动模型和linux的驱动模型也有区别,
: nt4中的服务可以是用户态的,换句话说,nt4的服务约等于
: linux的核心模块+linux的daemon程序,而wdm驱动则约等于
: nt4核心态驱动+pnp支持+电源管理支持。
你所说的nt4方案也可以2k下用啊
只要打开service manager
加入服务,启动服务
就搞定了
:
: 所以,如果说nt4的驱动模式更接近于linux,则那些ms fans不妨可以
: 认为windows的wdm比linux先进。
:
: btw,对于小四兄的应用,我想大部分情况下应该只是一个nt4核心
: 态驱动就够了,不需要wdm支持。对这种程序,写一个hello
: world其实更简单。我一会儿转一个过来大家审查一下。
: 【 在 hellguard (小四★北渡北汉江⊙) 的大作中提到: 】
: : 学习笔记,没有技术含量,高手勿Ctrl-F了
: : 日期: 2003-06-10 21:50
: : 更新:
: : --------------------------------------------------------------------------
: : 目录:
: : ☆ 概述
: : ☆ 编写hello.c文件
: : ☆ 编写dirs文件
: : ☆ 编写sources文件
: : ☆ 编写makefile文件
: : ☆ 编译产生hello.sys文件
: : ...................
:
: --
:
: ※ 来源:·BBS 水木清华站 smth.org·[FROM: 61.51.240.205]
☆─────────────────────────────────────☆
cygwin (梦醒⊙崇尚暴力) 于 (Wed Jun 11 17:12:01 2003) 提到:
这我就不懂了
filemon的那个驱动不是wdm的?
【 在 soycola (酱油可乐) 的大作中提到: 】
: wdm驱动这样做是不行的,嘿嘿,wdm驱动都是按需加载的,有设备才
: 加载(所以才能实现pnp),所以它那个StartupType统统是3:demand_start
: ,除了一些启动时需要加载的驱动以外。2k为了兼容nt,wdm驱动仍然
: 保留了服务这个概念,但是由于我在上面说的原因,我们应当认识到
: 服务这个driver center的东西本质上和wdm这种device centered的架构
: 是不甚融洽的。
☆─────────────────────────────────────☆
cygwin (梦醒⊙崇尚暴力) 于 (Wed Jun 11 17:21:35 2003) 提到:
我只写过一回驱动
所以对这些了解不多
刚才在driverdev找kmd,
发现只有一篇文章,还是提问的
驱动除了vxd(win9x),wdm,kmd还有没有其它类型?
而wdm与kmd又有何居别?
【 在 soycola (酱油可乐) 的大作中提到: 】
: 小四所说‘想说hello不容易’是因为kmd的驱动编译环境实在
: 复杂,相信每个写过驱动的人都有体会,至于安装复杂还在其次。
: 我回的帖子主要是两个意思,1是可以用那个极简单的makefile解决
: 编译复杂的问题(ddk的那个build程序是微软自己用来编译win2k
: 的,所以考虑了很多细节,至于我们用它则属于牛刀宰鸡),2是
: 可以回避复杂的安装,直接用nt4的那个方案,因为小四用的程序
: 估计只是一个KMD。
反正我知道它的这个程序肯定可以用nt4的那种方式加载。
☆─────────────────────────────────────☆
hellguard (小四★北渡北汉江⊙) 于 (Wed Jun 11 17:46:17 2003) 提到:
【 在 soycola (酱油可乐) 的大作中提到: 】
> 我想大部分情况下应该只是一个nt4核心
> 态驱动就够了,不需要wdm支持。对这种程序,写一个hello
> world其实更简单。我一会儿转一个过来大家审查一下。
这个我明白,的确是不需要WDM,不过是顺手逮着学学。那我就等着学
你那个例子啦。主要是市面上的书直奔硬件而去,我想找个Hello World
而不得,只好自己瞎折腾一回,见笑见笑。
Linux的驱动模型我并不熟悉更多,只是从前写过LLKM而已。我所
接触的FKLD、SLKM都是伪设备驱动,真要讨论涉及物理的驱动,我
一点经验都没有的。
☆─────────────────────────────────────☆
hellguard (小四★北渡北汉江⊙) 于 (Wed Jun 11 17:47:57 2003) 提到:
好,多谢,我回头学学
【 在 soycola (酱油可乐) 的大作中提到: 】
: 诺,就是这个,很久以前在driverdev贴的,自己挺臭美的所以就转过来了呵呵。
: /*++
: hello.c
: --*/
: #define _X86_
: #include <ddk/ntddk.h>
: #pragma comment(linker, "/entry:DriverEntry /subsystem:native /base:0x10000 /driver")
: #pragma comment(lib, "wdm.lib")
: VOID _stdcall Unload(IN PDRIVER_OBJECT DriverObject)
: {
: DbgPrint("Bye bye!/n");
: ...................
☆─────────────────────────────────────☆
hellguard (小四★北渡北汉江⊙) 于 (Wed Jun 11 17:56:00 2003) 提到:
发现听你讲这些挺省事的啊,虽然不搞这些东西,听你讲讲
也有收获,
上次你们提到
A New Interface for Driver Writing -- The Windows Driver Framework
在OSR主站上有这篇,
http://www.osronline.com/article.cfm?id=212
我转在Driver版了,已经换行处理过
【 在 soycola (酱油可乐) 的大作中提到: 】
: 98就不说了。只说wdm和kmd,我能想到的最精确的描述就是:
: KMD(kernel mode driver)是‘驱动程序为中心’驱动架构
: 下的产物WDM驱动是设备中心的驱动架构下的产物。不过这么
: 说可能过于概括。在KMD时代,驱动程序处于主导地位,发现
: 并枚举总线和设备、找到或分配设备的资源占用情况、创建
: 设备对象并提供环境子系统可以访问的符号链接等,都是驱动
: 程序的工作。驱动告诉os说这里有个设备,驱动告诉os说这个
: 设备的io、mem、dma、irq,驱动创建一个设备对象然后扔给os说
: 给你个设备,然后os才知道有个设备;
: 而在WDM时代就不一样了,设备翻身做了主人,在总线驱动和控
: 制器驱动(注1)的帮助下,os自己就知道当前计算机上链接有哪些设
: ...................
☆─────────────────────────────────────☆
netfun (netfun) 于 (Tue Jun 17 15:41:30 2003) 提到:
WDM是Microsoft为了统一9x系列与NT系列而引入的驱动模型,实际上pnp与power只是
她的两个需求而已,这可以从Windows Driver Model的命名可以看到。
在NT系列中WDM构建于NT Legacy KMD(Kernel Mode Driver NT4)的基础上,并不是不
甚融洽的。而正是由于PNP与Power的引入才使Driver的安装发生了根本的变革,使其复杂
的多,但是pnp driver的安装仍是基于最基本的services的概念,正是由于安装的复杂,
microsoft引入了setupapi.dll用于这部分任务,而setupapi.dll则是对services的封
装,当然实际上整个过程是非常复杂的,从内核态引入root bus(/driver/pnpmanager
这是一个ntoskrnl.exe buildin driver)到device node等等。这一切的基础都是KMD。
Microsoft并没有鄙弃KMD,WDM是KMD发展而来的。
【 在 soycola (酱油可乐) 的大作中提到: 】
: wdm驱动这样做是不行的,嘿嘿,wdm驱动都是按需加载的,有设备才
: 加载(所以才能实现pnp),所以它那个StartupType统统是3:demand_start
: ,除了一些启动时需要加载的驱动以外。2k为了兼容nt,wdm驱动仍然
: 保留了服务这个概念,但是由于我在上面说的原因,我们应当认识到
: 服务这个driver center的东西本质上和wdm这种device centered的架构
: 是不甚融洽的。
本文转自
http://smth.edu.cn/bbsanc.php?path=%2Fgroups%2Fcomp.faq%2FMSDN%2Fdiscuss%2FM.1101432861.80