WDF 驱动程序例程的 DriverEntry

[适用于 KMDF 和 UMDF]

DriverEntry 是在加载驱动程序后调用的第一个驱动程序提供的例程。 它负责初始化驱动程序。

语法

NTSTATUS DriverEntry(
  _In_ PDRIVER_OBJECT  DriverObject,
  _In_ PUNICODE_STRING RegistryPath
);

参数

DriverObject [in]
指向 DRIVER_OBJECT 结构的指针,该结构表示驱动程序的 WDM 驱动程序对象。

RegistryPath [in]
指向 UNICODE_STRING 结构的指针,该结构指定注册表中驱动程序 的 Parameters 键 的路径。

返回值

如果例程成功,则必须返回STATUS_SUCCESS。 否则,它必须返回 ntstatus.h 中定义的错误状态值之一。

注解

与所有 WDM 驱动程序一样,基于框架的驱动程序必须具有 DriverEntry 例程,该例程在加载驱动程序后调用。 基于框架的驱动程序的 DriverEntry 例程必须:

  • 激活 WPP 软件跟踪

    DriverEntry 应包含用于激活软件跟踪 的WPP_INIT_TRACING 宏。

  • 调用 WdfDriverCreate

    调用 WdfDriverCreate 使驱动程序能够使用 Windows 驱动程序框架接口。 (驱动程序在调用 WdfDriverCreate.) 之前无法调用其他框架例程

  • 分配可能需要的任何非特定于设备的系统资源和全局变量。

    通常,驱动程序将系统资源与单个设备相关联。 因此,基于框架的驱动程序在 EvtDriverDeviceAdd 回调中分配大多数资源,该回调在检测到单个设备时调用。

    由于 UMDF 驱动程序的多个实例可能由单独的 Wudfhost 实例承载,因此全局变量可能无法在 UMDF 驱动程序的所有实例中使用。

  • 从注册表获取特定于驱动程序的参数。

    某些驱动程序从注册表获取参数。 这些驱动程序可以调用 WdfDriverOpenParametersRegistryKey 以打开包含这些参数的注册表项。

  • 提供 DriverEntry 返回值

注意 UMDF 驱动程序在用户模式主机进程中运行,而 KMDF 驱动程序在系统进程中以内核模式运行。 框架可能会将 UMDF 驱动程序的多个实例加载到主机进程的单独实例中。 因此:

  • 如果框架在不同主机进程中加载驱动程序的实例,则框架可能会多次调用 UMDF 驱动程序的 DriverEntry 例程。 相比之下,框架只调用 KMDF 驱动程序的 DriverEntry 例程一次。
  • 如果 UMDF 驱动程序在其 DriverEntry 例程中创建全局变量,该变量可能不可用于驱动程序的所有实例。 但是,KMDF 驱动程序在其 DriverEntry 例程中创建的全局变量可用于驱动程序的所有实例。

有关何时调用基于框架的驱动程序的 DriverEntry 例程的详细信息,请参阅 生成和加载 WDF 驱动程序

DriverEntry 例程未在 WDK 标头中声明。 静态驱动程序验证程序 (SDV) 和其他验证工具可能需要如下声明:

DRIVER_INITIALIZE MyDriverEntry;

NTSTATUS
DriverEntry(
    IN PDRIVER_OBJECT  DriverObject,
    IN PUNICODE_STRING  RegistryPath
    )
{
// Function body
}

示例

下面的代码示例演示串行 (KMDF) 示例驱动程序的 DriverEntry 例程。

NTSTATUS
DriverEntry(
    IN PDRIVER_OBJECT  DriverObject,
    IN PUNICODE_STRING  RegistryPath
    )
{
    WDF_DRIVER_CONFIG  config;
    WDFDRIVER  hDriver;
    NTSTATUS  status;
    WDF_OBJECT_ATTRIBUTES  attributes;
    SERIAL_FIRMWARE_DATA driverDefaults;

    //
    // Initialize WPP tracing.
    //
    WPP_INIT_TRACING(
                     DriverObject,
                     RegistryPath
                     );

    SerialDbgPrintEx(
                     TRACE_LEVEL_INFORMATION,
                     DBG_INIT,
                     "Serial Sample (WDF Version) - Built %s %s\n",
                     __DATE__, __TIME__
                     );
    //
    // Register a cleanup callback function (which calls WPP_CLEANUP)
    // for the framework driver object. The framework will call
    // the cleanup callback function when it deletes the driver object,
    // before the driver is unloaded.
    //
    WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
    attributes.EvtCleanupCallback = SerialEvtDriverContextCleanup;

    WDF_DRIVER_CONFIG_INIT(
                           &config,
                           SerialEvtDeviceAdd
                           );

    status = WdfDriverCreate(
                             DriverObject,
                             RegistryPath,
                             &attributes,
                             &config,
                             &hDriver
                             );
    if (!NT_SUCCESS(status)) {
        SerialDbgPrintEx(
                         TRACE_LEVEL_ERROR,
                         DBG_INIT,
                         "WdfDriverCreate failed with status 0x%x\n",
                         status
                         );
        //
        // Clean up tracing here because WdfDriverCreate failed.
        //
        WPP_CLEANUP(DriverObject);
        return status;
    }

    //
    // Call an internal routine to obtain registry values
    // to use for all the devices that the driver 
    // controls, including whether or not to break on entry.
    //
    SerialGetConfigDefaults(
                            &driverDefaults,
                            hDriver
                            );

    //
    // Break on entry if requested bt registry value.
    //
    if (driverDefaults.ShouldBreakOnEntry) {
        DbgBreakPoint();
    }

    return status;
}

另请参阅

WdfDriverCreate

EvtDriverDeviceAdd