找回密码
 立即注册
搜索

编写 Hello World Windows 驱动程序 (KMDF)

2024-11-21 15:03| 发布者: admin| 查看: 38| 评论: 0|来自: 微软

摘要: 本文内容创建和生成驱动程序编写第一个驱动程序代码生成驱动程序部署驱动程序显示另外 3 个本文介绍如何使用 Kernel-Mode Driver Framework (KMDF) 编写小型通用 Windows驱动程序,然后在单独的计算机上部署和安装驱 ...
 

本文介绍如何使用 Kernel-Mode Driver Framework (KMDF) 编写小型 通用 Windows 驱动程序,然后在单独的计算机上部署和安装驱动程序。

在继续之前,请完成 下载 Windows 驱动程序工具包 (WDK) 中列出的安装步骤。

安装 WDK 时,需要包括 Windows 调试工具

创建和生成驱动程序

  1. 打开 Microsoft Visual Studio。 在“文件” 菜单上,选择“新建”>“项目” 。

  2. 在“新建项目”对话框的左侧下拉列表中,选择“C++”,在中间下拉列表中,选择“Windows”,然后在右侧下拉列表中,选择“驱动程序” 。

  3. 从项目类型列表中选择“内核模式驱动程序,空(KMDF)”。 选择“下一页”。

    Visual Studio“新建项目”对话框的屏幕截图,其中选择了“内核模式驱动程序”选项。

  4. 在“配置新项目”对话框中,在“项目名称”字段中输入“KmdfHelloWorld” 。

     备注

    在创建新的 KMDF 或 UMDF 驱动程序时,必须选择一个不多于 32 个字符的驱动程序名称。 此长度限制在 wdfglobals.h 中定义。

  5. 在“位置”字段中,输入要在其中创建新项目的目录。

  6. 选中“将解决方案和项目置于同一目录中”,然后选择“创建” 。

    Visual Studio“配置新项目”对话框的屏幕截图,其中突出显示了“创建”按钮。

    Visual Studio 将创建一个项目和一个解决方案。 可以在“解决方案资源管理器” 窗口中看到它们。 (如果解决方案资源管理器窗口不可见,请从“视图”菜单中选择“解决方案资源管理器”。) 解决方案具有名为 KmdfHelloWorld 的驱动程序项目。

    Visual Studio 解决方案资源管理器窗口的屏幕截图,其中显示了解决方案和名为 KmdfHelloWorld 的空驱动程序项目。

  7. “解决方案资源管理器”窗口中,选择并按住 (或右键单击) KmdfHelloWorld 解决方案,然后选择“Configuration Manager”。 为驱动程序项目选择配置和平台。 例如,选择“调试” 和“x64” 。

  8. “解决方案资源管理器”窗口中,再次选择并按住 (或右键单击) KmdfHelloWorld 项目,选择“添加”,然后选择“新建项”。

  9. 在“添加新项目”对话框中,选择“C++ 文件”。 对于“名称”,请输入“Driver.c”。

     备注

    文件扩展名为 .c,不是 .cpp

    选择 添加 。 Driver.c 文件添加在源文件下,如下所示。

    Visual Studio 解决方案资源管理器窗口的屏幕截图,其中显示了添加到驱动程序项目的 driver.c 文件。

编写第一个驱动程序代码

创建空的 Hello World 项目并添加 Driver.c 源文件以后,即可通过实现两个基本事件回调函数来编写驱动程序运行所需的最基本的代码。

  1. 在 Driver.c 中,首先包括以下头文件:

    C++
    #include <ntddk.h>
    #include <wdf.h>

     提示

    如果无法添加 Ntddk.h,请打开“配置”->“C/C++”->“常规”->“其他包含目录”并添加 C:\Program Files (x86)\Windows Kits\10\Include\<build#>\km,将 <build#> 替换为 WDK 安装中的相应目录。

    Ntddk.h 包含所有驱动程序的核心 Windows 内核定义,而 Wdf.h 包含基于 Windows 驱动程序框架 (WDF) 的驱动程序的定义。

  2. 接下来,为要使用的两个回调提供声明:

    C++
    DRIVER_INITIALIZE DriverEntry;
    EVT_WDF_DRIVER_DEVICE_ADD KmdfHelloWorldEvtDeviceAdd;
  3. 使用以下代码编写 DriverEntry

    C++
    NTSTATUS 
    DriverEntry(
    _In_ PDRIVER_OBJECT DriverObject,
    _In_ PUNICODE_STRING RegistryPath
    )

    {
    // NTSTATUS variable to record success or failure
    NTSTATUS status = STATUS_SUCCESS;

    // Allocate the driver configuration object
    WDF_DRIVER_CONFIG config;

    // Print "Hello World" for DriverEntry
    KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "KmdfHelloWorld: DriverEntry\n" ));

    // Initialize the driver configuration object to register the
    // entry point for the EvtDeviceAdd callback, KmdfHelloWorldEvtDeviceAdd
    WDF_DRIVER_CONFIG_INIT(&config,
    KmdfHelloWorldEvtDeviceAdd
    );

    // Finally, create the driver object
    status = WdfDriverCreate(DriverObject,
    RegistryPath,
    WDF_NO_OBJECT_ATTRIBUTES,
    &config,
    WDF_NO_HANDLE
    );
    return status;
    }

    DriverEntry 是所有驱动程序的入口点,就像 Main() 适用于许多用户模式应用程序一样。 DriverEntry 的任务是初始化驱动程序范围的结构和资源。 在此示例中,你针对 DriverEntry 输出了“Hello World”,将驱动程序对象配置为注册 EvtDeviceAdd 回调的入口点,然后创建了驱动程序对象并返回。

    驱动程序对象充当你可能在驱动程序中创建的所有其他框架对象的父对象,这些框架对象包括设备对象、I/O 队列、计时器、旋转锁等。 有关框架对象的详细信息,请参阅框架对象简介

     提示

    对于 DriverEntry,我们强烈建议将名称保留为“DriverEntry”,以便进行代码分析和调试。

  4. 接下来,使用以下代码编写 KmdfHelloWorldEvtDeviceAdd

    C++
    NTSTATUS 
    KmdfHelloWorldEvtDeviceAdd(
    _In_ WDFDRIVER Driver,
    _Inout_ PWDFDEVICE_INIT DeviceInit
    )

    {
    // We're not using the driver object,
    // so we need to mark it as unreferenced
    UNREFERENCED_PARAMETER(Driver);

    NTSTATUS status;

    // Allocate the device object
    WDFDEVICE hDevice;

    // Print "Hello World"
    KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "KmdfHelloWorld: KmdfHelloWorldEvtDeviceAdd\n" ));

    // Create the device object
    status = WdfDeviceCreate(&DeviceInit,
    WDF_NO_OBJECT_ATTRIBUTES,
    &hDevice
    );
    return status;
    }

    系统在检测到你的设备已到达时,会调用 EvtDeviceAdd。 它的任务是初始化该设备的结构和资源。 在此示例中,你仅针对 EvtDeviceAdd 输出了“Hello World”消息、创建了设备对象并返回。 在你编写的其他驱动程序中,可以为硬件创建 I/O 队列,为特定于设备的信息设置设备上下文存储空间,或执行准备设备所需的其他任务。

     提示

    对于设备添加回调,请注意以驱动程序名称为前缀对回调命名的方式 (KmdfHelloWorldEvtDeviceAdd)。 通常,我们建议以这种方式命名驱动程序功能,以区别于其他驱动程序的功能。 DriverEntry 是完全应该这样命名的唯一一项。

  5. 现在,整个 Driver.c 如下所示:

    C++
    #include <ntddk.h>
    #include <wdf.h>
    DRIVER_INITIALIZE DriverEntry;
    EVT_WDF_DRIVER_DEVICE_ADD KmdfHelloWorldEvtDeviceAdd;

    NTSTATUS
    DriverEntry(
    _In_ PDRIVER_OBJECT DriverObject,
    _In_ PUNICODE_STRING RegistryPath
    )

    {
    // NTSTATUS variable to record success or failure
    NTSTATUS status = STATUS_SUCCESS;

    // Allocate the driver configuration object
    WDF_DRIVER_CONFIG config;

    // Print "Hello World" for DriverEntry
    KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "KmdfHelloWorld: DriverEntry\n" ));

    // Initialize the driver configuration object to register the
    // entry point for the EvtDeviceAdd callback, KmdfHelloWorldEvtDeviceAdd
    WDF_DRIVER_CONFIG_INIT(&config,
    KmdfHelloWorldEvtDeviceAdd
    );

    // Finally, create the driver object
    status = WdfDriverCreate(DriverObject,
    RegistryPath,
    WDF_NO_OBJECT_ATTRIBUTES,
    &config,
    WDF_NO_HANDLE
    );
    return status;
    }

    NTSTATUS
    KmdfHelloWorldEvtDeviceAdd(
    _In_ WDFDRIVER Driver,
    _Inout_ PWDFDEVICE_INIT DeviceInit
    )

    {
    // We're not using the driver object,
    // so we need to mark it as unreferenced
    UNREFERENCED_PARAMETER(Driver);

    NTSTATUS status;

    // Allocate the device object
    WDFDEVICE hDevice;

    // Print "Hello World"
    KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "KmdfHelloWorld: KmdfHelloWorldEvtDeviceAdd\n" ));

    // Create the device object
    status = WdfDeviceCreate(&DeviceInit,
    WDF_NO_OBJECT_ATTRIBUTES,
    &hDevice
    );
    return status;
    }
  6. 保存 Driver.c。

此示例说明了驱动程序的基本概念:它们是一个“回调集合”,初始化后,会等待系统在需要时调用它们。 系统调用可以是新的设备到达事件、来自用户模式应用程序的 I/O 请求、系统电源关闭事件、来自另一个驱动程序的请求,或者当用户意外拔出设备时发生的意外删除事件。 幸运的是,就“Hello World”而言,只需操心驱动程序和设备的创建。

  1. “解决方案资源管理器”窗口中,选择并按住 (或右键单击) 解决方案“KmdfHelloWorld” (1 个项目) ,然后选择“Configuration Manager”。 为驱动程序项目选择配置和平台。 在本练习中,我们选择“调试”和“x64”。

  2. “解决方案资源管理器”窗口中,选择并按住 (或右键单击“) KmdfHelloWorld”,然后选择“属性”。 在“Wpp 跟踪”>“所有选项”中,将“运行 Wpp 跟踪”设置为“否”。 依次选择“应用”、“确定” 。

  3. 123下一页

    路过

    雷人

    握手

    鲜花

    鸡蛋

    相关分类

    QQ|Archiver|手机版|小黑屋|软件开发编程门户 ( 陇ICP备2024013992号-1|甘公网安备62090002000130号 )

    GMT+8, 2024-11-21 17:34 , Processed in 0.040604 second(s), 16 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.