开发过USB设备驱动的朋友,不知有没有碰到过下面的问题:假如你的设备驱动程序没有经过数字签名,那么,在XP体系下,你在每个USB口上第一次插上你的USB设备时,体系都会要求你装一次驱动程序。这种感觉是很欠好的。咱们期望能像大多数USB移动盘相同,插上设备就主动装置驱动,然后就能够对设备进行访问了。
怎么让咱们的USB设备插上后,体系也能主动为它装置驱动,而不需求烦劳用户手动装置呢?处理此问题的核心技术在于编写一个类协作装置程序。
首要,有一个问题咱们要清楚,USB设备第一次插到机器上的一个USB口上时,体系要为它装一次驱动程序。咱们以USB设备为例,来了解一下支撑热插拔的PnP设备的装置进程:
(1)设备刺进体系,USB总线驱动向内核PnP管理器陈述有新设备接入体系;
(2)内核PnP管理器向USB总线驱动问询设备的详细信息,比方PID和VID等;
(3)内核PnP管理器将设备的信息陈述给用户层的PnP管理器,并要求它为新设备装置驱动;
(4)用户层PnP管理器调用体系的Setup组件来为设备装置驱动;
(5)Setup运用设备VID和PID到%Windir%inf下寻觅合适它的inf文件,并取得一个可用于设备的驱动程序列表;
(6)Setup在生成驱动程序列表的时分,会查看inf文件是否经过数字签名,假如没有经过数字签名,Setup会将此inf文件担任装置的驱动程序设置成“不行信赖的”驱动程序;
(7)Setup对驱动程序列表中的各驱动程序信息进行剖析,挑选最匹配设备的驱动程序进行装置;
这儿,有必要提一下“不行信赖的驱动程序”这个概念。这个概念在xp之后才有的,2k和98没有。在Setup 生成的驱动程序列表中,每个驱动程序的信息结构中都有一个Rank字段。在xp中,0x0 Rank = 0x3FFF的驱动程序被以为是“可信赖的”;0x8000 = Rank = 0xFFFF的驱动被以为是“不行信赖的”。假如咱们的驱动程序没有经过数字签名,那么它的Rank值必定落在0x8000到0xFFFF之间。
再回到前面的装置进程,假如驱动程序中有合适设备的“可信赖”驱动程序,那么体系主动对它进行装置;假如驱动程序列表中的一切驱动程序都是“不行信赖的”,那么体系就会弹出“发现新硬件”导游,要你供给更好的驱动程序,或许要你承认装置“不行信赖的”驱动程序。这便是为什么在xp体系下,即使你在一个USB口上现已装置了设备的驱动程序,你再换个口插上设备,体系又会提示你装置驱动程序的原因。
说了半天,我想现在各位必定都理解过来了:影响设备驱动程序主动装置的主要原因,是由于咱们的驱动程序被体系以为是“不行信赖的”。而体系判别一个驱动程序是否“可信赖”,是经过驱动程序信息结构中的Rank字段的值来判别的。那么,假如咱们能把咱们的驱动程序信息中的Rank值修正到“可信赖”空间,那么体系是否就会信赖咱们的驱动程序,而主动对它进行装置呢?答案是,有或许。我不敢说必定能够,原因后面会说到。可是,怎么修正驱动程序信息的Rank值呢?这就要用到“协作装置程序”。
咱们知道,在设备的装置进程中,Setup要向设备类装置程序、类协作装置程序和设备协作装置程序发送“设备装置功用码”(假如有这些装置程序的话)。ddk文档中又说,类装置程序和类协作装置程序能够对DIF_SELECTBESTCOMPATDRV恳求进行处理(设备协作装置程序不行以)。在对DIF_SELECTBESTCOMPATDRV进行处理的时分,类装置程序和类协作装置程序能够修正驱动程序列表中各驱动程序的信息。答案越来越明晰了,咱们只需写一个类协作装置程序,对DIF_SELECTBESTCOMPATDRV进行处理,修正咱们想要装置的驱动程序的Rank值,那么就或许骗过体系,使体系信赖咱们的驱动程序,并完结主动装置。关于编写协作装置程序的详细要求和办法,能够参阅ddk文档中的“Writing a Co-installer(编写协作装置程序)”和ddksrcgeneraltoastercoinstaller。
接下来,咱们来了解一下,在类协作装置程序处理DIF_SELECTBESTCOMPATDRV时,应该做哪些工作。
(1)首要,调用SetupDiEnumDriverInfo遍历驱动程序列表,取得每个驱动程序的信息——一个SP_DRVINFO_DATA结构。
(2)接着,用(1)中取得的SP_DRVINFO_DATA作为输入参数,调用SetupDiGetDriverInstallParams,取得驱动程序装置参数——一个SP_DRVINSTALL_PARAMS结构,其间咱们想要修正的Rank赫然在列。你能够依照自己的需求修正Rank的值,在这儿咱们必定是要把它改为0了(0表明驱动程序与设备最匹配)。
(3)最终,把修正后的SP_DRVINSTALL_PARAMS结构作为输入,调用SetupDiSetDriverInstallParams将咱们修正的值设置收效。
在类协作装置程序中只需作如此处理,便能够使Setup尔后信赖咱们的驱动程序,然后到达咱们想瞒天过海的意图。
再略微提一下类协作装置程序的注册。协作装置程序做好了,怎么使它参加到设备装置的进程中来呢?咱们有必要注册它。ddk文档对此讲得十分清楚了,参看“Registering a Class Co-installer”,我就不在这儿把它翻译出来了。
最终,要提示一点:有必要为咱们的usb设备界说一个新的设备setup类,然后将咱们的协作装置程序注册为这个setup类的类协作装置程序。假如咱们让设备依然归于usb setup类,并将咱们的类协作装置程序注册为usbsetup类的一个协作装置程序,那么在装置进程中,Setup依然弹出一些窗体影响咱们设备的主动装置,好像咱们的小聪明并没能瞒过它。这便是前面我说修正Rank值为“可信赖”仅仅有或许瞒过体系而不是必定能够瞒过体系的原因。为什么会呈现这种状况呢?从现象看,我感觉是usb setup类的类装置程序依然发现咱们的驱动程序是不行信赖的。可是,Setup是以类协作装置程序、设备协作装置程序和类装置程序的顺序调用它们的,在Setup调用usb setup类装置程序之前,咱们现已修正了驱动程序的Rank值。按理说,它应该不会发现驱动程序是不行信赖的。这是一个问题,详细原因我还没有弄理解,期望有知其所以然者,能给点提示!不论怎么,经过试验我发现,只需咱们界说了新的setup类,那么咱们就能够骗过体系Setup组件,使其主动为咱们的设备装置驱动程序。
就写这些,有爱好的朋友能够试一下!我不想把详细的完成进程一步一步地写出来,更不肯供给详细的完成代码。由于我以为只需把原理和办法讲清楚了(希望我讲得还算清楚),每个人都能够在此基础上做自己的工作。
不论各位朋友看完之后感觉怎么,能夸就夸夸,该骂就骂骂,都顶一下