VS2008 开发驱动程序(续)

4.       WDM驱动开发示例

4.1   项目属性配置

1. 打开VS2008,新建一个Visual C++  à  Win32 à win32空项目。例如WdmDemo2. 打开VS2008 的“生成”菜单中的“配置管理器”选项。在活动解决方案配置中选择《新建》,新建一个Check空的解决方案配置。

3.       在解决方案管理器中,新建一个WdmDemo.h头文件,一个WdmDemo.cpp源文件。

4.       打开VS2008的“项目”菜单里面“属性”选项。即打开WdmDemo项目属性页。在项目属性页选择“配置属性”,打开十字图标。

5.       选择“C/C++”并展开内部选项。

在“常规”选项中,在“附加包含目录”中添加wdk 引用头文件目录。并去除“从父级或项目默认设置继承”复选框的勾选。Wdk头文件目录如下:

                           D:/WinDDK/7600.16385.0/inc/api

                           D:/WinDDK/7600.16385.0/inc/crt

                           D:/WinDDK/7600.16385.0/inc/ddk

                           注意笔者的WDK安装目录在D盘。

                  在“调试信息格式”中选择 C7 兼容(/Z7)”选项。

                  在“警告等级”中选择“3级(/W3)”。

                  在“将警告视为错误”中选择“是(/WX)”。

在“优化”选项中,在“优化”中选择“禁用(/Od)”。

在“预处理器”选项中,在“预处理器定义”中添加             WIN32=100;_X86_=1;WINVER=0x501;DBG=1”。并去除“从父级或项目默认属性继承”复选框的勾选。

在“高级”选项中,选择“调用约定”为“__stdcall  (/Gz)”。

6.       选择“链接器”并展开内部选项。

在“常规”选项中,修改“输出文件”的文件扩展名为 .sys 添加“附加库目录”

                           D:/WinDDK/7600.16385.0/lib/Crt/i386

                           D:/WinDDK/7600.16385.0/lib/wxp/i386

并去除“从父级或项目默认设置继承”复选框的勾选。

在“输入”选项中,添加“附加依赖项”ntoskrnl.lib并去除“从父级或项目默认设置继承”复选框的勾选。

在“清单文件”选项中,选择“生成清单”为否。

在“调试”选项中,选择“生成调试信息”为“是 /Debug)”。

在“系统”选项中,选择“子系统”为“本机 /SUBSYSTEM:NATIVE)”。选择“驱动程序”为“WDM (/DRIVER:WDM”。

在“高级”中,添加“入口点”为DriverEntry。选择“随即基址”为“默认值”。选择“数据执行保护”为默认值。选择“目标计算机”为“MachineX86(/MACHINE:X86)”。

            在“命令行”选项中,添加“/SECTION:INIT,D /IGNORE:4078”。

4.2   示例代码简介

/************************************************************************

* 文件名称:HelloWDM.h                                                

*    :张帆

* 完成日期:2007-11-1

*************************************************************************/

 

#ifdef __cplusplus

extern "C"

{

#endif

#include <wdm.h>

#ifdef __cplusplus

}

#endif

 

typedef struct _DEVICE_EXTENSION

{

     PDEVICE_OBJECT fdo;

     PDEVICE_OBJECT NextStackDevice;

     UNICODE_STRING ustrDeviceName;   // 设备名

     UNICODE_STRING ustrSymLinkName;  // 符号链接名

} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

 

#define PAGEDCODE code_seg("PAGE")

#define LOCKEDCODE code_seg()

#define INITCODE code_seg("INIT")

 

#define PAGEDDATA data_seg("PAGE")

#define LOCKEDDATA data_seg()

#define INITDATA data_seg("INIT")

 

#define arraysize(p) (sizeof(p)/sizeof((p)[0]))

 

NTSTATUS HelloWDMAddDevice(IN PDRIVER_OBJECT DriverObject,

                           IN PDEVICE_OBJECT PhysicalDeviceObject);

NTSTATUS HelloWDMPnp(IN PDEVICE_OBJECT fdo,

                        IN PIRP Irp);

NTSTATUS HelloWDMDispatchRoutine(IN PDEVICE_OBJECT fdo,

                                      IN PIRP Irp);

void HelloWDMUnload(IN PDRIVER_OBJECT DriverObject);

 

extern "C"

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,

                         IN PUNICODE_STRING RegistryPath);

  

/************************************************************************

* 文件名称:HelloWDM.cpp                                                

*    :张帆

* 完成日期:2007-11-1

*************************************************************************/

#include "WdmDemo.h"

 

/************************************************************************

* 函数名称:DriverEntry

* 功能描述:初始化驱动程序,定位和申请硬件资源,创建内核对象

* 参数列表:

      pDriverObject:I/O管理器中传进来的驱动对象

      pRegistryPath:驱动程序在注册表的中的路径

* 返回值:返回初始化驱动状态

*************************************************************************/

#pragma INITCODE

extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,

                                     IN PUNICODE_STRING pRegistryPath)

{

     KdPrint(("Enter DriverEntry/n"));

 

     pDriverObject->DriverExtension->AddDevice = HelloWDMAddDevice;

     pDriverObject->MajorFunction[IRP_MJ_PNP] = HelloWDMPnp;

     pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =

     pDriverObject->MajorFunction[IRP_MJ_CREATE] =

     pDriverObject->MajorFunction[IRP_MJ_READ] =

     pDriverObject->MajorFunction[IRP_MJ_WRITE] = HelloWDMDispatchRoutine;

     pDriverObject->DriverUnload = HelloWDMUnload;

 

     KdPrint(("Leave DriverEntry/n"));

     return STATUS_SUCCESS;

}

 

/************************************************************************

* 函数名称:HelloWDMAddDevice

* 功能描述:添加新设备

* 参数列表:

      DriverObject:I/O管理器中传进来的驱动对象

      PhysicalDeviceObject:I/O管理器中传进来的物理设备对象

* 返回值:返回添加新设备状态

*************************************************************************/

#pragma PAGEDCODE

NTSTATUS HelloWDMAddDevice(IN PDRIVER_OBJECT DriverObject,

                           IN PDEVICE_OBJECT PhysicalDeviceObject)

{

     PAGED_CODE();

     KdPrint(("Enter HelloWDMAddDevice/n"));

 

     NTSTATUS status;

     PDEVICE_OBJECT fdo;

     UNICODE_STRING devName;

     RtlInitUnicodeString(&devName,L"//Device//MyWDMDevice");

     status = IoCreateDevice(

         DriverObject,

         sizeof(DEVICE_EXTENSION),

         &(UNICODE_STRING)devName,

         FILE_DEVICE_UNKNOWN,

         0,

         FALSE,

         &fdo);

     if( !NT_SUCCESS(status))

         return status;

     PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;

     pdx->fdo = fdo;

     pdx->NextStackDevice = IoAttachDeviceToDeviceStack(fdo, PhysicalDeviceObject);

     UNICODE_STRING symLinkName;

     RtlInitUnicodeString(&symLinkName,L"//DosDevices//HelloWDM");

 

     pdx->ustrDeviceName = devName;

     pdx->ustrSymLinkName = symLinkName;

     status = IoCreateSymbolicLink(&(UNICODE_STRING)symLinkName,&(UNICODE_STRING)devName);

 

     if( !NT_SUCCESS(status))

     {

         IoDeleteSymbolicLink(&pdx->ustrSymLinkName);

         status = IoCreateSymbolicLink(&symLinkName,&devName);

         if( !NT_SUCCESS(status))

         {

              return status;

         }

     }

 

     fdo->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;

     fdo->Flags &= ~DO_DEVICE_INITIALIZING;

 

     KdPrint(("Leave HelloWDMAddDevice/n"));

     return STATUS_SUCCESS;

}

 

/************************************************************************

* 函数名称:DefaultPnpHandler

* 功能描述:PNP IRP进行缺省处理

* 参数列表:

      pdx:设备对象的扩展

      Irp:IO请求包

* 返回值:返回状态

*************************************************************************/

#pragma PAGEDCODE

NTSTATUS DefaultPnpHandler(PDEVICE_EXTENSION pdx, PIRP Irp)

{

     PAGED_CODE();

     KdPrint(("Enter DefaultPnpHandler/n"));

     IoSkipCurrentIrpStackLocation(Irp);

     KdPrint(("Leave DefaultPnpHandler/n"));

     return IoCallDriver(pdx->NextStackDevice, Irp);

}

 

/************************************************************************

* 函数名称:HandleRemoveDevice

* 功能描述:IRP_MN_REMOVE_DEVICE IRP进行处理

* 参数列表:

      fdo:功能设备对象

      Irp:IO请求包

* 返回值:返回状态

*************************************************************************/

#pragma PAGEDCODE

NTSTATUS HandleRemoveDevice(PDEVICE_EXTENSION pdx, PIRP Irp)

{

     PAGED_CODE();

     KdPrint(("Enter HandleRemoveDevice/n"));

 

     Irp->IoStatus.Status = STATUS_SUCCESS;

     NTSTATUS status = DefaultPnpHandler(pdx, Irp);

     IoDeleteSymbolicLink(&(UNICODE_STRING)pdx->ustrSymLinkName);

 

    //调用IoDetachDevice()fdo从设备栈中脱开:

    if (pdx->NextStackDevice)

        IoDetachDevice(pdx->NextStackDevice);

    

    //删除fdo

    IoDeleteDevice(pdx->fdo);

     KdPrint(("Leave HandleRemoveDevice/n"));

     return status;

}

 

/************************************************************************

* 函数名称:HelloWDMPnp

* 功能描述:对即插即用IRP进行处理

* 参数列表:

      fdo:功能设备对象

      Irp:IO请求包

* 返回值:返回状态

*************************************************************************/

#pragma PAGEDCODE

NTSTATUS HelloWDMPnp(IN PDEVICE_OBJECT fdo,

                        IN PIRP Irp)

{

     PAGED_CODE();

 

     KdPrint(("Enter HelloWDMPnp/n"));

     NTSTATUS status = STATUS_SUCCESS;

     PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;

     PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);

     static NTSTATUS (*fcntab[])(PDEVICE_EXTENSION pdx, PIRP Irp) =

     {

         DefaultPnpHandler,     // IRP_MN_START_DEVICE

         DefaultPnpHandler,     // IRP_MN_QUERY_REMOVE_DEVICE

         HandleRemoveDevice,         // IRP_MN_REMOVE_DEVICE

         DefaultPnpHandler,     // IRP_MN_CANCEL_REMOVE_DEVICE

         DefaultPnpHandler,     // IRP_MN_STOP_DEVICE

         DefaultPnpHandler,     // IRP_MN_QUERY_STOP_DEVICE

         DefaultPnpHandler,     // IRP_MN_CANCEL_STOP_DEVICE

         DefaultPnpHandler,     // IRP_MN_QUERY_DEVICE_RELATIONS

         DefaultPnpHandler,     // IRP_MN_QUERY_INTERFACE

         DefaultPnpHandler,     // IRP_MN_QUERY_CAPABILITIES

         DefaultPnpHandler,     // IRP_MN_QUERY_RESOURCES

         DefaultPnpHandler,     // IRP_MN_QUERY_RESOURCE_REQUIREMENTS

         DefaultPnpHandler,     // IRP_MN_QUERY_DEVICE_TEXT

         DefaultPnpHandler,     // IRP_MN_FILTER_RESOURCE_REQUIREMENTS

         DefaultPnpHandler,     //

         DefaultPnpHandler,     // IRP_MN_READ_CONFIG

         DefaultPnpHandler,     // IRP_MN_WRITE_CONFIG

         DefaultPnpHandler,     // IRP_MN_EJECT

         DefaultPnpHandler,     // IRP_MN_SET_LOCK

         DefaultPnpHandler,     // IRP_MN_QUERY_ID

         DefaultPnpHandler,     // IRP_MN_QUERY_PNP_DEVICE_STATE

         DefaultPnpHandler,     // IRP_MN_QUERY_BUS_INFORMATION

         DefaultPnpHandler,     // IRP_MN_DEVICE_USAGE_NOTIFICATION

         DefaultPnpHandler,     // IRP_MN_SURPRISE_REMOVAL

     };

 

     ULONG fcn = stack->MinorFunction;

     if (fcn >= arraysize(fcntab))

     {                           // 未知的子功能代码

         status = DefaultPnpHandler(pdx, Irp); // some function we don't know about

         return status;

     }                          

 

#if DBG

     static char* fcnname[] =

     {

         "IRP_MN_START_DEVICE",

         "IRP_MN_QUERY_REMOVE_DEVICE",

         "IRP_MN_REMOVE_DEVICE",

         "IRP_MN_CANCEL_REMOVE_DEVICE",

         "IRP_MN_STOP_DEVICE",

         "IRP_MN_QUERY_STOP_DEVICE",

         "IRP_MN_CANCEL_STOP_DEVICE",

         "IRP_MN_QUERY_DEVICE_RELATIONS",

         "IRP_MN_QUERY_INTERFACE",

         "IRP_MN_QUERY_CAPABILITIES",

         "IRP_MN_QUERY_RESOURCES",

         "IRP_MN_QUERY_RESOURCE_REQUIREMENTS",

         "IRP_MN_QUERY_DEVICE_TEXT",

         "IRP_MN_FILTER_RESOURCE_REQUIREMENTS",

         "",

         "IRP_MN_READ_CONFIG",

         "IRP_MN_WRITE_CONFIG",

         "IRP_MN_EJECT",

         "IRP_MN_SET_LOCK",

         "IRP_MN_QUERY_ID",

         "IRP_MN_QUERY_PNP_DEVICE_STATE",

         "IRP_MN_QUERY_BUS_INFORMATION",

         "IRP_MN_DEVICE_USAGE_NOTIFICATION",

         "IRP_MN_SURPRISE_REMOVAL",

     };

 

     KdPrint(("PNP Request (%s)/n", fcnname[fcn]));

#endif // DBG

 

     status = (*fcntab[fcn])(pdx, Irp);

     KdPrint(("Leave HelloWDMPnp/n"));

     return status;

}

 

/************************************************************************

* 函数名称:HelloWDMDispatchRoutine

* 功能描述:对缺省IRP进行处理

* 参数列表:

      fdo:功能设备对象

      Irp:IO请求包

* 返回值:返回状态

*************************************************************************/

#pragma PAGEDCODE

NTSTATUS HelloWDMDispatchRoutine(IN PDEVICE_OBJECT fdo,

                                      IN PIRP Irp)

{

     PAGED_CODE();

     KdPrint(("Enter HelloWDMDispatchRoutine/n"));

     Irp->IoStatus.Status = STATUS_SUCCESS;

     Irp->IoStatus.Information = 0;   // no bytes xfered

     IoCompleteRequest( Irp, IO_NO_INCREMENT );

     KdPrint(("Leave HelloWDMDispatchRoutine/n"));

     return STATUS_SUCCESS;

}

 

/************************************************************************

* 函数名称:HelloWDMUnload

* 功能描述:负责驱动程序的卸载操作

* 参数列表:

      DriverObject:驱动对象

* 返回值:返回状态

*************************************************************************/

#pragma PAGEDCODE

void HelloWDMUnload(IN PDRIVER_OBJECT DriverObject)

{

     PAGED_CODE();

     KdPrint(("Enter HelloWDMUnload/n"));

     KdPrint(("Leave HelloWDMUnload/n"));

}

4.3   安装调试示例

WDM驱动程序安装需要一个.inf安装文件来支持其安装,其实它只是一个文本文件。如果我们需要创建一个这样的文件,只需要新建一个文本文件,然后更改扩展名为.inf即可。WDK开发驱动程序包中有个CheckInf的控制台的调试工具可以帮助我们检查inf文件的语法错误。inf示例如下:

;--------- Version Section ---------------------------------------------------

 

[Version]

Signature="$CHICAGO$";

Provider=Zhangfan_Device

DriverVer=11/1/2007,3.0.0.3

 

; If device fits one of the standard classes, use the name and GUID here,

; otherwise create your own device class and GUID as this example shows.

 

Class=ZhangfanDevice

ClassGUID={EF2962F0-0D55-4bff-B8AA-2221EE8A79B0}

 

 

;--------- SourceDiskNames and SourceDiskFiles Section -----------------------

 

; These sections identify source disks and files for installation. They are

; shown here as an example, but commented out.

 

[SourceDisksNames]

1 = "WdmDemo",Disk1,,

 

[SourceDisksFiles]

WdmDemo.sys = 1,MyDriver_Check,

 

;--------- ClassInstall/ClassInstall32 Section -------------------------------

 

; Not necessary if using a standard class

 

; 9X Style

[ClassInstall]

Addreg=Class_AddReg

 

; NT Style

[ClassInstall32]

Addreg=Class_AddReg

 

[Class_AddReg]

HKR,,,,%DeviceClassName%

HKR,,Icon,,"-5"

 

;--------- DestinationDirs Section -------------------------------------------

 

[DestinationDirs]

YouMark_Files_Driver = 10,System32/Drivers

 

;--------- Manufacturer and Models Sections ----------------------------------

 

[Manufacturer]

%MfgName%=Mfg0

 

[Mfg0]

 

; PCI hardware Ids use the form

; PCI/VEN_aaaa&DEV_bbbb&SUBSYS_cccccccc&REV_dd

;改成你自己的ID

%DeviceDesc%=YouMark_DDI, PCI/VEN_9999&DEV_9999

 

;---------- DDInstall Sections -----------------------------------------------

; --------- Windows 9X -----------------

 

; Experimentation has shown that DDInstall root names greater than 19 characters

; cause problems in Windows 98

 

[YouMark_DDI]

CopyFiles=YouMark_Files_Driver

AddReg=YouMark_9X_AddReg

 

[YouMark_9X_AddReg]

HKR,,DevLoader,,*ntkern

HKR,,NTMPDriver,,WdmDemo.sys

HKR, "Parameters", "BreakOnEntry", 0x00010001, 0

 

; --------- Windows NT -----------------

 

[YouMark_DDI.NT]

CopyFiles=YouMark_Files_Driver

AddReg=YouMark_NT_AddReg

 

[YouMark_DDI.NT.Services]

Addservice = HelloWDM, 0x00000002, YouMark_AddService

 

[YouMark_AddService]

DisplayName = %SvcDesc%

ServiceType = 1 ; SERVICE_KERNEL_DRIVER

StartType = 3 ; SERVICE_DEMAND_START

ErrorControl = 1 ; SERVICE_ERROR_NORMAL

ServiceBinary = %10%/System32/Drivers/WdmDemo.sys

 

[YouMark_NT_AddReg]

HKLM, "System/CurrentControlSet/Services/HelloWDM/Parameters",/

"BreakOnEntry", 0x00010001, 0

 

 

; --------- Files (common) -------------

 

[YouMark_Files_Driver]

WdmDemo.sys

 

;--------- Strings Section ---------------------------------------------------

 

[Strings]

ProviderName="Zhangfan."

MfgName="Zhangfan Soft"

DeviceDesc="Hello World WDM!"

DeviceClassName="Zhangfan_Device"

SvcDesc="Zhangfan"

 第一次亦可直接复制进文本文件中进行创建。

WDM驱动的辅助安装程序为EvDriverInstaller.exe,可以从DriverStudio中提取,亦可从网上搜集。然后被EvDriverInstaller复制到虚拟机中,从“file”菜单中选择“Open”查找到.inf所在目录选择打开(注:驱动文件WdmDemo.sys需和.inf文件放在同一目录下),然后在程序界面的右下方有三个按钮“Add New Device”,“Remove Device”,“Restart Device”,点击“Add New Device”程序自动根据.inf设置安装WdmDemo.sys驱动程序。安装完毕后,可以在EvDriverInstaller程序中间的列表框中发现添加了一个项目一个问号图标及“Hello World WDM!”,同时打开我的电脑的“计算机管理”-》“设备管理器”,即可发现有个新的设备已经出现。名字为“Zhangfan_Device”。

本文原创,转载请注明出处。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
VS Code是一种非常强大的文本编辑,也是一种非常受欢迎的开发工具,可以用于开发各种类型的程序,包括驱动程序。以下是关于如何使用VS Code来开发驱动程序的一些重要方面的简要介绍。 1. 配置环境:首先,我们需要安装并配置Windows开发工具包(WDK)和Windows驱动程序框架(WDF)。这些工具包为开发者提供了用于创建、编译和调试驱动程序的必要工具和库。 2. 安装VS Code扩展:为了增强VS Code的驱动程序开发能力,我们可以安装一些非官方的扩展。例如,可以安装"vscode-windows-driver-kit"扩展来提供与WDK集成的功能。 3. 创建驱动程序项目:使用VS Code,我们可以方便地创建一个新的驱动程序项目。可以通过在终端中执行命令行来进行此操作,并指定所需的驱动类型和项目结构。 4. 编写驱动程序代码:VS Code提供了强大的代码编辑功能,支持多种编程语言和语法高亮。对于驱动程序开发,C和C++是主要的编程语言。我们可以使用VS Code的自动补全、调试和错误检查功能来帮助我们编写高质量的驱动程序代码。 5. 构建和编译:使用VS Code,我们可以配置构建和编译驱动程序的过程。可以使用相关的命令行工具来执行这些操作并生成驱动程序的二进制文件。 6. 调试和测试:VS Code提供了强大的调试功能,可以帮助我们定位和修复驱动程序中的错误。我们可以设置断点、监视变量值,并使用VS Code的调试来单步执行代码。 总之,使用VS Code可以方便地开发驱动程序。它提供了许多有用的功能和扩展,使其成为一种理想的选择。通过合理利用这些功能,我们可以更加高效和便捷地开发和调试驱动程序

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值