- UID
- 66114
注册时间2010-4-1
阅读权限30
最后登录1970-1-1
龙战于野
TA的每日心情 | 慵懒 2019-3-12 17:25 |
---|
签到天数: 3 天 [LV.2]偶尔看看I
|
DriverEntry的第一个参数是一个指针,指向一个刚被初始化的驱动程序对象,该对象就代表你的驱动程序。WDM驱动程序的DriverEntry例程应完成对这个对象的初始化并返回。非WDM驱动程序需要做大量额外的工作,它们必须探测自己的硬件,为硬件创建设备对象(用于代表硬件),配置并初始化硬件使其正常工作。而对于WDM驱动程序,颇麻烦的硬件探测和配置工作由PnP管理器自动完成,我将在第六章讨论PnP。如果你想知道非WDM驱动程序是如何初始化自身的,参见Art Baker的《The Windows NT Device Driver Book
(Prentice Hall, 1997)》、Viscarola和Mason的《Windows NT Device Driver Development
(Macmillan, 1998)》。 DriverEntry的第二个参数是设备服务键的键名。这个串不是长期存在的(函数返回后可能消失),如果以后想使用该串就必须先把它复制到安全的地方。 对于WDM驱动程序的DriverEntry例程,其主要工作是把各种函数指针填入驱动程序对象。这些指针为操作系统指明了驱动程序容器中各种子例程的位置。它们包括下面这些指针成员(驱动程序对象中): - DriverUnload
指向驱动程序的清除例程。I/O管理器会在卸载驱动程序前调用该例程。通常,WDM驱动程序的DriverEntry例程一般不分配任何资源,所以DriverUnload例程也没有什么清除工作要做。 - DriverExtension->AddDevice
指向驱动程序的AddDevice函数。PnP管理器将为每个硬件实例调用一次AddDevice例程。由于AddDevice例程对WDM驱动程序特别重要,所以我将在本章下一节单独讲述它。 - DriverStartIo
如果驱动程序使用标准的IRP排队方式,应该设置该成员,使其指向驱动程序的StartIo例程。如果你不理解什么是“标准”排队方式,不要着急,到第五章你就会完全明白,许多驱动程序都使用这种方法。 - MajorFunction
是一个指针数组,I/O管理器把每个数组元素都初始化成指向一个哑派遣函数,这个哑派遣函数仅返回失败。驱动程序可能仅需要处理几种类型的IRP,所以至少应该设置与那几种IRP类型相对应的指针元素,使它们指向相应的派遣函数。我将在第五章详细讨论IRP和派遣函数。现在,你仅需要知道至少有三种IRP必须处理。
下面是一个近乎完整的DriverEntry例程: extern "C"
NTSTATUS
DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
DriverObject->DriverUnload = DriverUnload; <--1
DriverObject->DriverExtension->AddDevice = AddDevice;
DriverObject->DriverStartIo = StartIo;
DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp; <--2
DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower;
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = DispatchWmi;
... <--3
servkey.Buffer = (PWSTR) ExAllocatePool(PagedPool, RegistryPath->Length + sizeof(WCHAR)); <--4
if (!servkey.Buffer)
return STATUS_INSUFFICIENT_RESOURCES;
servkey.MaximumLength = RegistryPath->Length + sizeof(WCHAR);
RtlCopyUnicodeString(&servkey, RegistryPath);
return STATUS_SUCCESS; <--5
} |
- 前三条语句为驱动程序的其它入口点设置了函数指针。在这里,我用了能表达其功能的名字命名了这些函数:DriverUnload、AddDevice、StartIo。
- 每个WDM驱动程序必须能处理PNP、POWER、SYSTEM_CONTROL这三种请求;应该在这里为这些请求指定派遣函数。在早期的Windows 2000 DDK中,IRP_MJ_SYSTEM_CONTROL曾被称作IRP_MJ_WMI,所以我把系统控制派遣函数命名为DispatchWmi。
- 在省略号处,你可以插入设置其它MajorFunction指针的代码。
- 如果驱动程序需要访问设备的服务键,可以在这里备份RegistryPath串。例如,如果驱动程序要作为WMI生产者(见第十章),则需要备份这个串。这里我假设已经在某处声明了一个类型为UNICODE_STRING的全局变量servkey。
- 返回STATUS_SUCCESS指出函数成功。如果函数失败,应该返回NTSTATUS.H中的一个错误代码,或者返回用户定义的错误代码。STATUS_SUCCESS的值为0。
|
|