適用於 WDF 驅動程式的 DriverEntry 例程

[適用於 KMDF 和 UMDF]

DriverEntry 是載入驅動程式之後呼叫的第一個驅動程式提供的例程。 它負責初始化驅動程式。

語法

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

參數

DriverObject [in]
表示驅動程式 WDM 驅動程式物件的 DRIVER_OBJECT 結構的指標。

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
}

範例

下列程式代碼範例顯示 Serial (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