zoukankan      html  css  js  c++  java
  • 【原创】《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
  • 相关阅读:
    JavaScript Patterns 5.7 Object Constants
    JavaScript Patterns 5.6 Static Members
    JavaScript Patterns 5.5 Sandbox Pattern
    JavaScript Patterns 5.4 Module Pattern
    JavaScript Patterns 5.3 Private Properties and Methods
    JavaScript Patterns 5.2 Declaring Dependencies
    JavaScript Patterns 5.1 Namespace Pattern
    JavaScript Patterns 4.10 Curry
    【Android】如何快速构建Android Demo
    【Android】如何实现ButterKnife
  • 原文地址:https://www.cnblogs.com/cposture/p/4734288.html
Copyright © 2011-2022 走看看