zoukankan      html  css  js  c++  java
  • 梦织未来Windows驱动编程 第03课 驱动的编程规范

    最近根据梦织未来论坛的驱动教程学习了一下Windows下的驱动编程,做个笔记备忘。这是第03课《驱动的编程规范》。

    驱动部分包括基本的驱动卸载函数、驱动打开关闭读取写入操作最简单的分发例程。代码如下:

      1 //CreateDevice.c
      2 //2016.07.14
      3 
      4 #include "ntddk.h"
      5 
      6 //驱动卸载函数Self
      7 VOID MyDriverUnload(PDRIVER_OBJECT pDriverObject)
      8 { 
      9     UNICODE_STRING usSymName;
     10     RtlInitUnicodeString(&usSymName, L"\??\FirstDevice");
     11     
     12     //先删除符号链接,后删除设备对象
     13     if (pDriverObject->DeviceObject != NULL)
     14     {
     15         IoDeleteSymbolicLink(&usSymName);                //删除符号链接
     16         IoDeleteDevice(pDriverObject->DeviceObject);    //删除设备对象
     17         KdPrint(("Delete Device Sucess."));
     18     }
     19 }
     20 
     21 //创建设备函数Self
     22 NTSTATUS CreateDevice(PDRIVER_OBJECT pDriverObject)
     23 {
     24     NTSTATUS Status;
     25     UNICODE_STRING usDevName;
     26     UNICODE_STRING usSymName;
     27     PDEVICE_OBJECT pDevObj;        //设备对象,用于指向创建的设备
     28     
     29     //DDK API    为UNICODE_STRING赋值的函数
     30     RtlInitUnicodeString(&usDevName, L"\Device\FirstDevice");
     31     
     32     //创建设备函数API    创建设备"\Device\FirstDevice"
     33     //设备创建后,会返回给pDevObj,同时给pDriverObject->DeviceObject赋值
     34     //The IoCreateDevice routine creates a device object for use by a driver.
     35     /*
     36         NTSTATUS IoCreateDevice(
     37         _In_     PDRIVER_OBJECT  DriverObject,
     38         _In_     ULONG           DeviceExtensionSize,
     39         _In_opt_ PUNICODE_STRING DeviceName,
     40         _In_     DEVICE_TYPE     DeviceType,
     41         _In_     ULONG           DeviceCharacteristics,
     42         _In_     BOOLEAN         Exclusive,
     43         _Out_    PDEVICE_OBJECT  *DeviceObject
     44         );
     45     */
     46     Status = IoCreateDevice(pDriverObject,         
     47                             0, 
     48                             &usDevName, 
     49                             FILE_DEVICE_UNKNOWN, 
     50                             FILE_DEVICE_SECURE_OPEN, 
     51                             TRUE, 
     52                             &pDevObj);
     53     if (!NT_SUCCESS(Status))    //检查返回值
     54     {
     55         return Status;
     56     }
     57     
     58     //DO_BUFFERED_IO or DO_DIRECT_IO 
     59     //Specifies the type of buffering that is used by the I/O manager for I/O requests that are sent to the device stack. 
     60     //Higher-level drivers OR this member with the same value as the next-lower driver in the stack, except possibly for highest-level drivers.
     61     pDevObj->Flags |= DO_BUFFERED_IO;
     62     
     63     RtlInitUnicodeString(&usSymName, L"\??\FirstDevice");
     64     
     65     //The IoCreateSymbolicLink routine sets up a symbolic link between a device object name and a user-visible name for the device.
     66     /*
     67         NTSTATUS IoCreateSymbolicLink(
     68         _In_ PUNICODE_STRING SymbolicLinkName,
     69         _In_ PUNICODE_STRING DeviceName
     70         );
     71     */
     72     Status = IoCreateSymbolicLink(&usSymName, &usDevName);    //DDK API    创建符号链接
     73     if (!NT_SUCCESS(Status))
     74     {
     75         IoDeleteDevice(pDevObj);    //删除设备对象
     76         return Status;
     77     }
     78     
     79     return STATUS_SUCCESS; 
     80 }
     81 
     82 //打开设备的函数
     83 NTSTATUS CreateCompleteRoutine(PDRIVER_OBJECT pDriverObject, PIRP pIrp)
     84 {
     85     NTSTATUS Status;
     86     
     87     Status = STATUS_SUCCESS;
     88     
     89     KdPrint(("Create"));
     90     
     91     //A driver sets an IRP's I/O status block to indicate the final status of an I/O request, before calling IoCompleteRequest for the IRP.
     92     
     93     //This is the completion status, either STATUS_SUCCESS if the requested operation was completed successfully or an informational, warning, or error STATUS_ XXX value.
     94     //For more information, see Using NTSTATUS values.
     95     pIrp->IoStatus.Status = Status;
     96     //This is the completion status, either STATUS_SUCCESS if the requested operation was completed successfully or an informational, warning, or error STATUS_ XXX value. 
     97     //For more information, see Using NTSTATUS values.
     98     pIrp->IoStatus.Information = 0;
     99     
    100     //The IoCompleteRequest routine indicates that the caller has completed all processing for a given I/O request and is returning the given IRP to the I/O manager.
    101     //IO_NO_INCREMENT 不再往下层传递
    102     IoCompleteRequest(pIrp, IO_NO_INCREMENT);
    103     return Status;
    104 }
    105 
    106 //关闭设备的函数
    107 NTSTATUS CloseCompleteRoutine(PDRIVER_OBJECT pDriverObject, PIRP pIrp)
    108 {
    109     NTSTATUS Status;
    110 
    111     Status = STATUS_SUCCESS;
    112 
    113     KdPrint(("Close"));
    114 
    115     pIrp->IoStatus.Status = Status;
    116     pIrp->IoStatus.Information = 0;
    117 
    118     IoCompleteRequest(pIrp, IO_NO_INCREMENT);
    119     return Status;
    120 }
    121 
    122 //读取设备的函数
    123 NTSTATUS ReadCompleteRoutine(PDRIVER_OBJECT pDriverObject, PIRP pIrp)
    124 {
    125     NTSTATUS Status;
    126 
    127     Status = STATUS_SUCCESS;
    128 
    129     KdPrint(("Read"));
    130 
    131     pIrp->IoStatus.Status = Status;
    132     pIrp->IoStatus.Information = 0;
    133 
    134     IoCompleteRequest(pIrp, IO_NO_INCREMENT);
    135     return Status;
    136 }
    137 
    138 //写入设备的函数
    139 NTSTATUS WriteCompleteRoutine(PDRIVER_OBJECT pDriverObject, PIRP pIrp)
    140 {
    141     NTSTATUS Status;
    142 
    143     Status = STATUS_SUCCESS;
    144 
    145     KdPrint(("Write"));
    146 
    147     pIrp->IoStatus.Status = Status;
    148     pIrp->IoStatus.Information = 0;
    149 
    150     IoCompleteRequest(pIrp, IO_NO_INCREMENT);
    151     return Status;
    152 }
    153 
    154 //驱动程序入口函数
    155 NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath)
    156 {
    157     //输出信息
    158     //DbgPrint("1111");
    159 
    160     
    161     NTSTATUS Status;
    162     Status = CreateDevice(pDriverObject);    //创建设备对象和符号链接
    163     if (!NT_SUCCESS(Status))
    164     {
    165         KdPrint(("Create Device Failed."));
    166     } else {
    167         KdPrint(("Create Device Sucess."));
    168         KdPrint(("%wZ", pRegistryPath));
    169     }
    170         
    171     //打开关闭读取写入的分发例程赋值
    172     pDriverObject->MajorFunction[IRP_MJ_CREATE] = (PDRIVER_DISPATCH)CreateCompleteRoutine;    //打开设备
    173     pDriverObject->MajorFunction[IRP_MJ_CLOSE]    = (PDRIVER_DISPATCH)CloseCompleteRoutine;    //关闭设备
    174     pDriverObject->MajorFunction[IRP_MJ_READ]    = (PDRIVER_DISPATCH)ReadCompleteRoutine;    //读取设备
    175     pDriverObject->MajorFunction[IRP_MJ_WRITE]    = (PDRIVER_DISPATCH)WriteCompleteRoutine;    //写入设备
    176     
    177     //驱动卸载函数赋值
    178     pDriverObject->DriverUnload = MyDriverUnload;
    179 
    180     return STATUS_SUCCESS;
    181 }
    CreateDevice.c

    应用层采用了MFC创建了一个窗口,窗口有三个按钮:Create、Read、Write。界面如下:

    其中Create按钮的处理函数如下:

     1 void CCheckMyDriverDlg::OnCreateButton()
     2 {
     3     // TODO: 在此添加控件通知处理程序代码
     4     HANDLE hFile = CreateFileW(L"\\.\FirstDevice", 
     5                 FILE_ALL_ACCESS, 
     6                 0, 
     7                 NULL,
     8                 OPEN_EXISTING,
     9                 FILE_ATTRIBUTE_NORMAL,
    10                 NULL);
    11     if (hFile == INVALID_HANDLE_VALUE)
    12     {
    13         AfxMessageBox (L"Open Device Failed.");
    14         return;
    15     }
    16 
    17     CloseHandle (hFile);
    18 }

    Read按钮的处理函数如下:

     1 void CCheckMyDriverDlg::OnReadButton()
     2 {
     3     // TODO: 在此添加控件通知处理程序代码
     4     HANDLE hFile = CreateFileW(L"\\.\FirstDevice", 
     5         FILE_ALL_ACCESS, 
     6         0, 
     7         NULL,
     8         OPEN_EXISTING,
     9         FILE_ATTRIBUTE_NORMAL,
    10         NULL);
    11     if (hFile == INVALID_HANDLE_VALUE)
    12     {
    13         AfxMessageBox (L"Open Device Failed.");
    14         return;
    15     }
    16 
    17     wchar_t Buffer[MAX_PATH] = {0};
    18     DWORD len = 0;
    19     if (!ReadFile (hFile, Buffer, MAX_PATH-1, &len, NULL))
    20     {
    21         AfxMessageBox (L"Read Device Failed.");
    22         return;
    23     }
    24 
    25     CloseHandle (hFile);
    26 
    27 }

    Write按钮的处理函数如下:

     1 void CCheckMyDriverDlg::OnWriteButton()
     2 {
     3     // TODO: 在此添加控件通知处理程序代码
     4     HANDLE hFile = CreateFileW(L"\\.\FirstDevice", 
     5         FILE_ALL_ACCESS, 
     6         0, 
     7         NULL,
     8         OPEN_EXISTING,
     9         FILE_ATTRIBUTE_NORMAL,
    10         NULL);
    11     if (hFile == INVALID_HANDLE_VALUE)
    12     {
    13         AfxMessageBox (L"Open Device Failed.");
    14         return;
    15     }
    16 
    17     wchar_t Buffer[MAX_PATH] = L"What The Fuck, Man ?";
    18     DWORD len;
    19     if (!WriteFile (hFile, Buffer, MAX_PATH, &len, NULL))
    20     {
    21         AfxMessageBox (L"Write Device Failed.");
    22         return;
    23     }
    24 
    25     CloseHandle (hFile);
    26 
    27 }

     以下为操作部分:

    将生成的FirstDevice.sys文件复制到XP虚拟机下,使用驱动加载工具InstDrv安装并启动驱动后,在Dbgview工具内有如下输出信息:

    并能够找到相应注册表,使用WinObj工具查看设备对象\Device\FirstDevice:

    然后查看符号链接\??\FirstDevice:

    使用InstDrv停止此驱动时输出:

     

     期间并未出现蓝屏问题

    安装驱动程序后,使用上面写的MFC程序CheckMyDriver.exe,点击Create按钮后,输出

    点击Read按钮后,输出:

    点击Write按钮后,输出:

     

     以上操作均为出现蓝屏。本课结束。

    由于本人刚开始学习驱动程序,实力有限,可能对于某些地方的理解并不正确,希望大家能提出意见建议,共同学习,共同进步。

    最后谢谢大家的支持。

    2016-07-14 14:58:13

  • 相关阅读:
    第一节:RestfulCRUD案例
    第三节:<mvc:annotationdriven />标签解析
    第二节:SpringMVC 的表单标签
    第一节:SpringMVC—数据绑定流程分析
    第四章:(2)Web开发 之 webjars&静态资源映射规则
    第三节:处理静态资源
    10.05
    四则运算二柱子1
    10.08
    10.02
  • 原文地址:https://www.cnblogs.com/linuxxiaoyu/p/5668153.html
Copyright © 2011-2022 走看看