你的位置:首页 > 操作系统

[操作系统]梦织未来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::OnBnClickedButton4() 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