驱动开发学习笔记(4-2)–INF文件-2

.INF文件是什么

.INF是 Device Information File 的缩写,是微软公司为供硬件设备制造商发布其设备驱动程序而发展的———许多硬件设备的驱动程序都是使用 .INF文件来安装的。.INF文件从 Windows3.X 时代就开始大量被使用了。
.INF文件是一种具有特定格式的纯文本文件,我们可说它是一种安装脚本(SetupScript)。虽然 .INF 只是纯文本文件,但是当我们在文件管理器explorer对 .INF文件按鼠标右键後,如图inf右键.PNG,在右键菜单上就会出现“安装I”命令,这是因为微软公司已在其操作系统 Windows 中内置提供了 Setup API(可以解释.INF脚本文件),我们只需用文本编辑软件编写 .INF文件,便可完成大部份的安装工作,所以尤其是在软体的大小并不是很大的情况下,安装工作不是很复杂的时候,使用 .INF文件来进行安装工作将会是一个好选择。而且如果要安装设备驱动程序,.INF文件是目前唯一的选择。 可以用 .INF文件创建包括注册表条目和目的目录的自定义软件安装指令。.INF文件可以提供有限的平台独立性,并指定有限的软件依赖性。目前.INF文件最普遍的应用是为安装硬件设备的驱动程序服务的,本文的目的就是介绍 .INF文件的功能、结构、并提供了几个 事例来说明如何用.INF文件,如何扩展.INF文件的用途,比如制作绿色软件,仅供参考。

下面首先给出一个驱动程序的.INF文件的例子,如图usbinfpng.png,是我从Windows2000中抽取出来的用于Win98se的USB存储设备驱动的usbstor.INF文件,删除了大部分内容,紧紧保留了一个基本的.INF文件的框架。

.INF文件的格式

在图usbinfpng.png中,可以看到.INF文件是由许多节(Section)组成,与.INI文件类似,整个.INF文件由几个节组成,节名用方括号扩起来,如version 节,Manufacturer节,和Strings节等等。而每个节又由一系列的条目组成,每个条目都是是由一个键(Key)与一个值(Value)组成,都是“Key=Value”这样的形式,在这些节中定义的项目可以完成硬件的自动检测和软件(包括驱动程序)的安装。.INF文件中分号后面的字符串是注释。在一个 .INF文件中,所有跟随在分号(;)后的文字都会被视为注释。注释并不一定要在新行开始,可以在一行文字後面加入注释。

.INF文件案格式和作用如下所示:

[Version] 节: 包含对此 .INF文件的简短描述与此 .INF文件支持的设备类型的信息。用于确认 .INF文件的基本版本信息。任何.INF文件都必须 包括这个节。
在图usbinfpng.png中,[Version] 节中的语句 Signature=”$CHICAGO$”表明这个.INF文件可以用于windows 95以后的所有平台上,目前来说就是win98,winme,winnt4,win2k,winxp,win2k3。这种.INF文件比较多见。如果[Version]节中的签名条目是 Signature=”$Windows 95$”,表明这个.INF文件可以用于windows 95以后的Win9x平台上,目前来说就是win98,winme。 如果[Version]节中的签名条目是 Signature=”$WINDOWS NT$”,表明这个.INF文件可以用于WindowsNT系列的平台上,包括winnt4,win2k,winxp,win2k3。WIN9x系列的操作系统的SetupAPI将会拒绝执行这种类型的.INF文件。

[Manufacturer] 与 [Manufacturer Name] 节: 列出此 .INF文件可辨识的所有硬件设备,并列出了开发该硬件的厂商名称,主要用于硬件设备的安装。在设备驱动程序的.INF文件中必须包括[Manufacturer]节与 [Manufacturer Name] 节。对应到图usbinfpng.png中就是[Manufacturer]节和[Microsoft]节,安装新硬件的向导中列出来的厂商名字和设备名称就是来自这两个节。这行语句“%MfgName%=Microsoft” 的等号右边的名字指明设备制造商是Microsoft,等号左边是厂商的名字,图中的厂商名称是”Microsoft”(在后面讲到的[Strings]节中)。在一个.INF文件中可以有多个设备制造商的名字,都必须放在[Manufacturer]节中,同时[Manufacturer Name] 节可以列出该厂商的多种设备。 [Manufacturer Name] 节区含有对要安装的设备的描述,并为要安装的设备指出 [Install] 节区。 [Manufacturer Name]节语法:
[manufacturer-name]
device-description=install-section-name,device-id[,compatible-device-id]…
device-description就是对要安装的设备的描述。install-section-name就是此设备的 [Install] 节区名称,manufacturer-name 节区名称必须已在 [Manufacturer] 节区中被定义。device-id是此设备的硬件标志符,每个厂家的不同的硬件对应着不同的设备标志符。
对应到图usbinfpng.png中,就是这行语句“%GenericBulkOnly.DeviceDesc%=USBSTOR_BULK, USB\Class_08&SubClass_02&Prot_50”等号左边是设备的描述,也就是设备名字是”USB Mass Storage Device”,而等号右边的USB\Class_08&SubClass_02&Prot_50是设备标志符,这个标志符是对应到一类的硬件设备,就是USB存储设备,操作系统检测到USB存储设备,安装相应的驱动的时候,就会从设备驱动的安装节即[USBSTOR_BULK]节开始安装驱动。可以看出来此.INF文件可以用于通用的USB存储设备”USB Mass Storage Device”的驱动程序的安装。
普通的安装软件的.INF文件中,不包括[Manufacturer] 与 [Manufacturer Name] 节,即使包含,也不会执行它们,这2个节仅仅用于硬件的设备驱动中起作用。

[Install] 节: 描述设备驱动程序与硬件设备的实际属性。它也定义了所有 [Install] 节的名称,在此定义的节中包含了安装该设备的信息和命令。默认情况下,会执行 [DefaultInstall] 节,在图inf右键.PNG中,Install操作就会执行[DefaultInstall] 节。[DefaultInstall] 节中包含指向其他节的指针,该节可用于指定要复制和删除的文件、注册表的更新、.INF文件的更新等。
对应到图usbinfpng.png中,[Install] 节就是[USBSTOR_BULK]节,其中要执行复制文件CopyFiles和添加注册表项目AddReg2种操作。
如果是安装普通的软件的.INF文件,可以通过鼠标右键菜单上的“安装”命令来安装(图inf右键.PNG),这个时候.INF文件必须包括[DefaultInstall]节,也可以包括其他的[Install]节,用RUNDLL32.EXE SETUPAPI.DLL,InstallHinfSection [Install]节的名字,这样类似的命令来安装。
[Install]节的语法:

1
2
3
4
5
6
7
8
9
10
11
12
[install-section-name]
Copyfiles=file-list-section[,file-list-section]...
LogConfig=log-config-section-name
Renfiles=file-list-section[,file-list-section]...
Delfiles=file-list-section[,file-list-section]...
UpdateInis=update-ini-section[,update-ini-section]...
UpdateIniFields=update-inifields-section[,update-inifields-section]...
AddReg=add-registry-section[,add-registry-section]...
DelReg=del-registry-section[,del-registry-section]...
Ini2Reg=ini-to-registry-section[,ini-to-registry-section]...
UpdateCfgSys=update-config-section
UpdateAutoBat=update-autoexec-section

[Install] 节定义了安装程式与硬体驱动需要的资源,以便安装新的驱动程式或者软件。此节中每个条目都有其特定格式与意义,并非每个条目都是必要的。无论是安装驱动程序还是普通的软件,最后都要从某一个[Install] 节开始执行。

[DestinationDirs] 节: 指定硬盘上复制、删除或重命名节文件的位置(例如 \Windows 或 Windows\System)。 .INF文件通过[DestinationDirs]节来指定操作的目标路径,语法如下:
[DestinationDirs]
file-list-section =ldid[, subdir ]
DefaultDestDir=ldid[, subdir ]
[DestinationDirs] 节定义了 [file-list-section] 节中指定的操作(可以是 CopyFiles、RenFiles 或 DelFiles 节)的目标目录。DefaultDestDir命令可以为 .INF文件中的任何没有明确在[DestinationDirs]节中命名的CopyFiles、RenFiles或DelFiles节指定默认目标文件夹。
在.INF文件中,使用逻辑磁盘标识符 (LDID) 来表示路径,如下表:
00 Null LDID – 可用于创建新的 LDID
01 Source Drive:\pathname
10 Windows 文件夹(等价于%windir%目录 )
11 System 文件夹
12 IOSubsys 文件夹
13 Command 文件夹
17 Inf 文件夹
18 Help 文件夹
20 Fonts
21 Viewers
22 VMM32
23 Color 文件夹
24 包含 Windows 文件夹的驱动器根目录
28 Host Winboot
30 启动盘的根文件夹
31 虚拟启动盘的主驱动器根文件夹
如图usbinfpng.png中,这行语句“USBSTOR.CopyList = 10, system32\drivers”表明USBSTOR.CopyList这个文件列表中文件的目标路径是%windir%\system32\drivers,其中10代表Windows所在的文件夹,也就是说USBSTOR.CopyList这个文件列表中文件USBSTOR.SYS在安装驱动的时候将会被复制到%windir%\system32\drivers文件夹。而usbstor.inf这个文件将会被复制到17,也就是%windir%\inf文件夹中。
[Strings] 节: 定义并列出上面所使用的可本地化字符串。如果某个特定的字符串会在 .INF文件中频繁地出现,那么在此节中为它们定义一个字符串变量将会是个好选择。如图usbinfpng.png中,语句MfgName=”Microsoft”,定义了[Manufacturer]节使用的MfgName变量(就是字符串”Microsoft”)。
[FileCopy/Delete/RenameSection(s)] 节:列出要复制、删除或重命名的文件。 节的名字是CopyFiles,DelFiles,RenFiles。
[RegistryUpdateSection(s)] 节:指定在注册表中添加或删除的项目。 节的名字是AddReg,DelReg。
[IniFileUpdateSection(s)] 节:指定 .ini 文件的更新。链接将在该节中创建。 节的名字是 UpdateInis。

[ClassInstall] 节:为设备定义一个新的类别(Class)。主要用于硬件设备的安装。

[SourceDisksNames] 节: 列出包含文件的磁盘。

[SourceDisksFiles] 节: 列出每个文件所在的特定磁盘。
其他的节还有许多,如:Update .ini Fields 节 (UpdateIniFields),Add Ini File to Registry 节 (Ini2Reg),Update Config.sys 节 (UpdateCfgSys),Update Autoexec.bat 节 (UpdateAutoBat),Optional Components 节,等等。

.INF文件是由Windows的SetupAPI解释执行的脚本文件,它的运行过程很简单,是一种线性的执行,线性的意思就是.INF文件的运行过程不存在分支语句,也就是没有条件语句,一旦开始执行,就是沿着固定的路线运行。它的运行是按照节为单位来执行的,从某一个[Install]节开始执行,从上到下执行该节中的条目,如果该条目是一个节,那么就一条条执行子节中的条目,如此递归执行。
这样的脚本看起来功能很弱,但是对于简单的安装任务已经足够了,安装不外乎复制文件,添加注册表,修改.INI文件等任务,这些都可以用.INF文件来完成。对于更复杂的安装要求,如要求安装程序的界面漂亮方便,要求有选择性的安装,要求安装程序自动修复的功能,就只好求助于其他的工具了,如微软的Windows Installer,就具备更加强大的功能。

.INF文件的版本

.INF文件的语法是统一的分节语法,随着操作系统的更新,微软逐渐增加了一些必要的关键字,但是整个的.INF文件的结构不会变化。从语法上来说,.INF文件都是一个类别。
按照.INF文件的版本来分类,可以分为2类:
1 AdvancedINF,在[Version]节中有“AdvancedINF=2.5,”您需要新版本的 AdvPack.dll” ”这么一行语句,表明此.INF文件需要AdvPack.dll这个动态链接库来解释执行,AdvancedINF有一些高级特性,但是在目前用的不太多。
2 普通INF,没有指明需要AdvPack.dll的.INF文件,使用SetupAPI.DLL来解释执行(win9x系列的操作系统使用Setupx.dll),系统中缺省使用的就是这种普通INF。

.INF文件的功能

从前面的介绍,能够看出使用 .INF文件可以完成如下功能:
1 复制文件、删除文件、或重新命名文件。
2 新增或删除注册表(Registry)中的项目。
3 修改重要的系统设置文件(如 Autoexec.bat、Config.sys、.INI 等)。
粗看起来,似乎上面提到的第一个功能可以用批处理文件.BAT来完成,第二个功能可以通过注册表文件.REG来完成,第三个功能现在用得不多,不经常处理.INI文件了。这样说起来似乎.INF文件也没有太大的优势啊。这种看法是有问题的,下面我将会着重指出.INF在在这几个方面的应用,而不会仔细讲解.INF的语法。 下面要提到.INF文件优于别的工具的方面。

用.INF文件编辑注册表

.INF文件可以编辑操纵注册表,相应的的命令是AddReg和DelReg,语法如下:

1
2
3
4
5
6
7
AddReg = add-registry-section[,add-registry-section]...
[ add-registry-section]
reg-root-string, [subkey], [value-name], [flag], [value]
[add-registry-section]节定义了将要添加的注册表子键或值名,可以有选择地设置它的值。
DelReg = del-registry-section[,del-registry-section]...
[ del-registry-section]
reg-root-string, subkey, [value-name]

[ del-registry-section]节定义了将要从注册表中删除子键subkey或值名value-name。
有时候上网遇到某些网站,修改了IE的主页,然后禁用了REGEDIT工具,这个时候很多人只好借助于其他第三方工具如魔法兔子等来恢复注册表的编辑权限,其实这个时候仅仅依靠.INF文件就可以恢复使用REGEDIT工具的权限。
把下面的这段代码复制到记事本里,另存为jiereg.inf,然后右击它选择“安装(I)”,就可以了。

1
2
3
4
5
6
7
[Version]
Signature="$CHICAGO$"
[DefaultInstall]
AddReg=My.Add.Reg
[My.Add.Reg]
HKCU,"SOFTWARE\Microsoft\windows\currentversion\policies\system","disableregistrytools", 0x00010001,"0"
HKLM,"SOFTWARE\Microsoft\windows\currentversion\policies\system","disableregistrytools", 0x00010001,"0"

当然还可以用其他的方法,原理也是一样的,这里仅仅是演示一下.INF文件的用途。
直接使用注册表文件,有时候还会遇到另外一个缺点,就是.REG文件里面使用16进制代码表示UNICODE字符串的,如下面的两条注册表语句:
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders]
“Cookies”=hex(2):25,00,55,00,53,00,45,00,52,00,50,00,52,00,4f,00,46,00,49,00,4c,00,45,00,25,00,5c,00,43,00,6f,00,6f,00,6b,00,69,00,65,00,73,00,00,00,00,00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\SoftEther]
“ImagePath”=hex(2):22,00,44,00,3a,00,5c,00,50,00,72,00,6f,00,67,00,72,00,61,00,6d,00,20,00,46,00,69,00,6c,00,65,00,73,00,5c,00,53,00,6f,00,66,00,74,00,45,00,74,00,68,00,65,00,72,00,5c,00,53,00,6f,00,66,00,74,00,45,00,74,00,68,00,65,00,72,00,2e,00,65,00,78,00,65,00,22,00,20,00,73,00,65,00,72,00,76,00,69,00,63,00,65,00,00,00,00,00

这上面两条语句难以阅读和修改,手工修改的话很麻烦,其中
“Cookies”的值实际上就是“%USERPROFILE%\Cookies”字符串的UNICODE表示。
“ImagePath”的值实际上就是”D:\Program Files\SoftEther\SoftEther.exe” service
如果用.INF文件的形式的话,就很简单明白了:

1
2
3
4
5
6
7
[Version]
Signature="$CHICAGO$"
[DefaultInstall]
AddReg=Folders_AddReg
[Folders_AddReg]
HKCU,"Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders","Cookies",0x00020000,"%USERPROFILE%\Cookies"
HKLM,"SYSTEM\CurrentControlSet\Services\SoftEther","ImagePath",0x020000,"""D:\Program Files\SoftEther\SoftEther.exe"" service"

这个时候可以手工修改里面的路径信息,而.REG文件则很难做到这一点。

用.INF文件编辑.INI文件

.INF文件可以使用UpdateInis命令修改.INI文件的功能也经常需要,UpdateInis的语法如下:

1
2
3
UpdateInis = update-ini-section[,update-ini-section]...
[ update-ini-section-name]
ini-file, ini-section, [old-ini-entry], [new-ini-entry], [flags]

[update-ini-section-name]节给出的 .INF 文件中替换、删除或添加的全部条目。
ini-file 包含要更改条目的 .ini 文件名。 ini-section 包含要更改条目的节名。 old-ini-entry 可选,常用形式为 Key=Value。new-ini-entry 可选,常用形式为 Key=Value。flags 是可选操作标记。
使用逻辑磁盘标识符 (LDID),可以方便的修改.INI文件中的路径信息,当然其他的条目也同样。举例如下: Total Commander ,是一套极佳的文件管理员,内含各种压缩与解压缩,类似NC般非常好用的工具,对于文件与路径的寻找,除一般的复制、删除、搬移、编辑等功能外,还有FTP功能(具有续传、背景传输)与解决了中文乱码问题,”专题”再也不会变成”彩题”、新增文件分割、文件合并、文件编码、文件解码(MIME,UUE,XXE)及新的操作介面(浮动工具列)。真是一套相当强悍可完全取代文件总管的工具程序。
Total Commander依靠wincmd.ini来配置相应的操作特性和功能,于是可以使用如下的.INF文件修改wincmd.ini中的路径信息:

1
2
3
4
5
6
7
8
9
10
11
[version]
Signature="$CHICAGO$"
[DefaultInstall]
AddReg=AddGhister
UpdateInis=UpdateInicmd
[AddGhister]
HKCU,"Software\Ghisler\Total Commander","IniFileName",0,".\\wincmd.ini"
HKCU,"Software\Ghisler\Total Commander","FtpIniName",0,".\\wcx_ftp.ini"
[UpdateInicmd]
%01%\wincmd.ini, Configuration,,"InstallDir=%01%"
%01%\wincmd.ini, Configuration,,"Mainmenu=%01%\LANGUAGE\TCExtMenu.mnu"

其中 [AddGhister]节负责修改注册表中记录的wincmd.ini的路径,而[UpdateInicmd]节负责修改wincmd.ini文件红的相应路径信息,可以看出,一个简单的.INF文件就完成了修改Total Commander的路径的任务,在Total Commander5.x版本中,必须修改wincmd.ini文件中的路径信息,这个时候使用.INF文件是非常方便的。

用.INF文件删除正在使用的文件

有时候由于某些文件正被操作系统使用而无法删除,如某些用于资源管理器的OCX控件,可以使用.INF文件的DelFiles命令删除,该命令如果发现要删除的文件被锁定,就会把文件放到系统删除队列中排队,等系统重启动的时候,该文件就自动被删除了。
Delfiles的语法是:

1
2
3
Delfiles= file-list-section [,file-list-section]...
[file-list-section]
filename,,,1

[file-list-section]节定义了将要删除的文件列表,filename后面的1是一个标志,指明如果文件当前无法删除,就等到系统重启动后删除。把下面的这段代码复制到记事本里,另存为delinuse.inf,把这个文件拷贝到无法删除的文件的目录,然后右击它选择“安装(I)”,就可以删除当前目录下正在使用的setup.exe和setup2.exe。

1
2
3
4
5
6
7
8
9
10
[Version]
Signature="$Chicago$"
 
[DestinationDirs]
DefaultDestDir = 01 ; 当前目录 ,定义了将要删除的文件的路径
[DefaultInstall]
DelFiles = DELETELIST
[DELETELIST]
setup.exe ,,,1; 将要删除的文件
setup2.exe ,,,1; 将要删除的文件

同样可以使用Copyfiles命令替换系统正在访问的文件。这些功能通过普通的del和copy命令都无法实现,如果不使用.INF文件,必须使用第三方的软件来完成。

辅助制作绿色软件

在注册表.REG文件中,不可以使用变量,这个缺陷对于需要设置路径的安装程序来说,是非常致命的弱点,.REG文件中的路径都是静态的,一旦写好,就不会随着系统的变化而变化,如果需要把安装的程序从C盘改变到D盘,而在.REG文件中记录了安装路径的话,这个时候直接倒入注册表文件.REG是不行的,导入的注册表仍然是原来写入的路径。而在.INF文件中,可以使用变量来操纵路径,从而可以跟踪安装程序所需要的路径的变化。
对于绿色软件的制作,可以看我写的另外的专门的文章——绿色软件的制作,其中核心的一点就是获得原来软件的安装程序所做出的注册表的改变,然后把该变化导出为一个注册表文件.REG来进一步分析。如果导出的.REG文件不包括绝对路径,那么可以把该注册表文件和提取出的软件打包在一起做成绿色软件。如果导出的.REG文件中包含当前软件的绝对安装路径,那么就必须每次都要手工修改注册表中路径,是很麻烦的,降低了做成绿色软件的意义所在。而使用.INF文件,使用AddReg命令可以轻松容易的解决这个注册表路径的难题。

对于绿色软件的安装制作来说,最重要的就是01,也就是源文件夹。下面举一个例子:
Registry Crawler V4.5 ,是强大的用户和开发者快速定位并配置注册表的工具软件。一个强大的搜索引擎允许你基于搜索标准查找注册信息。(可以从天空软件站下载http://www4.skycn.com/soft/2963.html),安装完成后导出的注册表包含着如下一条语句:

1
2
3
4
5
6
7
8
9
10
[HKEY_LOCAL_MACHINE\SOFTWARE\4Developers\RCrawler\AppPath]
@="F:\\tools\\Reg\\RCrawler"
;其中“F:\tools\Reg\RCrawler”是安装路径。
;而改写为.INF文件就是:
[version]
Signature="$CHICAGO$"
[DefaultInstall]
AddReg=Add
[Add]
HKLM,"SOFTWARE\4Developers\RCrawler\AppPath","",0,"%01%"

注意里面的%01%就代表当前的安装路径。

当我们把F:\tools\Reg\RCrawler这个目录下的文件移动到其他目录时候,要用.REG文件的方式的话,就必须手工修改注册表文件,而使用前面的.INF文件的时候,什么都无需修改,只要在文件管理器explorer里面,用鼠标右键执行“安装”命令的时候,%01%就自动被替换为当前所在的目录了。

最后,总结一句,注册表文件.REG非常方便和直观,但是对于处理路径的变化的情况,非常笨拙和不方便,而.INF不如注册表文件直观,但是可以方便的处理路径信息(包括UNICODE的路径信息),所以应该把.REG文件和.INF文件结合使用,互相弥补各自的缺点。

.INF文件的生成方法
可以直接手工用一个纯文本的编辑器书写.INF文件,当相对应的.REG文件非常庞大,条目比较多时候,可以用小工具reg2inf.exe来自动的把.REG文件转换为.INF文件,然后再进行相应的路径修改,把绝对路径替换为用逻辑磁盘标识符 (LDID) 来表示的路径。
如果涉及到文件操作的时候,只好手工写了,目前还没有自动化的工具。

inf 文件的好处是 不像vbs那么强大,甚至有可能由危险的格式化代码
inf的限制很强,这样比其他的脚本文件安全,当然相对的功能就弱,但是也足够了
以上谈到的都是我平时使用.INF文件的经验和一点学习心得,欢迎大家提出不同意见和看法,进行讨论

原创文章,转载请注明: 转载自 obaby@mars

本文标题: 《驱动开发学习笔记(4-2)–INF文件-2》

本文链接地址: http://h4ck.org.cn/2009/10/inf-2/

You may also like

发表评论

电子邮件地址不会被公开。 必填项已用*标注