• 【原创】《windows驱动开发技术详解》第4章实验总结二


    1 实验要求(WDM驱动)
     

     
    2 编写过程
     
    2.1 确立整体架构
     
    2.1.1 入口函数——DriverEntry
     
    (1)作用
    • 设置pDriverObject结构体,注册AddDevice和相关PNP函数,包括IRP_MJ_PNP,IRP_MJ_CREATE等
    (2)注意
    • AddDevice在Driver_Object结构体的DriverExtension->AddDevice,原型是NTSTATUS AddDevice (PDRIVER_OBJECT pDriverObject, PDEVICE_OBJECT PhysicaPhysicalDeviceObject);因为它需要一个最基本的驱动对象以及用于附加的物理设备对象
    • 注册IRP_MJ_PNP请求函数,IRP请求函数的返回值和形参类型都一样
    • 注册IRP_MJ_CREATE、 IRP_MJ_READ、IRP_MJ_WRITE、IRP_MJ_CLOSE请求,这里注册为同一个函数
     
    2.1.2 添加设备——AddDevice
     
    (1)作用
    • 该函数由系统调用,用于创建设备对象,符号链接、附加到PDO
    (2)注意
    • 顺序问题:创建设备对象->符号链接->附加到PDO->设置设备拓展->设置设备对象Flags;符号链接最好紧接放在创建设备对象之后,后面三步位置可以随意,这样做是因为当符号链接创建失败后,要删除设备对象。如果把PDO后面三步放在符号链接前,如果没有对PDO进行脱离,再删除设备对象会产生问题;造成时间浪费。
    • 附加到PDO函数:IoAttachDeviceToDeviceStack,注意返回值,返回的是附加设备的下层设备,如果没有过滤驱动,那么就是PDO。
    • pDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;这一步是必需的,保证设备初始化完毕。
     
    2.1.3 驱动卸载——DriverUnLoad
     
    (1)作用
    • 这个和NT驱动有点区别,NT驱动要删除设备对象和符号链接,以及释放资源。而WDM的只需要释放资源即可。
    (2)注意
    • 返回值为VOID
     
    2.1.4 驱动卸载——IRP_MN_REMOVE_DEVICE请求处理
     
    (1)作用
    • 删除设备对象和符号链接,脱离PDO
    (2)注意
    • 这个请求处理函数,名字自定义,但是返回值NTSTATUS,形参是PDEVICE_OBJECT和PIRP,这和所有PNP请求处理函数都一样
    • 要对IRP的返回状态进行设置,主要是IoStatus.Status和IoStatus.Information
    • IRP请求可以继续向底层转发,IoCallDriver
    • IoDetachDevice的实参是被附加的设备对象
    • 删除时,如果设备对象的NextDevice域不为空也要删除
     
    2.1.5 PNP请求处理——IRP_MJ_PNP
     
    (1)作用
    • 处理各种类型PNP请求
    (2)注意
    • (根据Major分,这是一个大类)IRP_MJ_PNP请求,根据其Minor值还分了多种类型的PNP。
    • 函数内部,主要就是从当前IRP堆栈里获取Minor值,然后再调用相应的处理函数,比如上文的IRP_MN_REMOVE_DEVICE
    • 获取Minor值方法:PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);ULONG fcn = stack->MinorFunction;
    • 要知道PNP的请求列表,对于IRP_MN类的请求处理,如果是要转发到下一层则可以不用对IoStatus的返回情况进行设置,否则要对其进行设置
     
    2.1.6 PNP请求Minor值对应的请求的默认处理
     
    (1)作用
    • 处理具体类型PNP请求
    (2)注意
    • 对于IRP_MN类的请求处理,如果是要转发到下一层则可以不用对IoStatus的返回情况进行设置,否则要对其进行设置
    • 请求可以转发给下层IoCallDriver,也可以进行完成处理
    3 完整代码
      1 #include <wdm.h>
      2 
      3 typedef struct {
      4     UNICODE_STRING devName;
      5     UNICODE_STRING linkName;
      6     PDEVICE_OBJECT fdo;
      7     PDEVICE_OBJECT nextStackDevice;
      8 }DEVICE_EXTENSION, *PDEVICE_EXTENSION;
      9 
     10 #pragma PAGEDCODE
     11 void dump(PDEVICE_OBJECT pdo)
     12 {
     13     PAGED_CODE();
     14     //显示调试信息
     15     KdPrint(("-------------------------------------
    "));
     16     KdPrint(("Begin dump device stack
    "));
     17     for (int i = 0; NULL != pdo; pdo = pdo->AttachedDevice, i++)
     18     {
     19         KdPrint(("the %d device in device stack
    ", i));
     20         KdPrint(("device attcheddevice:%#010x", pdo->AttachedDevice));
     21         KdPrint(("device nextdevice:%#010x", pdo->NextDevice));
     22         KdPrint(("device stacksize:%d
    ", pdo->StackSize));
     23         KdPrint(("device's driverobject:%#010x", pdo->DriverObject));
     24     }
     25     KdPrint(("Dump over
    "));
     26     KdPrint(("-------------------------------------
    "));
     27 }
     28 
     29 #pragma PAGEDCODE
     30 NTSTATUS AddDevice(PDRIVER_OBJECT pDriverObject, PDEVICE_OBJECT PhysicalDeviceObject) //形参不知道
     31 {
     32     PAGED_CODE();
     33 
     34     KdPrint(("Enter AddDevice
    "));
     35 
     36     NTSTATUS status;
     37     PDEVICE_OBJECT pDeviceObject;
     38     UNICODE_STRING devName, linkName;
     39     PDEVICE_EXTENSION pDevExt;
     40 
     41     //创建设备对象
     42     RtlInitUnicodeString(&devName, L"\Device\WDM_ChenJiaqi");
     43     status = IoCreateDevice(pDriverObject, sizeof(DEVICE_EXTENSION), &devName, FILE_DEVICE_UNKNOWN, 0, TRUE, &pDeviceObject);
     44     if (!NT_SUCCESS(status))
     45     {
     46         return status;
     47     }
     48     //创建符号链接
     49     RtlInitUnicodeString(&linkName, L"\??\WDM_ChenJiaqi");
     50     status = IoCreateSymbolicLink(&linkName, &devName);
     51     if (!NT_SUCCESS(status))
     52     {
     53         IoDeleteDevice(pDeviceObject);
     54         return status;
     55     }
     56     //将FDO附加到PDO之上
     57     PDEVICE_OBJECT pNextStackDevice = IoAttachDeviceToDeviceStack(pDeviceObject, PhysicalDeviceObject);
     58     //设置设备扩展
     59     pDevExt = reinterpret_cast<PDEVICE_EXTENSION>(pDeviceObject->DeviceExtension);
     60     pDevExt->devName = devName;
     61     pDevExt->linkName = linkName;
     62     pDevExt->fdo = pDeviceObject;
     63     pDevExt->nextStackDevice = pNextStackDevice;
     64     //设备对象Flags
     65     pDeviceObject->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
     66     pDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
     67 
     68     dump(pNextStackDevice);
     69     KdPrint(("Leave AddDevice
    "));
     70     return STATUS_SUCCESS;
     71 }
     72 
     73 #pragma PAGEDCODE
     74 VOID DriverUnLoad(PDRIVER_OBJECT pDriverObject)
     75 {
     76     PAGED_CODE();
     77     //释放内存等相关操作
     78     pDriverObject;
     79     KdPrint(("Enter DriverUnLoad
    "));
     80     KdPrint(("Leave DriverUnLoad
    "));
     81 }
     82 
     83 #pragma PAGEDCODE
     84 NTSTATUS DefaultPnpHandler(PDEVICE_EXTENSION pdx, PIRP pIrp)
     85 {
     86     PAGED_CODE();
     87     KdPrint(("Enter DefaultPnpHandler
    "));
     88     //
     89     IoSkipCurrentIrpStackLocation(pIrp);
     90     KdPrint(("Leave DefaultPnpHandler
    "));
     91     //
     92     return IoCallDriver(pdx->nextStackDevice, pIrp);
     93 }
     94 
     95 //对IRP_MN_REMOVE_DEVICE的处理,从DriverUnLoad的功能分离出来
     96 #pragma PAGEDCODE
     97 NTSTATUS HandleRemoveDevice(PDEVICE_EXTENSION pDeviceExtension, PIRP pIrp)
     98 {
     99     PAGED_CODE();
    100 
    101     KdPrint(("Enter HandleRemoveDevice
    "));
    102     //设置IRP的完成状态
    103     pIrp->IoStatus.Status = STATUS_SUCCESS;
    104     pIrp->IoStatus.Information = 0; //读写字节数
    105     //将IRP请求向底层驱动转发
    106     NTSTATUS status = DefaultPnpHandler(pDeviceExtension, pIrp); //这个函数由我们自己编写
    107     //删除符号链接
    108     IoDeleteSymbolicLink(&pDeviceExtension->linkName);
    109     //调用IoDetechDevice()把FDO从设备栈脱离开
    110     IoDetachDevice(pDeviceExtension->nextStackDevice);
    111     //删除FDO
    112     IoDeleteDevice(pDeviceExtension->fdo);
    113     KdPrint(("Leave HandleRemoveDevice
    "));
    114     return status;
    115 }
    116 
    117 #pragma PAGEDCODE
    118 NTSTATUS DefaultDispatchRoutinue(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
    119 {
    120     //对IRP的处理
    121     PAGED_CODE();
    122     KdPrint(("Enter DefaultDispatchRoutinue
    "));
    123     pDeviceObject;
    124     //设置IRP返回情况
    125     pIrp->IoStatus.Status = STATUS_SUCCESS;
    126     pIrp->IoStatus.Information = 0;    // no bytes xfered
    127     //完成对IRP的处理
    128     IoCompleteRequest(pIrp, IO_NO_INCREMENT);
    129     KdPrint(("Leave DefaultDispatchRoutinue
    "));
    130     return STATUS_SUCCESS;
    131 }
    132 
    133 #pragma PAGEDCODE
    134 NTSTATUS WDMPnp(IN PDEVICE_OBJECT fdo,IN PIRP Irp)
    135 {
    136     PAGED_CODE();
    137 
    138     KdPrint(("Enter HelloWDMPnp
    "));
    139     NTSTATUS status = STATUS_SUCCESS;
    140     //得到设备拓展
    141     PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
    142     //得到当前IRP堆栈
    143     PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
    144     //定义函数指针列表
    145     static NTSTATUS(*fcntab[])(PDEVICE_EXTENSION pdx, PIRP Irp) =
    146     {
    147         DefaultPnpHandler,        // IRP_MN_START_DEVICE
    148         DefaultPnpHandler,        // IRP_MN_QUERY_REMOVE_DEVICE
    149         HandleRemoveDevice,        // IRP_MN_REMOVE_DEVICE
    150         DefaultPnpHandler,        // IRP_MN_CANCEL_REMOVE_DEVICE
    151         DefaultPnpHandler,        // IRP_MN_STOP_DEVICE
    152         DefaultPnpHandler,        // IRP_MN_QUERY_STOP_DEVICE
    153         DefaultPnpHandler,        // IRP_MN_CANCEL_STOP_DEVICE
    154         DefaultPnpHandler,        // IRP_MN_QUERY_DEVICE_RELATIONS
    155         DefaultPnpHandler,        // IRP_MN_QUERY_INTERFACE
    156         DefaultPnpHandler,        // IRP_MN_QUERY_CAPABILITIES
    157         DefaultPnpHandler,        // IRP_MN_QUERY_RESOURCES
    158         DefaultPnpHandler,        // IRP_MN_QUERY_RESOURCE_REQUIREMENTS
    159         DefaultPnpHandler,        // IRP_MN_QUERY_DEVICE_TEXT
    160         DefaultPnpHandler,        // IRP_MN_FILTER_RESOURCE_REQUIREMENTS
    161         DefaultPnpHandler,        // 
    162         DefaultPnpHandler,        // IRP_MN_READ_CONFIG
    163         DefaultPnpHandler,        // IRP_MN_WRITE_CONFIG
    164         DefaultPnpHandler,        // IRP_MN_EJECT
    165         DefaultPnpHandler,        // IRP_MN_SET_LOCK
    166         DefaultPnpHandler,        // IRP_MN_QUERY_ID
    167         DefaultPnpHandler,        // IRP_MN_QUERY_PNP_DEVICE_STATE
    168         DefaultPnpHandler,        // IRP_MN_QUERY_BUS_INFORMATION
    169         DefaultPnpHandler,        // IRP_MN_DEVICE_USAGE_NOTIFICATION
    170         DefaultPnpHandler,        // IRP_MN_SURPRISE_REMOVAL
    171     };
    172     //得到IRP的Minor编号,了解它是哪种类型的PNP请求
    173     ULONG fcn = stack->MinorFunction;
    174     if (fcn >= sizeof(fcntab) / sizeof(fcntab[0]))
    175     {                        // 未知的子功能代码
    176         status = DefaultPnpHandler(pdx, Irp); // some function we don't know about
    177         return status;
    178     }
    179     //PNP请求名列表
    180     static char* fcnname[] =
    181     {
    182         "IRP_MN_START_DEVICE",
    183         "IRP_MN_QUERY_REMOVE_DEVICE",
    184         "IRP_MN_REMOVE_DEVICE",
    185         "IRP_MN_CANCEL_REMOVE_DEVICE",
    186         "IRP_MN_STOP_DEVICE",
    187         "IRP_MN_QUERY_STOP_DEVICE",
    188         "IRP_MN_CANCEL_STOP_DEVICE",
    189         "IRP_MN_QUERY_DEVICE_RELATIONS",
    190         "IRP_MN_QUERY_INTERFACE",
    191         "IRP_MN_QUERY_CAPABILITIES",
    192         "IRP_MN_QUERY_RESOURCES",
    193         "IRP_MN_QUERY_RESOURCE_REQUIREMENTS",
    194         "IRP_MN_QUERY_DEVICE_TEXT",
    195         "IRP_MN_FILTER_RESOURCE_REQUIREMENTS",
    196         "",
    197         "IRP_MN_READ_CONFIG",
    198         "IRP_MN_WRITE_CONFIG",
    199         "IRP_MN_EJECT",
    200         "IRP_MN_SET_LOCK",
    201         "IRP_MN_QUERY_ID",
    202         "IRP_MN_QUERY_PNP_DEVICE_STATE",
    203         "IRP_MN_QUERY_BUS_INFORMATION",
    204         "IRP_MN_DEVICE_USAGE_NOTIFICATION",
    205         "IRP_MN_SURPRISE_REMOVAL",
    206     };
    207 
    208     KdPrint(("PNP Request (%s)
    ", fcnname[fcn]));
    209     //!!!根据IRP的MINOR编号,调用相应的请求处理函数
    210     status = (*fcntab[fcn])(pdx, Irp);
    211     KdPrint(("Leave HelloWDMPnp
    "));
    212     return status;
    213 }
    214 
    215 #pragma INITCODE 
    216 extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegisterPath)
    217 {
    218     //设置pDriverObject结构体,注册AddDevice和相关PNP函数,包括IRP_MJ_PNP,IRP_MJ_CREATE等
    219     KdPrint(("Enter DriverEntry
    "));
    220     pRegisterPath;
    221     //设置AddDevice函数
    222     pDriverObject->DriverExtension->AddDevice = AddDevice;
    223     //注册PNP
    224     pDriverObject->MajorFunction[IRP_MJ_PNP] = WDMPnp;
    225     pDriverObject->MajorFunction[IRP_MJ_CREATE] =
    226         pDriverObject->MajorFunction[IRP_MJ_WRITE] =
    227         pDriverObject->MajorFunction[IRP_MJ_READ] =
    228         pDriverObject->MajorFunction[IRP_MJ_CLOSE] = DefaultDispatchRoutinue;
    229     KdPrint(("Leave DriverEntry
    "));
    230     return STATUS_SUCCESS;
    231 }
    4 inf文件
    ;;WDM_Driver inf文件--2015年8月14日
    [Version]
    Signature = "$Windows NT$"
    Class = WDM_Driver
    ClassGUID = {EF2962F0-0D55-4bff-B8AA-2221EE8A79B0}
    Provider = cposture
    DriverVer = 
    CatalogFile=WDM_Driver.cat
    CatalogFile.ntamd64=WDM_Driver.cat
    CatalogFile.nt=WDM_Driver.cat
    [ClassInstall32.NTamd64]
    AddReg=Class_AddReg
    [Class_AddReg]  
    HKR,,,,%DeviceClassName%            
    HKR,,Icon,,"-5" 
    [SourceDisksNames]
    1 = %DiskName%,,
    [SourceDisksFiles]
    WDM_Driver层次结构.sys = 1
    WDM_Driver层次结构.sys = 1
    [DestinationDirs]
    DefaultDestDir = 12  
    my_files_driver = 12
    [my_files_driver]
    WDM_Driver层次结构.sys
    [my_files_driver64]
    WDM_Driver层次结构.sys
    [Manufacturer]
    %MfgName%=Mfg0,NT,NTamd64
    [Mfg0.NT]
    %DeviceDesc%=InstallLauncher, PCIVEN_9999&DEV_9999
    [Mfg0.NTamd64]
    %DeviceDesc%=InstallLauncher, PCIVEN_9999&DEV_9999
    ;---------- DDInstall Sections -----------------------------------------------
    [InstallLauncher.NT]                        
    CopyFiles=my_files_driver
    AddReg=Install_NT_AddReg
    [InstallLauncher.NT.Services]
    Addservice = WDM_Driver, 0x00000002, Sys_AddService    
    [Sys_AddService]  
    DisplayName = %DeviceDesc%                                
    ServiceType = 1
    StartType = 3
    ErrorControl = 1
    ServiceBinary = %12%WDM_Driver层次结构.sys
    [Install_NT_AddReg]
    HKLM, "SystemCurrentControlSetServicesWDM_DriverParameters","BreakOnEntry", 0x00010001, 0 
    ;---------------------64位支持---------------
    [InstallLauncher.NTamd64]                        
    CopyFiles=my_files_driver64
    AddReg=Install_NT_AddReg64
    [InstallLauncher.NTamd64.Services]
    Addservice = WDM_Driver, 0x00000002, Sys_AddService64
    [Sys_AddService64]
    DisplayName = %DeviceDesc%
    ServiceType = 1
    StartType = 3
    ErrorControl = 1
    ServiceBinary = %12%WDM_Driver层次结构.sys
    [Install_NT_AddReg64]
    HKLM, "SystemCurrentControlSetServicesWDM_DriverParameters","BreakOnEntry", 0x00010001, 0
     
    [Strings]
    MfgName="cpostute"
    DeviceDesc="WDM_Driver"
    DiskName="WDM_Driver Source Disk"
    DeviceClassName = WDM_Driver
    本文链接:http://www.cnblogs.com/cposture/p/4734288.html
  • 相关阅读:
    Spring的IOC容器学习笔记
    全球疫情可视化展示
    GitHub-暂存区与版本回退
    GitHub-创建仓库与本地同步
    Shell脚本常用模板
    Shell按行读取文件的3种方法
    shell脚本:通过域名获取证书的过期时间
    如何禁止chrome浏览器http自动转成https 【转】
    kafka_2.11-2.0.0_常用操作
    kafka_2.11-2.0.0_安装部署
  • 原文地址:https://www.cnblogs.com/cposture/p/4734288.html
Copyright © 2020-2023  润新知