How to install driver on Windows 2000/XP Platform

| | 评论(0)

How to install driver on Windows 2000/XP Platform

再贴旧文。一个不好的新闻是,Windows 2003将不能用这篇文章里写到的方法了。革命永远进步,学习成就未来,呵呵。两个text-area里的文字被blog-city加了
符号,没有什么办法,可以把它拷出来存成HTML文件。

在Windows2000/XP上如何安装驱动程序

by Mach, Apr 10, 2003

 

这里讨论在Windows 2000/XP平台上如何安装一个硬件驱动程序。软件虚拟驱动程序将会有所不同,下次再说。

在Windows2000和WindowsXP上,Microsoft推荐的方式是单独的inf文件和sys以及cat文件。当系统提示找到新硬件时,用户手工引导到厂商提供inf文件安装。这种方式一个最大的缺点就是,厂商必须通过WHQL测试并获得数字签名文件(*.cat). 而且,如果不希望用户参与安装过程怎么办?

一种通行的办法是,用安装工具(例如InstallShiled, Wise, Orca等产品)做一个安装包来安装。在做安装包前,需要准备:驱动程序(假设是abc.sys,当然也有可能是多个)和abc.inf文件。注意:abc.inf中不要有拷贝自己或*.sys的内容。

具体Inf文件的写法可以参考DDK的文档。下面是一个简单的例子,一个用同一个driver支持Abc Technology Coporation(这是虚构的一家公司)的PCI-ABC和PCMCIA-ABC卡的inf文件。注意abc.inf文件里不要写copyfiles. Abc.inf实现了自己的设备类:Abc. 一个驱动并不一定要自己实现设备类,因为Microsoft已经预定义了一些设备类,例如4D36E965-E325-11CE-BFC1-08002BE10318就是DVD/CD-ROM drivers类,可以使用这些预定义的类。系统里已经安装的设备类可以在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class中看到。对Abc驱动程序来说,系统检测到硬件并正确安装了Abc驱动后HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class就会出现Abc设备类的GUID和实例。

安装包要做的事情:

1.拷贝文件。
abc.sys -> $(WINNT)\System32\DRIVERS
abc.inf -> $(WINNT)\inf
如果有数字验证文件,abc.cat -> $(WINNT)\System32\DRIVERS, 注意在inf文件里要加一行。

2.写注册表
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\abc]
"ImagePath"="System32\\DRIVERS\\abc.sys"
"ErrorControl"=dword:00000000
"Start"=dword:00000003
"Type"=dword:00000001
"Group"="ExtendedBase"
其实这一步应该可以不要的,因为这些值可以从inf文件生成。但开发商可能会需要指定start值,就可以在这里指定。

3.在安装程序里调用一些SetupAPI。通常是写一个标准DLL,在安装程序里调用DLL里面的函数入口。

#include
#pragma comment( lib, "setupapi")
#include
#pragma comment( lib, "C:\\NTDDK\\libfre\\i386\\newdev.lib")
#include
#include

UINT __stdcall CopyAbcNT5Inf(void)
{
BOOL ret = FALSE;
UINT n = 0;

TCHAR strWinDir[_MAX_PATH], strInf[_MAX_PATH], strInfDes[_MAX_PATH];
ZeroMemory( strWinDir, _MAX_PATH*sizeof(TCHAR));
ZeroMemory( strInf, _MAX_PATH*sizeof(TCHAR));
ZeroMemory( strInfDes, _MAX_PATH*sizeof(TCHAR));

// Get the Windows Directory path
n = GetWindowsDirectory(strWinDir, _MAX_PATH);
if( n == 0)
return FALSE;

// Append the name of the INF file
_tcscpy( strInf, strWinDir);
_tcscat( strInf, _T( "\\Inf\\abc.inf"));

// Call SetupCopyOEMInf() to invoke Windows to generate the PNF(procompiled INF file) file abc.PNF
ret = SetupCopyOEMInf( strInf, NULL, SPOST_NONE,
0, strInfDes, _MAX_PATH, NULL, NULL);
if( !ret)
return ret;

BOOL bRebootRequired = FALSE;
BOOLEAN bRet=0;


bRet = UpdateDriverForPlugAndPlayDevices( NULL, _T("PCMCIA\\ABC_Technology-PCMCIA-ABC/2-3D57"),
strInfDes, INSTALLFLAG_FORCE, &bRebootRequired);

bRet = UpdateDriverForPlugAndPlayDevices( NULL, _T("PCI\\VEN_9010&DEV_9008&SUBSYS_00000000&REV_00"),
strInfDes, INSTALLFLAG_FORCE, &bRebootRequired);

return ret;
}

例子如上。首先用SetupCopyOEMInf把abc.inf拷贝到$(WINNT)\inf目录中去。这里是已经用安装程序拷贝到同一个目录了,目的是为了保持执行SetupCopyOEMInf后abc.inf的名字不变,否则,如果是从其它目录拷贝到$(WINNT)\inf,文件名会被改为oem1.inf这样的形式。

UpdateDriverForPlugAndPlayDevices的作用是:如果硬件在安装软件之前已经安装在系统里了,在Device Manager里面可以看到一个带黄色感叹号或问号的设备。UpdateDriverForPlugAndPlayDevices会为这些设备更新驱动。

注意UpdateDriverForPlugAndPlayDevices是Windows DDK的function, 必须链接DDK的newdev.lib库。另外,Windows SDK里有个叫INFINST的例子,用SETUP API读出INF的各个项并执行动作。DDK下面也有个setup, 不过是命令行的,但调用了一些 Setup API去生成一个虚拟的设备(在Device Manager里可以看到)。

注意:在最终发行之前,必须在各种平台(Windows 2000 Professional, Windows 2000 Server, Windows XP, all kinds of version and all kinds of Service Packs)上完全测试。测试必须在干净的系统上进行,并覆盖硬件先装和软件先装的情况。一种可能出现的问题是:UpdateDriverForPlugAndPlayDevices在XP上会陷入死循环。这种情况需要在Windows XP DDK上编译一个版本,而在2000上使用Windows 2000 DDK编译一个版本。

4. 最后,安装硬件。系统应该自动找到PnP硬件并搜索inf目录,自动找到并安装合适的驱动,不需要人工介入。无论是Windows 2000还是XP都不会提示驱动缺少认证。有资料说为了不出现缺少认证警告需要改本地策略,也就是设置:
[HKLM\Software\Microsoft\Driver Signing\Policy]
可选的值:忽略:0x00000000 警告:0x00000001 阻止:0x00000002
在安装中改这个值,安装完毕再改回来。注意:这个值在Windows XP里不能修改。在实际测试中我发现按本文的方法不需要如此修改,就已经不会出现警告了。不过新硬件插入的时候,需要让XP自动寻找驱动一次(2000不需如此)。

posted 2004.02.16 Monday

分类

发表评论

关于此日记

此日记由mach发表于2004年2月16日 00:50

此Blog上的上一篇日记如何产生一个只有资源没有DllMain()的DLL

此Blog上的下一篇日记[Joke]现场总线的难题 (from GongKong.com)

主索引归档页可以看到最新的日记和所有日记。

Powered by Movable Type 4.0