这一章讨论了驱动程序包的文件集并讨论了驱动程序作为一个整体的事宜。此文档的其他部分讨论了对驱动程序文件内容的要求和指南。
这一章包括以下信息:
·2.1 驱动程序文件
·2.2 注册表中的驱动程序信息
·2.3 指定驱动程序装载顺序
·2.4 安装过滤器驱动程序
·2.5 为设备安装Null驱动程序
1.1 驱动程序文件
支持一个特定的设备的软件依赖于设备的种类和设备被使用的方式。典型情况下,厂商在驱动程序包中提供下面的软件以支持设备:
1.一个设备安装信息文件(INF文件)。
一个INF文件包含系统Setup组件使用的信息以安装支持设备的文件。当Setup安装驱动程序时,它拷贝这些文件到%windir%/inf目录中。这个文件是必须的。
更多的信息,参见第3章,建立一个INF文件。
1. 设备的一个或多个驱动程序。
一个.sys文件时驱动程序的映像文件。当驱动程序被安装时,Setup拷贝此文件到%windir%/system32/drivers目录中。对大多数设备,驱动程序是必须的;某些设备不需要驱动程序,比如原始能力的设备。
更多的信息,参见这一章的剩余部分和其他章节。
2. 驱动程序包的数字签名(驱动程序目录文件)。
驱动程序目录文件包含数字签名。所有的驱动程序包都应被签名。
厂商通过提交它的驱动程序包给Windows 硬件质量实验室(WHQL)测试、签名,从而获得数字签名。WHQL将包返回,并附带一个目录文件(.cat 文件)。厂商必须为设备在INF文件中列出这个目录文件。更多的信息参见《Windows 2000驱动程序开发参考》卷1第3部分第1章的INF Version节。参考WHQL指南以获得如何提交驱动程序包以测试、签名的信息。
3. 一个或多个协同安装程序。
协同安装程序是一个Win32 DLL,它辅助设备在微软Windows 2000系统中的安装。例如,一个IHV也许会提供一个协同安装程序,从而将设备特定的信息写入注册表中,而这是不能被INF处理的。协同安装程序是可选的。更多的信息参见第4章,编写协同安装程序。
4. 其他文件。
一个驱动程序包可以包含其他文件,比如定制的设置应用程序,一个设备图标,一个驱动程序库文件(例如对视频驱动程序),等等。更多的信息参见第6章,编写定制的设备安装应用程序;第7章,提供设备属性页;第9章,安装一个要求重新启动机器的设备;以及图形驱动程序设计指南的第1部分,图形驱动程序。
1.2 注册表中的驱动程序信息
操作系统和驱动程序将关于驱动程序和设备的信息存储在注册表中。总的来说,驱动程序应使用注册表存储机器重启动后仍必须维护的数据。此外,驱动程序可以访问注册表以获得系统或者其他程序或者驱动程序存储在其中的信息。更多的关于注册表的信息,参见平台SDK文档。
以下的注册表中的树是驱动程序开发者特别感兴趣的(这里HKLM代表HKEY_LOCAL_MACHINE):
·HKLM/SYSTEM/CurrentControlSet/Services
·HKLM/SYSTEM/CurrentControlSet/Control
·HKLM/SYSTEM/CurrentControlSet/Enum
·HKLM/SYSTEM/CurrentControlSet/HardwareProfiles
驱动程序和用户模式的设置组件必须使用系统例程如IoGetDeviceProperty和SetupDiGetDeviceRegistryProperty访问注册表的Plug and Play(PnP)主键。驱动程序不应直接访问这些主键。以下注册表信息的讨论仅仅是为调试一个设备的安装/配置问题。
在HKLM/SYSTEM/CurrentControlSet下的主键是保留驱动程序重要数据的安全地方,因为数据被存在系统区。系统采取特别的预防措施以保护系统区(例如做多个备份)。
HKLM/SYSTEM/CurrentControlSet/Services树
这个树存储机器每个服务的信息。每个驱动程序有一个形式为HKLM/SYSTEM/CurrentControlSet/Services/DriverName的主键。当PnP管理器调用驱动程序的DriverEntry例程时,它在RegistryPath参数中将此路径传给驱动程序。驱动程序可以将全局驱动程序定义的数据存储在它的Services树主键下。在此主键下存储的信息在它初始化时对驱动程序是可用的。
以下的主键和值表项是特别有意义的:
ImagePath
说明驱动程序映像文件全路径的值表项。Setup使用驱动程序INF文件的必须的ServiceBinary表项建立这个值。这个表项在驱动程序的INF AddService指令中引用的service-install-section中。这个路径的典型值是%windir%/system32/Drivers/DriverName.sys,此处DriverName是驱动程序的Services主键名称。
Parameters
用来存储驱动程序专用数据的主键。对一些类型的驱动程序,系统期望找到专用的值表项。你可以使用驱动程序的INF文件的AddReg表项来对这个子键添加值表项。
Performance
对可选的性能监视信息说明的主键。在此主键下的值说明了驱动程序的性能DLL的名称和在此DLL中某些导出的函数的名称。你可以使用驱动程序的INF文件的AddReg表项来对这个子键添加值表项。
HKLM/SYSTEM/CurrentControlSet/Control 树
注册表的这个树包含了控制系统启动和一些设备配置方面的信息。以下的子键特别令人感兴趣:
Class
包含关于计算机上的设备设置类别的信息。对每个类有一个子键,使用设置类别的GUID命名。每个子键包含一个设置类别的信息,如类安装程序(如果有的话),注册的类顶层过滤器驱动程序,注册的类底层过滤器驱动程序,等等。每个类别子键为每个安装在系统中的类设备实例包含软件主键(驱动程序的主键)。
CoDeviceInstallers
包含关于特定类别的、以注册的协同安装程序的信息。
DeviceClasses
包含关于机器中设备接口的信息。对每个设备接口类有一个子键,每个已注册到设备接口类的接口的实例,在那些子键下有一个表项。
HKLM/SYSTEM/CurrentControlSet/Enum 树
注册表的这个树包含了关于机器中设备的信息。PnP管理器为每个设备建立一个子键,名字是HKLM/SYSTEM/CurrentControlSet/Enum/enumerator/deviceID的形式。在这些主键下是一个子键,是机器中现有的每个设备实例。设备实例的子键具有如设备描述、硬件ID、兼容性ID、资源要求等等的信息。
Enum树为操作系统组件的使用而保留,并且它的布局容易改变。驱动程序和用户模式的Setup组件必须使用系统API,如IoGetDeviceProperty和SetupDiGetDeviceRegistryProperty,以从树中提取信息。驱动程序和Setup应用程序不应直接访问Enum树。当调试驱动程序时,你可以使用注册表编辑器察看Enum树。
HKLM/SYSTEM/CurrentControlSet/HardwareProfiles
注册表的这个树包含了计算机上关于硬件profiles的信息。
1.3 指定驱动程序装载顺序
对于大多数设备,Setup和PnP管理器装载驱动程序的顺序由机器中设备的物理层次所决定。Setup和PnP管理器从系统根设备的配置开始,然后是根设备的子设备(例如,PCI适配器),然后是这些子设备的子设备等等。如果驱动程序还没有为另一个设备装入,PnP管理器为每个设备装入驱动程序。
在INF文件中的设置可以影响驱动程序的装入顺序。这一节描述了厂商应当在在驱动程序的INF AddService指令中引用的service-install-section中说明的相关值。这一节讨论了StartType、LoadOrderGroup、Dependencies表项。
为说明StartType,驱动程序应该遵守这些规则:
·PnP驱动程序
PnP驱动程序应该有一个SERVICE_DEMAND_START(0x3)的开始类型,说明无论什么时候PnP管理器发现一个驱动程序可以服务的设备时,它都可以装入驱动程序。
·必须要起动机器的设备的驱动程序
如果设备要求重启动机器,设备的驱动程序应有一个SERVICE_BOOT_START(0x0)的开始类型。
·检测不是PnP可枚举的且不要求起动机器的设备的驱动程序
对于非即插即用设备,驱动程序通过调用IoReportDetectedDevice向PnP管理器报告此设备。这样的驱动程序有一个SERVICE_SYSTEM_START(0x01)的开始类型,这样Setup在系统初始化时将装入驱动程序。
仅仅报告非即插即用设备的驱动程序应该设置这种开始类型。如果驱动程序同时为PnP设备和非PnP设备服务,它应当设置这种开始类型。
·必须被服务控制管理器启动的非PnP的驱动程序
这样的驱动程序有一个SERVICE_AUTO_START(0x02)的开始类型。PnP驱动程序不应设置这种类型。
PnP驱动程序的开发者应使此驱动程序在Setup配置驱动程序所服务的设备的任何时候,都能被加载。相反,在PnP管理器确定驱动程序所服务的设备不存在时,驱动程序应能在任何时候被卸载。PnP驱动程序所依赖的唯一驱动程序装载顺序如下:
·子设备的驱动程序可以依赖于已被加载的父设备的驱动程序。
·在设备栈的驱动程序依赖于在它之下的已被加载的驱动程序。(例如,功能驱动程序要确定任何低层的过滤器驱动程序已经被加载。)注意在设备栈的驱动程序不能依赖于在任何较低层驱动程序之后被加载,因为当另一个此类设备被配置时,驱动程序也许已经被装载了。在过滤组之内的过滤器驱动程序不能预测它们的装载顺序。例如,如果一个设备有三个注册的顶层过滤器驱动程序,这三个驱动程序会在功能驱动程序之后被加载,但是在它们的过滤组之内,装载顺序是任意的。
如果一个驱动程序的装载顺序明显依赖于另一个驱动程序,这个依赖性通过父亲/孩子关系来实现。子设备的驱动程序被加载以前,它依赖于父设备的驱动程序已被加载。
为了增加设置正确的StartType值的重要性,下表描述了Setup和PnP管理器如何在INF文件中使用StartType表项:
1. 在系统启动时,操作系统装载程序在将控制转移给内核以前,装入SERVICE_BOOT_START类型的驱动程序。当内核得到控制时,这些驱动程序已在内存中。Boot-start类型的驱动程序使用INF LoadOrderGroup表项以安排装载顺序。(Boot-start类型的驱动程序在大多数设备被配置以前装入,这样它们的装入顺序不能被设备层次所决定。)操作系统忽略Boot-start类型的驱动程序INF的Dependencies表项。
2. PnP管理器调用SERVICE_BOOT_START类型的驱动程序的DriverEntry例程,这样驱动程序可以服务boot类型的设备。
如果boot类型的驱动程序的设备有子设备,这些设备就被枚举。如果子设备的驱动程序也是Boot-start类型的驱动程序,它们被配置和启动。如果一个设备的驱动程序不全是Boot-start类型的驱动程序,PnP管理器为设备建立设备节点但并不启动设备。
3. 在所有的boot类型的驱动程序被装入以及boot类型的设备被启动后,PnP管理器配置其余的PnP设备并装入它们的驱动程序。
PnP管理器遍历设备树并为还未启动的设备节点装入驱动程序(即任何在前面步骤还没有启动的设备节点)。当每个设备启动时,PnP管理器枚举设备的子设备(如果它有子设备)。
在PnP管理器配置这些设备时,它为设备装入驱动程序并启动设备,而不管驱动程序的StartType值。许多这些驱动程序是SERVICE_DEMAND_START类型的,但是它们可以有任何StartType值。
PnP管理器忽略在这一步骤装入驱动程序中由于INF Dependencies表项和LoadOrderGroup表项而建立的注册表表项。装载顺序基于物理设备层次。
在这一步骤的之后,所有的设备已经被配置,除了不是即插即用可枚举的设备和这些设备的子设备之外。(子设备也许是、也许不是即插即用可枚举的。)
4. PnP管理器装入StartType为SERVICE_SYSTEM_START的、还没有被装入的驱动程序。
这些驱动程序检测并报告它们的非PnP设备。PnP管理器处理由于这些驱动程序的INF LoadOrderGroup表项而导致的注册表表项。它忽略由于这些驱动程序的INF Dependencies表项而建立的注册表表项。
5. 服务控制管理器装入StartType为SERVICE_AUTO_START的、还没有被装入的驱动程序。
服务控制管理器处理关于服务的DependOnGroup和DependOnService的服务数据库信息。这个信息来自于INF AddService表项的Dependencies表项。注意Dependencies信息仅仅为非PnP驱动程序处理,因为任何必须的PnP驱动程序在系统启动的前面步骤中已经被装入。服务控制管理器忽略INF LoadOrderGroup信息。
参见平台SDK文档获得更多关于服务控制管理器的信息。
1.4 安装过滤器驱动程序
一个PnP过滤器驱动程序能支持一个特定的设备或者支持一个设置类的所有设备以及可以依附在设备的功能驱动程序之下(底层过滤程序)或者之上(顶层过滤程序)。参见第1部分的第1章驱动程序种类以获得更多关于PnP驱动程序层的信息。
为了注册一个设备专用的过滤器驱动程序,通过设备的INF文件的DDInstall.HW节的AddReg表项建立一个注册表表项。对于设备专用的顶层过滤,建立名为UpperFilters的表项。对于设备专用的底层过滤,建立名为LowerFilters的表项。例如,以下INF摘录了安装cdaudio作为cdrom驱动程序的顶层过滤:
:
;Installation section for cdaudio.Sets cdrom as the service
;and adds cdaudio as a PnP upper filter driver.
;
[cdaudio_install]
CopyFiles = cdaudio_copyfiles,cdrom_copyfiles
[cdaudio_install.HW]
AddReg = cdaudio_addreg
[cdaudio_install.Services]
AddService = cdrom,0x00000002,cdrom_ServiceInstallSection
AddService = cdaudio,,cdaudio_ServiceInstallSection
:
[cdaudio_addreg]
HKR,,"UpperFilters",0x00010000,"cdaudio";REG_MULTI_SZ value
:
[cdaudio_ServiceInstallSection]
DisplayName = %cdaudio_ServiceDesc%
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
StartType = 3 ; SERVICE_DEMAND_START
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
ServiceBinary = %12%/cdaudio.sys
:
为了安装一个设备设置类别的类范围的顶层/底层过滤程序,你可以提供一个安装必要服务的设置应用程序。设置应用程序然后为希望的设备设置类别注册作为顶层或底层过滤的服务。为拷贝服务的二进制文件,设置应用程序可以使用SetupInstallFiltersFromInfSection。为安装服务,设置应用程序可以使用SetupInstallServicesFromInfSection。为了为特别的设备设置类别注册作为顶层或底层过滤的服务,设置应用程序为每个感兴趣的设备设置类别调用SetupInstallFromInfSection,使用从SetupDiOpenClassRegKey提取的注册表主键句柄作为RelativeKeyRoot参数。例如,考虑以下的INF节:
:
[DestinationDirs]
upperfilter_copyfiles = 12
[upperfilter_inst]
CopyFiles = upperfilter_copyfiles
AddReg = upperfilter_addreg
[upperfilter_copyfiles]
upperfilt.sys
[upperfilter_addreg]
;append this service to existing REG_MULTI_SZ list,if any
HKR,,UpperFilters,0x00010008,upperfilt
[upperfilter_inst.Services]
AddService = upperfilt,,upperfilter_service
[upperfilter_service]
DisplayName = %upperfilter_ServiceDesc%
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
StartType = 3 ; SERVICE_DEMAND_START
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
ServiceBinary = %12%/upperfilt.sys
:
设置应用程序将为[upperfilter_inst]节调用SetupInstallFilesFromInfSection。接下来,它为[upperfilter_inst.Services]节调用SetupInstallServicesFromInfSection。最后,为[upperfilter_inst]节调用SetupInstallFromInfSection,为每个它想注册的顶层过滤服务的类主键分别调用一次。每个调用会为Flags参数说明SPINST_REGISTRY以指示仅仅注册表的修改需要被执行。
1.5 为设备安装Null驱动程序
如果设备在机器中没有使用并且设备不会被启动,你也许为设备安装一个null驱动程序。这样的设备典型情况下并不存在,但是如果存在,你可以安装一个null驱动程序,此设备的INF的表项如下:
:
[MyModels]
%MyDeviceDescription% = MyNullInstallSection,&BadDeviceHardwareID%
:
[MyNullInstallSection]
;the install section must be empty
[MyNullInstallSection.Services]
AddService = ,2 ; no value for the service name
:
在Models节的设备的硬件ID应该具体的标识此设备,使用子系统厂商ID和相关的其他信息。操作系统为设备建立设备节点,但是如果设备不是具有未加工能力(raw capable),操作系统不会启动设备。
如果设备有启动配置,那些资源会被保留。
这一章包括以下信息:
·2.1 驱动程序文件
·2.2 注册表中的驱动程序信息
·2.3 指定驱动程序装载顺序
·2.4 安装过滤器驱动程序
·2.5 为设备安装Null驱动程序
1.1 驱动程序文件
支持一个特定的设备的软件依赖于设备的种类和设备被使用的方式。典型情况下,厂商在驱动程序包中提供下面的软件以支持设备:
1.一个设备安装信息文件(INF文件)。
一个INF文件包含系统Setup组件使用的信息以安装支持设备的文件。当Setup安装驱动程序时,它拷贝这些文件到%windir%/inf目录中。这个文件是必须的。
更多的信息,参见第3章,建立一个INF文件。
1. 设备的一个或多个驱动程序。
一个.sys文件时驱动程序的映像文件。当驱动程序被安装时,Setup拷贝此文件到%windir%/system32/drivers目录中。对大多数设备,驱动程序是必须的;某些设备不需要驱动程序,比如原始能力的设备。
更多的信息,参见这一章的剩余部分和其他章节。
2. 驱动程序包的数字签名(驱动程序目录文件)。
驱动程序目录文件包含数字签名。所有的驱动程序包都应被签名。
厂商通过提交它的驱动程序包给Windows 硬件质量实验室(WHQL)测试、签名,从而获得数字签名。WHQL将包返回,并附带一个目录文件(.cat 文件)。厂商必须为设备在INF文件中列出这个目录文件。更多的信息参见《Windows 2000驱动程序开发参考》卷1第3部分第1章的INF Version节。参考WHQL指南以获得如何提交驱动程序包以测试、签名的信息。
3. 一个或多个协同安装程序。
协同安装程序是一个Win32 DLL,它辅助设备在微软Windows 2000系统中的安装。例如,一个IHV也许会提供一个协同安装程序,从而将设备特定的信息写入注册表中,而这是不能被INF处理的。协同安装程序是可选的。更多的信息参见第4章,编写协同安装程序。
4. 其他文件。
一个驱动程序包可以包含其他文件,比如定制的设置应用程序,一个设备图标,一个驱动程序库文件(例如对视频驱动程序),等等。更多的信息参见第6章,编写定制的设备安装应用程序;第7章,提供设备属性页;第9章,安装一个要求重新启动机器的设备;以及图形驱动程序设计指南的第1部分,图形驱动程序。
1.2 注册表中的驱动程序信息
操作系统和驱动程序将关于驱动程序和设备的信息存储在注册表中。总的来说,驱动程序应使用注册表存储机器重启动后仍必须维护的数据。此外,驱动程序可以访问注册表以获得系统或者其他程序或者驱动程序存储在其中的信息。更多的关于注册表的信息,参见平台SDK文档。
以下的注册表中的树是驱动程序开发者特别感兴趣的(这里HKLM代表HKEY_LOCAL_MACHINE):
·HKLM/SYSTEM/CurrentControlSet/Services
·HKLM/SYSTEM/CurrentControlSet/Control
·HKLM/SYSTEM/CurrentControlSet/Enum
·HKLM/SYSTEM/CurrentControlSet/HardwareProfiles
驱动程序和用户模式的设置组件必须使用系统例程如IoGetDeviceProperty和SetupDiGetDeviceRegistryProperty访问注册表的Plug and Play(PnP)主键。驱动程序不应直接访问这些主键。以下注册表信息的讨论仅仅是为调试一个设备的安装/配置问题。
在HKLM/SYSTEM/CurrentControlSet下的主键是保留驱动程序重要数据的安全地方,因为数据被存在系统区。系统采取特别的预防措施以保护系统区(例如做多个备份)。
HKLM/SYSTEM/CurrentControlSet/Services树
这个树存储机器每个服务的信息。每个驱动程序有一个形式为HKLM/SYSTEM/CurrentControlSet/Services/DriverName的主键。当PnP管理器调用驱动程序的DriverEntry例程时,它在RegistryPath参数中将此路径传给驱动程序。驱动程序可以将全局驱动程序定义的数据存储在它的Services树主键下。在此主键下存储的信息在它初始化时对驱动程序是可用的。
以下的主键和值表项是特别有意义的:
ImagePath
说明驱动程序映像文件全路径的值表项。Setup使用驱动程序INF文件的必须的ServiceBinary表项建立这个值。这个表项在驱动程序的INF AddService指令中引用的service-install-section中。这个路径的典型值是%windir%/system32/Drivers/DriverName.sys,此处DriverName是驱动程序的Services主键名称。
Parameters
用来存储驱动程序专用数据的主键。对一些类型的驱动程序,系统期望找到专用的值表项。你可以使用驱动程序的INF文件的AddReg表项来对这个子键添加值表项。
Performance
对可选的性能监视信息说明的主键。在此主键下的值说明了驱动程序的性能DLL的名称和在此DLL中某些导出的函数的名称。你可以使用驱动程序的INF文件的AddReg表项来对这个子键添加值表项。
HKLM/SYSTEM/CurrentControlSet/Control 树
注册表的这个树包含了控制系统启动和一些设备配置方面的信息。以下的子键特别令人感兴趣:
Class
包含关于计算机上的设备设置类别的信息。对每个类有一个子键,使用设置类别的GUID命名。每个子键包含一个设置类别的信息,如类安装程序(如果有的话),注册的类顶层过滤器驱动程序,注册的类底层过滤器驱动程序,等等。每个类别子键为每个安装在系统中的类设备实例包含软件主键(驱动程序的主键)。
CoDeviceInstallers
包含关于特定类别的、以注册的协同安装程序的信息。
DeviceClasses
包含关于机器中设备接口的信息。对每个设备接口类有一个子键,每个已注册到设备接口类的接口的实例,在那些子键下有一个表项。
HKLM/SYSTEM/CurrentControlSet/Enum 树
注册表的这个树包含了关于机器中设备的信息。PnP管理器为每个设备建立一个子键,名字是HKLM/SYSTEM/CurrentControlSet/Enum/enumerator/deviceID的形式。在这些主键下是一个子键,是机器中现有的每个设备实例。设备实例的子键具有如设备描述、硬件ID、兼容性ID、资源要求等等的信息。
Enum树为操作系统组件的使用而保留,并且它的布局容易改变。驱动程序和用户模式的Setup组件必须使用系统API,如IoGetDeviceProperty和SetupDiGetDeviceRegistryProperty,以从树中提取信息。驱动程序和Setup应用程序不应直接访问Enum树。当调试驱动程序时,你可以使用注册表编辑器察看Enum树。
HKLM/SYSTEM/CurrentControlSet/HardwareProfiles
注册表的这个树包含了计算机上关于硬件profiles的信息。
1.3 指定驱动程序装载顺序
对于大多数设备,Setup和PnP管理器装载驱动程序的顺序由机器中设备的物理层次所决定。Setup和PnP管理器从系统根设备的配置开始,然后是根设备的子设备(例如,PCI适配器),然后是这些子设备的子设备等等。如果驱动程序还没有为另一个设备装入,PnP管理器为每个设备装入驱动程序。
在INF文件中的设置可以影响驱动程序的装入顺序。这一节描述了厂商应当在在驱动程序的INF AddService指令中引用的service-install-section中说明的相关值。这一节讨论了StartType、LoadOrderGroup、Dependencies表项。
为说明StartType,驱动程序应该遵守这些规则:
·PnP驱动程序
PnP驱动程序应该有一个SERVICE_DEMAND_START(0x3)的开始类型,说明无论什么时候PnP管理器发现一个驱动程序可以服务的设备时,它都可以装入驱动程序。
·必须要起动机器的设备的驱动程序
如果设备要求重启动机器,设备的驱动程序应有一个SERVICE_BOOT_START(0x0)的开始类型。
·检测不是PnP可枚举的且不要求起动机器的设备的驱动程序
对于非即插即用设备,驱动程序通过调用IoReportDetectedDevice向PnP管理器报告此设备。这样的驱动程序有一个SERVICE_SYSTEM_START(0x01)的开始类型,这样Setup在系统初始化时将装入驱动程序。
仅仅报告非即插即用设备的驱动程序应该设置这种开始类型。如果驱动程序同时为PnP设备和非PnP设备服务,它应当设置这种开始类型。
·必须被服务控制管理器启动的非PnP的驱动程序
这样的驱动程序有一个SERVICE_AUTO_START(0x02)的开始类型。PnP驱动程序不应设置这种类型。
PnP驱动程序的开发者应使此驱动程序在Setup配置驱动程序所服务的设备的任何时候,都能被加载。相反,在PnP管理器确定驱动程序所服务的设备不存在时,驱动程序应能在任何时候被卸载。PnP驱动程序所依赖的唯一驱动程序装载顺序如下:
·子设备的驱动程序可以依赖于已被加载的父设备的驱动程序。
·在设备栈的驱动程序依赖于在它之下的已被加载的驱动程序。(例如,功能驱动程序要确定任何低层的过滤器驱动程序已经被加载。)注意在设备栈的驱动程序不能依赖于在任何较低层驱动程序之后被加载,因为当另一个此类设备被配置时,驱动程序也许已经被装载了。在过滤组之内的过滤器驱动程序不能预测它们的装载顺序。例如,如果一个设备有三个注册的顶层过滤器驱动程序,这三个驱动程序会在功能驱动程序之后被加载,但是在它们的过滤组之内,装载顺序是任意的。
如果一个驱动程序的装载顺序明显依赖于另一个驱动程序,这个依赖性通过父亲/孩子关系来实现。子设备的驱动程序被加载以前,它依赖于父设备的驱动程序已被加载。
为了增加设置正确的StartType值的重要性,下表描述了Setup和PnP管理器如何在INF文件中使用StartType表项:
1. 在系统启动时,操作系统装载程序在将控制转移给内核以前,装入SERVICE_BOOT_START类型的驱动程序。当内核得到控制时,这些驱动程序已在内存中。Boot-start类型的驱动程序使用INF LoadOrderGroup表项以安排装载顺序。(Boot-start类型的驱动程序在大多数设备被配置以前装入,这样它们的装入顺序不能被设备层次所决定。)操作系统忽略Boot-start类型的驱动程序INF的Dependencies表项。
2. PnP管理器调用SERVICE_BOOT_START类型的驱动程序的DriverEntry例程,这样驱动程序可以服务boot类型的设备。
如果boot类型的驱动程序的设备有子设备,这些设备就被枚举。如果子设备的驱动程序也是Boot-start类型的驱动程序,它们被配置和启动。如果一个设备的驱动程序不全是Boot-start类型的驱动程序,PnP管理器为设备建立设备节点但并不启动设备。
3. 在所有的boot类型的驱动程序被装入以及boot类型的设备被启动后,PnP管理器配置其余的PnP设备并装入它们的驱动程序。
PnP管理器遍历设备树并为还未启动的设备节点装入驱动程序(即任何在前面步骤还没有启动的设备节点)。当每个设备启动时,PnP管理器枚举设备的子设备(如果它有子设备)。
在PnP管理器配置这些设备时,它为设备装入驱动程序并启动设备,而不管驱动程序的StartType值。许多这些驱动程序是SERVICE_DEMAND_START类型的,但是它们可以有任何StartType值。
PnP管理器忽略在这一步骤装入驱动程序中由于INF Dependencies表项和LoadOrderGroup表项而建立的注册表表项。装载顺序基于物理设备层次。
在这一步骤的之后,所有的设备已经被配置,除了不是即插即用可枚举的设备和这些设备的子设备之外。(子设备也许是、也许不是即插即用可枚举的。)
4. PnP管理器装入StartType为SERVICE_SYSTEM_START的、还没有被装入的驱动程序。
这些驱动程序检测并报告它们的非PnP设备。PnP管理器处理由于这些驱动程序的INF LoadOrderGroup表项而导致的注册表表项。它忽略由于这些驱动程序的INF Dependencies表项而建立的注册表表项。
5. 服务控制管理器装入StartType为SERVICE_AUTO_START的、还没有被装入的驱动程序。
服务控制管理器处理关于服务的DependOnGroup和DependOnService的服务数据库信息。这个信息来自于INF AddService表项的Dependencies表项。注意Dependencies信息仅仅为非PnP驱动程序处理,因为任何必须的PnP驱动程序在系统启动的前面步骤中已经被装入。服务控制管理器忽略INF LoadOrderGroup信息。
参见平台SDK文档获得更多关于服务控制管理器的信息。
1.4 安装过滤器驱动程序
一个PnP过滤器驱动程序能支持一个特定的设备或者支持一个设置类的所有设备以及可以依附在设备的功能驱动程序之下(底层过滤程序)或者之上(顶层过滤程序)。参见第1部分的第1章驱动程序种类以获得更多关于PnP驱动程序层的信息。
为了注册一个设备专用的过滤器驱动程序,通过设备的INF文件的DDInstall.HW节的AddReg表项建立一个注册表表项。对于设备专用的顶层过滤,建立名为UpperFilters的表项。对于设备专用的底层过滤,建立名为LowerFilters的表项。例如,以下INF摘录了安装cdaudio作为cdrom驱动程序的顶层过滤:
:
;Installation section for cdaudio.Sets cdrom as the service
;and adds cdaudio as a PnP upper filter driver.
;
[cdaudio_install]
CopyFiles = cdaudio_copyfiles,cdrom_copyfiles
[cdaudio_install.HW]
AddReg = cdaudio_addreg
[cdaudio_install.Services]
AddService = cdrom,0x00000002,cdrom_ServiceInstallSection
AddService = cdaudio,,cdaudio_ServiceInstallSection
:
[cdaudio_addreg]
HKR,,"UpperFilters",0x00010000,"cdaudio";REG_MULTI_SZ value
:
[cdaudio_ServiceInstallSection]
DisplayName = %cdaudio_ServiceDesc%
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
StartType = 3 ; SERVICE_DEMAND_START
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
ServiceBinary = %12%/cdaudio.sys
:
为了安装一个设备设置类别的类范围的顶层/底层过滤程序,你可以提供一个安装必要服务的设置应用程序。设置应用程序然后为希望的设备设置类别注册作为顶层或底层过滤的服务。为拷贝服务的二进制文件,设置应用程序可以使用SetupInstallFiltersFromInfSection。为安装服务,设置应用程序可以使用SetupInstallServicesFromInfSection。为了为特别的设备设置类别注册作为顶层或底层过滤的服务,设置应用程序为每个感兴趣的设备设置类别调用SetupInstallFromInfSection,使用从SetupDiOpenClassRegKey提取的注册表主键句柄作为RelativeKeyRoot参数。例如,考虑以下的INF节:
:
[DestinationDirs]
upperfilter_copyfiles = 12
[upperfilter_inst]
CopyFiles = upperfilter_copyfiles
AddReg = upperfilter_addreg
[upperfilter_copyfiles]
upperfilt.sys
[upperfilter_addreg]
;append this service to existing REG_MULTI_SZ list,if any
HKR,,UpperFilters,0x00010008,upperfilt
[upperfilter_inst.Services]
AddService = upperfilt,,upperfilter_service
[upperfilter_service]
DisplayName = %upperfilter_ServiceDesc%
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
StartType = 3 ; SERVICE_DEMAND_START
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
ServiceBinary = %12%/upperfilt.sys
:
设置应用程序将为[upperfilter_inst]节调用SetupInstallFilesFromInfSection。接下来,它为[upperfilter_inst.Services]节调用SetupInstallServicesFromInfSection。最后,为[upperfilter_inst]节调用SetupInstallFromInfSection,为每个它想注册的顶层过滤服务的类主键分别调用一次。每个调用会为Flags参数说明SPINST_REGISTRY以指示仅仅注册表的修改需要被执行。
1.5 为设备安装Null驱动程序
如果设备在机器中没有使用并且设备不会被启动,你也许为设备安装一个null驱动程序。这样的设备典型情况下并不存在,但是如果存在,你可以安装一个null驱动程序,此设备的INF的表项如下:
:
[MyModels]
%MyDeviceDescription% = MyNullInstallSection,&BadDeviceHardwareID%
:
[MyNullInstallSection]
;the install section must be empty
[MyNullInstallSection.Services]
AddService = ,2 ; no value for the service name
:
在Models节的设备的硬件ID应该具体的标识此设备,使用子系统厂商ID和相关的其他信息。操作系统为设备建立设备节点,但是如果设备不是具有未加工能力(raw capable),操作系统不会启动设备。
如果设备有启动配置,那些资源会被保留。