2.1驱动程序开发原理
在无操作系统的裸机中,或者类似如DOS这样操作系统中,应用程序和硬件的交互是非常简单的。如同牛郎织女,本来就睡在同一张床上,想怎么说悄悄话都行。可是现在情况有变,他们被天河分开了。要想见面聊几句,也要麻烦喜鹊来搭桥。在WINDOWS操作系统中,应用程序与硬件间的交互与此极其类似。如果没有操作系统,我们访问硬件空间可能只需一条指令就行,甚至可以访问任意的内存空间或者IO空间。因此应用程序和硬件就成了牛郎织女,被操作系统这个天河硬生生的隔开了。当应用程序要访问某个硬件或者内存空间时,就必须借助于喜鹊(驱动程序)了。至于为什么要把硬件层和应用程序隔开,答案是——安全。允许应用程序随意访问硬件是一件很危险的事情,除了可能会造成蓝屏死机之类的问题,还会发生密码的安全性问题。从这一点来说,上面的比喻还真是不够贴切,牛郎织女分开好像不是安全原因,无论比喻贴不贴切,还是往下继续吧。
应用程序访问驱动程序,要指定驱动程序的符号链接名,然后把要发送的信息发送出去。操作系统找到相关驱动程序,驱动程序把信息发动给指定硬件。如写信一样,驱动程序像邮差。
2.2应用程序寻找设备接口的方法——SetupDixx系列函数
2.2.1SetupDiGetClassDevs
函数定义
HDEVINFO
SetupDiGetClassDevs(
constGUID*ClassGuid,
PCTSTR Enumerator,
HWND hwndParent,
DWORD Flags
);
SetupDiGetClassDevs 获取一个指定类别或全部类别的所有已安装设备的信息
参数说明:
输入参数:
PGUID ClassGuid
在创建设备列表的时候提供一个指向GUID的指针。如果设定了标志DIGCF_ALLCLASSES,则这个参数可以忽略,且列表结果中包括所有已经安装的设备类别。
PCTSTR Enumerator
提供包含设备实例的枚举注册表分支下的键名,可以通过它获取设备信息。如果这个参数没有指定,则要从整个枚举树中获取所有设备实例的设备信息。
HWND hwndParent
提供顶级窗口的句柄,所有用户接口可以使用它来与成员联系。
DWORD Flags
提供在设备信息结构中使用的控制选项。可以是以下数值:
DIGCF_PRESENT - 只返回当前存在的设备。
DIGCF_ALLCLASSES - 返回所有已安装的设备。如果这个标志设置了,ClassGuid参数将被忽略。
DIGCF_PROFILE - 只返回当前硬件配置文件中的设备。
返回值:
HDEVINFO
如果函数运行成功,返回设备信息结构的句柄,该结构包含与指定参数匹配的所有已安装设备。如果失败,则返回INVALID_HANDLE_VALUE。调用GetLastError可以获得更多错误信息。
说明使用此函数,需要包含头文件setupapi.h。
此外,在project setting中的link页面需要添加setupapi.lib。
在setuapi.h中有如下定义:
typedef PVOID HDEVINFO;
即HDEVINFO是个无类型指针
2.1.2 SetupDiEnumDeviceInfo(SetupDiEnumDeviceInterface同样有memberindex 可以视情况定)
函数定义
BOOLEAN
SetupDiEnumDeviceInfo(
IN HDEVINFO DeviceInfoSet,
IN DWORD MemberIndex,
OUT PSP_DEVINFO_DATA DeviceInfoData
);
SetupDiEnumDeviceInfo 枚举指定设备信息集合的成员,并将数据放在PSP_DEVINFO_DATA中
参数说明:
DeviceInfoSet
提供一个设备信息集合的句柄
MemberIndex
指定一个要取得的设备信息成员序号,从0开始
DeviceInfoD