飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 2397|回复: 0

DriverEntry概述

[复制链接]
  • TA的每日心情
    慵懒
    2019-3-12 17:25
  • 签到天数: 3 天

    [LV.2]偶尔看看I

    发表于 2010-9-23 18:49:39 | 显示全部楼层 |阅读模式

    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。
    PYG19周年生日快乐!
    您需要登录后才可以回帖 登录 | 加入我们

    本版积分规则

    快速回复 返回顶部 返回列表