第1页通过设备接口打开设备详细步骤一、驱动程序1.驱动程序框架的创建(1)用VC建立一个新工程。在VCIDE环境中选择File|New,弹出New对话框。在对话框中,选择Project选项卡。在Project选项卡中,选择Win32Application。设置工程名为OpenGuid.如图1所示,单击OK,进入下一个对话框,在对话框中选择一个空的工程。如图2。图1图2(2).新建两个文件GuidOpen.h和GuidOpen.cpp.这两个文件的具体写法,详见程序编写。也可以直接添加现成的已经写好的文件,张帆这本书中,一般都是用的HelloWDM.h和HelloWDM.cpp.(3).增加新的编译版本,去掉Debug和Release版本。在Build|Configuration如图3和图4。第2页图3图4(4).修改工程属性。选择Project|Setting,在弹出的对话框中,选择General选项卡,将Intermediatefiles和Outputfiles改为MyDriver_Check,这个名字英语C/C++中,所设置的Fo和Fd后面的文件名相一致。如图5。第3页图5将C/C++选项卡中,原有的ProjectOptions内容全部删掉,换成一下内容。/nologo/Gz/MLd/W3/WX/Z7/Od/DWIN32=100/D_X86_=1/DWINVER=0x500/DDBG=1/FoMyDriver_Check//FdMyDriver_Check//FD/c其中:/nologo:表示不显示编译的版本信息/Gz:默认函数调用采用标准调用(_stdcall)/MLd/W3:采用第三级警告模式/WX:将警告信息转换为错误信息,最大程度保证代码可靠/Z7:用Z7模式产生调试信息?/Od:关闭调试模式,VC的调试命令不能调试内核下的程序/DWIN32=100/D_X86_=1/DWINVER=0x500/DDBG=1:定义4个宏(不知道为什么)/FoMyDriver_Check/:MyDriver_Check/为OutputDirectories中“创建”的文件夹,存放中间生成的目标代码路径/FdMyDriver_Check/:MyDriver_Check/为存放.PDB文件的文件夹/FD:生成文件依奈/c:只进行编译,不连接图6选择Link选项卡,将原有的ProjectOptions内容全部删除,替换成如下内容:wdm.lib/nologo/base:0x10000/stack:0x400000,0x1000/entry:DriverEntry/subsystem:console/incremental:no/pdb:MyDriver_Check/GuidOpen.pdb/debug/machine:I386/nodefaultlib/out:MyDriver_Check/GuiOpen.sys/pdbtype:sept/subsystem:native/driver/SECTION:INIT,D/IGNORE:4078其中:wdm.lib:链接WDM库/nologo:链接时不显示版本信息/base:0x10000:加载驱动时,设定加载到虚拟内存的地址/stack:0x400000,0x1000:设定函数使用堆栈的地址与大小第4页/entry:DriverEntry:入口函数的地址(为符合标准函数调用的)/subsystem:console:设置子系统/incremental:no:非递曾式链接/pdb:MyDriver_Check/GuidOpen.pdb:设置pdb文件的文件名为GuidOpen,保存于MyDriver_Check文件夹下面C/C++属性页中的设置一样。/debug:以Debug方式链接/machine:I386:产生代码为386兼容的平台下的/nodefaultlib:不使用默认的库/out:MyDriver_Check/GuidOpen.sys:输出2进制的代码的文件名,保存于MyDriver_Check文件夹下与C/C++属性页中的设置一样。/pdbtype:sept:设置pdb文件的类型/subsystem:native:子系统为内核系统/driver:编译驱动/SECTION:INIT,D:将INIT的段设置为可抛弃的/IGNORE:4078:忽略4078号警告错误图7(5).修改VC的lib目录和include目录。Tools-Options-Directories属性页下的Showdirectoriesfor切换到Includefie添加DDK的头文件(安装的ddk的目录文件夹)\Inc\w2k(ddk的目录文件夹)\Inc\ddk\wdm\w2k置于最上面添加库文件(安装的ddk的目录文件夹)\lib\w2k\i386置于最上面第5页2.驱动程序说明(1)重要驱动程序中重要的数据结构驱动对象(DRIVER_OBJECT)在驱动加载时被内核中的对象管理程序所创建,由内核中的I/O管理器负责加载。typedefstruct_DRIVER_OBJECT{CSHORTType;CSHORTSize;PDEVICE_OBJECTDeviceObject;ULONGFlags;PVOIDDriverStart;ULONGDriverSize;PVOIDDriverSection;PDRIVER_EXTENSIONDriverExtension;UNICODE_STRINGDriverName;PUNICODE_STRINGHardwareDatabase;PFAST_IO_DISPATCHFastIoDispatch;PDRIVER_INITIALIZEDriverInit;PDRIVER_STARTIODriverStartIo;PDRIVER_UNLOADDriverUnload;PDRIVER_DISPATCHMajorFunction[IRP_MJ_MAXIMUM_FUNCTION+1];}DRIVER_OBJECT;typedefstruct_DRIVER_OBJECT*PDRIVER_OBJECT;DeviceObject:每个驱动程序会有一个或多个设备对象。设备对象是由程序员自己创建的,而非操作系统完成,在驱动被卸载时,遍历每个设备对象,并将其删除。设备对象(DEVICE_OBJECT)typedefstruct_DEVICE_OBJECT{struct_DRIVER_OBJECT*DriverObject;struct_DEVICE_OBJECT*NextDevice;struct_DEVICE_OBJECT*AttachedDevice;struct_IRP*CurrentIrp;ULONGFlags;struct_DEVOBJ_EXTENSION*DeviceObjectExtension;......................}DEVICE_OBJECT;typedefstruct_DEVICE_OBJECT*PDEVICE_OBJECT;//ntndis设备扩展是由程序员制定内容和大小,由I/O管理器创建的,并且保存在非分页内存中。(2)WDM驱动程序基本结构,在WDM驱动程序中,完成一个设备操作,至少需要两个设备对象共同完成,一个是物理设备对象(PhysicalDeviceObject)PDO和功能设备对象(FunctionDeviceObject)FDO。第6页当PC插入一个设备时,PDO会自动创建。确切的说是由总线驱动创建的,PDO不能单独操作设备,需要配合FDO一起使用。系统会检测到新设备,要求安装驱动程序,需要安装的驱动程序指的就是WDM程序,此驱动程序负责创建FDO,并且附加到PDO上。(3)驱动程序分析头文件中,除了生命函数之外,还要定义一个设备扩展。typedefstruct_DEVICE_EXTENSION{PDEVICE_OBJECTfdo;PDEVICE_OBJECTNextStackDevice;UNICODE_STRINGinterfaceName;//设备接口}DEVICE_EXTENSION,*PDEVICE_EXTENSION;当驱动程序被加载时,首先进入DriverEntry函数。DriverEntry主要是对驱动程序进行初始化,它是由系统进程所调用的,在Windows中有个特殊的进程叫做系统进程,打开进程管理器,里面有一个名为System的进程就是系统进程。系统进程在系统启动的时候就被创建了。驱动加载时,系统进程启动新的线程,调用执行体组建中的对象管理器,创建一个驱动对象。这个驱动对象是一个DRIVER_OBJECT的结构体。另外,系统进程调用执行体组建中的配置管理器程序,查询词驱动程序对应的注册表项。DriverEntry函数由两个参数PDRIVER_OBJECTpDeriverObject是刚才被创建的驱动对象的指针,和PUNICODE_STRINGpRegistryPath,设备服务键的的键名字符串的指针。在这个函数中,主要是对系统进程创建的驱动对象进行初始化。DriverEntry函数中,它对驱动对象的初始化一般是对例程的设置,卸载例程,AddDevice和IRP派遣函数。具体代码如下:pDriverObject-DriverExtension-AddDevice=GuidOpenAddDevice;pDriverObject-MajorFunction[IRP_MJ_PNP]=GuidOpenPnp;pDriverObject-MajorFunction[IRP_MJ_DEVICE_CONTROL]=pDriverObject-MajorFunction[IRP_MJ_CREATE]=pDriverObject-MajorFunction[IRP_MJ_CLOSE]=pDriverObject-MajorFunction[IRP_MJ_READ]=pDriverObject-MajorFunction[IRP_MJ_WRITE]=GuidOpenDispatchRoutine;pDriverObject-DriverUnload=GuidOpenUnload;另外,设备服务键的键名有时候需要保存下来,因为这个字符串不是长期存在的,如果以后想使用这个UNICODE字符串,就必须先把它复制到安全的地方,这个字符串的内容一般是\REGISTRY\MACHINE\SYSTEM\ControlSet\Service\[服务名].DriverEntry的返回值是NTSTATUS,是被定义的为32位的无符号长整形。0~0X7FFFFFFF被认为是正确的。而0X80000000~0XFFFFFFFF被认为是错误的。接着驱动程序进入GuidOpenAddDevice例程。它的主要任务是创建设备对象(功能设备对象)并将其附加到PDO之上。它有两个参数PDRIVER_OBJECTDriverObject,驱动对象和PDEVICE_OBJECTPhysicalDeviceObject设备对象,就是底层总线驱动创建的PDO对象。第7页创建设备对象,用IoCreatDevice(INPDRIVER_OBJECTDriverObject,//系统创建的驱动对象INULONGDeviceExtensionSize,//程序员自己定义的(在头文件中)设备扩展的大小INPUNICODE_STRINGDeviceNameOPTIONAL,//设备名,可以为空,此时,I/O管理器会自动以一个数字作为该设备对象的名称INDEVICE_TYPEDeviceType,//设备类型INULONGDeviceCharacteristics,//对设备的进一步描述INBOOLEANExclusize,//是否一次只能进行一次IRP处理OUTPDEVICE_OBJECT*DeviceObject)//新创建的设备对象具体代码如下PDEV