初始化与卸载例程

编写一个DriverEntry例程

运行的上下文环境

  再加载驱动程序的时候I/o管理器调用DriverEntry例程。DriverEntry例程运行的IRQL是PASSIVE_LEVEL,这意味着它有权访问分页的存储器资源。

  DriverEntry例程收到一个指向它自己的驱动程序对象的指针,这个指针必须初始化。它也收到一个包含注册表中驱动程序的服务键的UNICODE_STRING结构。WDM驱动程序中很少使用这个这注册名,内核模式的驱动程序依赖这个字符串去取出在系统注册表中存储的驱动程序特定的参数。这个注册的字符串的形式大概是HKEY_LOCAL_MACHINE/System/CurrentControlSet/Services/ DriverName

 

DriverEntry例程的作用

 

  虽然WDM和内核模式的驱动程序有些不同,但大体上一个DriverEntry例程的执行步骤如下:

1. DriverEntry例程查找它所控制的硬件,被分配的硬件被标识它在本驱动程序的控制之下。

2. 用指向其它驱动程序例程入口点的指针初始化来初始化驱动程序对象。

3. 如果驱动程序管理一个多功能的控制器,使用IoCreateController去创建一个控制器对象,然后初始化控制器的extension。

4. 使用IoCreateDevice去为每一个它控制的物理的或者逻辑的设备创建一个设备对象,然后初始化设备extension。

5. 通过IoCreateSymbolicLink函数使这个设备可以被Win32子系统看见。

6. 将设备与一个中断对象联系起来,如果ISR需要使用DPC对象,就在这一步创建和初始化它们。

7. 重复第4步到第6步,直到完成这个驱动程序所有的物理的和逻辑的设备。

8. 如果成功DriverEntry例程应该返回STATUS_SUCCESS给I/O管理器。

DriverEntry例程参数
 意义
 
IN PDRIVER_OBJECT pDriverObject          驱动程序对象地址
 
IN PUNICODE_STRING pRegistryPath      驱动程序服务键的注册表路径字符串
 
Return value                                           STATUS_SUCCESS或者STATUS_XXX
 

表6.1 DriverEntry例程的参数

 

在WDM驱动程序中不执行步骤1和3到6,它们被放到AddDevice例程中了。如果DriverEntry例程因为某个

原因而使初始化的过程失败,就应该释放任何占用的资源,返回合适的NTSTATUS失败代码给I/O管理器。下面的部分将详细的介绍其中一些步骤,硬件的寻找与分配是复杂的,将在介绍硬件的初始化的时候再详细论。

 

宣布驱动程序例程入口点

  I/O管理器可以找到DriverEntry例程,因为它有一个公认的名字(实际上,连接器使用一个命令行开关声明DriverEntry的地址,然而,DDK文档要求入口点命名为DriverEntry),其它的驱动程序例程不需要固定的名字,因此,I/O管理器需要一些方法定位它们。连接机制是驱动程序对象,驱动程序对象包含指向其它驱动程序例程的指针。DriverEntry例程负责设置这些指针。

这些函数指针有两种:

1. 在驱动程序对象中有明确的名字的函数。

2. 在驱动程序的MajorFunction队列中列出的IRP派遣函数。

下列代码片段是初始化两种函数指针的例子:

pDO->DriverStartIo = StartIo;           

pDO->DriverUnload = Unload;

// Initialize the MajorFunction Dispatch table

pDO->MajorFunction[ IRP_ MJ_CREATE ] = DispatchCreate;

pDO->MajorFunction[ IRP_MJ_CLOSE ] = DispatchClose;            

... ...

 

创建设备对象

  一旦硬件被识别和分配后,下一步是为每一个物理的或者逻辑的设备创建一个设备对象,大量的工作被IoCreateDevice函数作了,它的出口参数是设备对象的句柄,包括一个相应的设备extension。这个函数还连接这个新的设备对象到这个驱动程序对象管理的设备列表中

     IoCreateDeviceDeviceType参数是一个16-bit的值,这个值描述了被添加的设备的种类,微软保留了前一半范围给了定义好的设备类型。剩下的32767个设备类型可以被定义,要小心定义不要与其它制造商的设备冲突。现在,微软预定义大约30种设备类型,这些预定义的类型值被赋予了象征性的名字,它的形式是FILE_DEVICE_XXX,例如,FILE_DEVICE_DVD

IoCreateDevice函数参数

意义

IN PDRIVER_OBJECT pDriverObject

指向设备对象的指针

IN ULONG DeviceExtensionSize

请求的DEVICE_EXTENSION结构的大小

IN PUNICODE_STRING pDeviceName

内部的设备名

IN DEVICE_TYPE DeviceType

FILE_DEVICE_XXX (参考NTDDK.h)

IN ULONG DeviceCharacteristics

大规模存储设备的特性FILE_REMOVABLE_MEDIA

FILE_READ_ONLY_DEVICE

IN BOOLEAN Exclusive

如果设备不可以共享时为真

OUT PDEVICE_OBJECT *pDeviceObject

接收设备对象指针的变量

Return value

STATUS_SUCCESS或者STATUS_XXX

6.2 IoCreateDevice函数参数

 

选择一种数据缓冲策略

  如果IoCreateDevice调用成功,必须通知I/O管理器这个设备是使用缓冲区I/O还是直接I/O通过设置设备对象的Flags域来完成这个任务。

DO_BUFFERED_IOI/O管理器来回的在用户空间和系统空间的缓冲区之间复制数据。

DO_DIRECT_IO。 I/O管理器在I/O请求期间锁定用户缓冲区到物理存储器,创建缓冲区中的页面的描述符列表。

介绍派遣例程的时候再介绍怎样使用者两种方法访问用户缓冲区。如果不设置它们,I/O管理器会假定设备访问用户缓冲区的时候不需要I/O管理器的帮助。

设备名

  在WIN2000中的设备可以有多个名字,IoCreateDevice函数指定的名字是Win2000执行部件识别设备的名字,这个内部的名字对于Win32用户模式的应用程序来说是隐藏的,为了暴露这个设备给Win32子系统,Win16子系统或者虚拟DOS环境,新的设备必须起一个符号连接名

这两种名字分别在对象管理器名字空间的不同部分,对象管理器为所有的被操作系统管理的资源维持一个名字的目录,内部的设备名存储在目录树的/Device下面,符号连接名则在/DosDevices下面,当使用IoCreateDevice函数的时候,必须提供整个的/Device名字,例如,"//Device//Minimal0"是一个适当的名字字符串。在C语言必须使用双反斜线,因为单反斜线于一些字符合起来有时表示特殊的意义,例如,”/n”,而双反斜线才表示一个反斜线字符。

6.1 对象管理器名字空间的内部的设备名和符号连接名

内部的设备名和符号连接名遵循不同的命名习惯, 内部的设备名通常比较长且总是以基于0的数字作为结束。例如,FloppyDisk0或者FloppyDisk1对于文件系统的符号连接名通常采用AZ的模式,其它设备常是以基于1的数字作为结束,例如,LPT1或者LPT2

使用IoCreateSymbolicLink创建一个符号连接名,这个函数需传递一个存在的设备名和一个新的符号连接名,它们都是UNICODE_STRING数据类型。

最后必须注意设备名的选择不是必须要驱动程序的选择。在WDM的世界中总线驱动程序,Class驱动程序和许多即插即用驱动过程定义它们自己的名字。非WDM设备必须为它们添加的设备提供它们自己独一无二的名字。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值