梦织未来Windows驱动编程 第03课 驱动的编程规范
最近根据梦织未来论坛的驱动教程学习了一下Windows下的驱动编程,做个笔记备忘。这是第03课《驱动的编程规范》。 驱动部分包括基本的驱动卸载函数、驱动打开关闭读取写入操作最简单的分发例程。代码如下:
//CreateDevice.c
//2016.07.14 #include "ntddk.h" //驱动卸载函数Self
VOID MyDriverUnload(PDRIVER_OBJECT pDriverObject)
{
UNICODE_STRING usSymName;
RtlInitUnicodeString(&usSymName, L"\\??\\FirstDevice"); //先删除符号链接,后删除设备对象
if (pDriverObject->DeviceObject != NULL)
{
IoDeleteSymbolicLink(&usSymName); //删除符号链接
IoDeleteDevice(pDriverObject->DeviceObject); //删除设备对象
KdPrint(("Delete Device Sucess."));
}
} //创建设备函数Self
NTSTATUS CreateDevice(PDRIVER_OBJECT pDriverObject)
{
NTSTATUS Status;
UNICODE_STRING usDevName;
UNICODE_STRING usSymName;
PDEVICE_OBJECT pDevObj; //设备对象,用于指向创建的设备 //DDK API 为UNICODE_STRING赋值的函数
RtlInitUnicodeString(&usDevName, L"\\Device\\FirstDevice"); //创建设备函数API 创建设备"\\Device\\FirstDevice"
//设备创建后,会返回给pDevObj,同时给pDriverObject->DeviceObject赋值
//The IoCreateDevice routine creates a device object for use by a driver.
/*
NTSTATUS IoCreateDevice(
_In_ PDRIVER_OBJECT DriverObject,
_In_ ULONG DeviceExtensionSize,
_In_opt_ PUNICODE_STRING DeviceName,
_In_ DEVICE_TYPE DeviceType,
_In_ ULONG DeviceCharacteristics,
_In_ BOOLEAN Exclusive,
_Out_ PDEVICE_OBJECT *DeviceObject
);
*/
Status = IoCreateDevice(pDriverObject,
,
&usDevName,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
TRUE,
&pDevObj);
if (!NT_SUCCESS(Status)) //检查返回值
{
return Status;
} //DO_BUFFERED_IO or DO_DIRECT_IO
//Specifies the type of buffering that is used by the I/O manager for I/O requests that are sent to the device stack.
//Higher-level drivers OR this member with the same value as the next-lower driver in the stack, except possibly for highest-level drivers.
pDevObj->Flags |= DO_BUFFERED_IO; RtlInitUnicodeString(&usSymName, L"\\??\\FirstDevice"); //The IoCreateSymbolicLink routine sets up a symbolic link between a device object name and a user-visible name for the device.
/*
NTSTATUS IoCreateSymbolicLink(
_In_ PUNICODE_STRING SymbolicLinkName,
_In_ PUNICODE_STRING DeviceName
);
*/
Status = IoCreateSymbolicLink(&usSymName, &usDevName); //DDK API 创建符号链接
if (!NT_SUCCESS(Status))
{
IoDeleteDevice(pDevObj); //删除设备对象
return Status;
} return STATUS_SUCCESS;
} //打开设备的函数
NTSTATUS CreateCompleteRoutine(PDRIVER_OBJECT pDriverObject, PIRP pIrp)
{
NTSTATUS Status; Status = STATUS_SUCCESS; KdPrint(("Create")); //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. //This is the completion status, either STATUS_SUCCESS if the requested operation was completed successfully or an informational, warning, or error STATUS_ XXX value.
//For more information, see Using NTSTATUS values.
pIrp->IoStatus.Status = Status;
//This is the completion status, either STATUS_SUCCESS if the requested operation was completed successfully or an informational, warning, or error STATUS_ XXX value.
//For more information, see Using NTSTATUS values.
pIrp->IoStatus.Information = ; //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.
//IO_NO_INCREMENT 不再往下层传递
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return Status;
} //关闭设备的函数
NTSTATUS CloseCompleteRoutine(PDRIVER_OBJECT pDriverObject, PIRP pIrp)
{
NTSTATUS Status; Status = STATUS_SUCCESS; KdPrint(("Close")); pIrp->IoStatus.Status = Status;
pIrp->IoStatus.Information = ; IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return Status;
} //读取设备的函数
NTSTATUS ReadCompleteRoutine(PDRIVER_OBJECT pDriverObject, PIRP pIrp)
{
NTSTATUS Status; Status = STATUS_SUCCESS; KdPrint(("Read")); pIrp->IoStatus.Status = Status;
pIrp->IoStatus.Information = ; IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return Status;
} //写入设备的函数
NTSTATUS WriteCompleteRoutine(PDRIVER_OBJECT pDriverObject, PIRP pIrp)
{
NTSTATUS Status; Status = STATUS_SUCCESS; KdPrint(("Write")); pIrp->IoStatus.Status = Status;
pIrp->IoStatus.Information = ; IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return Status;
} //驱动程序入口函数
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath)
{
//输出信息
//DbgPrint("1111"); NTSTATUS Status;
Status = CreateDevice(pDriverObject); //创建设备对象和符号链接
if (!NT_SUCCESS(Status))
{
KdPrint(("Create Device Failed."));
} else {
KdPrint(("Create Device Sucess."));
KdPrint(("%wZ", pRegistryPath));
} //打开关闭读取写入的分发例程赋值
pDriverObject->MajorFunction[IRP_MJ_CREATE] = (PDRIVER_DISPATCH)CreateCompleteRoutine; //打开设备
pDriverObject->MajorFunction[IRP_MJ_CLOSE] = (PDRIVER_DISPATCH)CloseCompleteRoutine; //关闭设备
pDriverObject->MajorFunction[IRP_MJ_READ] = (PDRIVER_DISPATCH)ReadCompleteRoutine; //读取设备
pDriverObject->MajorFunction[IRP_MJ_WRITE] = (PDRIVER_DISPATCH)WriteCompleteRoutine; //写入设备 //驱动卸载函数赋值
pDriverObject->DriverUnload = MyDriverUnload; return STATUS_SUCCESS;
}
CreateDevice.c
应用层采用了MFC创建了一个窗口,窗口有三个按钮:Create、Read、Write。界面如下:
其中Create按钮的处理函数如下:
void CCheckMyDriverDlg::OnCreateButton()
{
// TODO: 在此添加控件通知处理程序代码
HANDLE hFile = CreateFileW(L"\\\\.\\FirstDevice",
FILE_ALL_ACCESS,
,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
AfxMessageBox (L"Open Device Failed.");
return;
} CloseHandle (hFile);
}
Read按钮的处理函数如下:
void CCheckMyDriverDlg::OnReadButton()
{
// TODO: 在此添加控件通知处理程序代码
HANDLE hFile = CreateFileW(L"\\\\.\\FirstDevice",
FILE_ALL_ACCESS,
,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
AfxMessageBox (L"Open Device Failed.");
return;
} wchar_t Buffer[MAX_PATH] = {};
DWORD len = ;
if (!ReadFile (hFile, Buffer, MAX_PATH-, &len, NULL))
{
AfxMessageBox (L"Read Device Failed.");
return;
} CloseHandle (hFile); }
Write按钮的处理函数如下:
void CCheckMyDriverDlg::OnWriteButton()
{
// TODO: 在此添加控件通知处理程序代码
HANDLE hFile = CreateFileW(L"\\\\.\\FirstDevice",
FILE_ALL_ACCESS,
,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
AfxMessageBox (L"Open Device Failed.");
return;
} wchar_t Buffer[MAX_PATH] = L"What The Fuck, Man ?";
DWORD len;
if (!WriteFile (hFile, Buffer, MAX_PATH, &len, NULL))
{
AfxMessageBox (L"Write Device Failed.");
return;
} CloseHandle (hFile); }
以下为操作部分:
将生成的FirstDevice.sys文件复制到XP虚拟机下,使用驱动加载工具InstDrv安装并启动驱动后,在Dbgview工具内有如下输出信息:
并能够找到相应注册表,使用WinObj工具查看设备对象\\Device\\FirstDevice:
然后查看符号链接\\??\\FirstDevice:
使用InstDrv停止此驱动时输出:
期间并未出现蓝屏问题
安装驱动程序后,使用上面写的MFC程序CheckMyDriver.exe,点击Create按钮后,输出
点击Read按钮后,输出:
点击Write按钮后,输出:
以上操作均为出现蓝屏。本课结束。
由于本人刚开始学习驱动程序,实力有限,可能对于某些地方的理解并不正确,希望大家能提出意见建议,共同学习,共同进步。
最后谢谢大家的支持。
2016-07-14 14:58:13
梦织未来Windows驱动编程 第03课 驱动的编程规范的更多相关文章
- 梦织未来Windows驱动编程 第05课 小结(读取另一驱动,遍历所有驱动)
读取另一驱动 驱动通过"\\Driver\\XueTr"获取到了XueTr工具的驱动,并Hook了XueTr驱动的分发函数. 具体的驱动代码如下: //FilterDriver.c ...
- 梦织未来Windows驱动编程 第06课 驱动对磁盘文件的操作
代码部分: 实现一个文件C:\\text.txt,并读取写入内容到文件,然后将文件设置为只读,并隐藏文件.代码如下: //MyCreateFile.c //2016.07.22 #include &l ...
- 梦织未来Windows驱动编程 第04课 驱动相关的数据结构
- 《天书夜读:从汇编语言到windows内核编程》五 WDM驱动开发环境搭建
(原书)所有内核空间共享,DriverEntery是内核程序入口,在内核程序被加载时,这个函数被调用,加载入的进程为system进程,xp下它的pid是4.内核程序的编写有一定的规则: 不能调用win ...
- PL2303HX在Windows 10下面不装安装驱动的解决办法(Code:10)
Prolific在很早之前推出了一款名为PL2303HX的芯片, 用于USB转RS232, 这款芯片使用的范围非常广, 并且年代久远. 但是这款芯片因为用的特别多, 所以中国就有很多厂家生产了仿造的P ...
- 重新想象 Windows 8 Store Apps (44) - 多线程之异步编程: 经典和最新的异步编程模型, IAsyncInfo 与 Task 相互转换
[源码下载] 重新想象 Windows 8 Store Apps (44) - 多线程之异步编程: 经典和最新的异步编程模型, IAsyncInfo 与 Task 相互转换 作者:webabcd 介绍 ...
- 重新想象 Windows 8 Store Apps (45) - 多线程之异步编程: IAsyncAction, IAsyncOperation, IAsyncActionWithProgress, IAsyncOperationWithProgress
[源码下载] 重新想象 Windows 8 Store Apps (45) - 多线程之异步编程: IAsyncAction, IAsyncOperation, IAsyncActionWithPro ...
- windows下编译qt的mysql驱动
windows下编译qt的mysql驱动cd %QTDIR%\src\plugins\sqldrivers\mysqlqmake –o Makefile INCLUDEPATH+="C:\M ...
- Java并发编程实战 03互斥锁 解决原子性问题
文章系列 Java并发编程实战 01并发编程的Bug源头 Java并发编程实战 02Java如何解决可见性和有序性问题 摘要 在上一篇文章02Java如何解决可见性和有序性问题当中,我们解决了可见性和 ...
随机推荐
- PAT - 1067 试密码 (20 分)
当你试图登录某个系统却忘了密码时,系统一般只会允许你尝试有限多次,当超出允许次数时,账号就会被锁死.本题就请你实现这个小功能. 输入格式: 输入在第一行给出一个密码(长度不超过 20 的.不包含空格. ...
- 关于pycharm使用sqlite数据可视化的使用
如图
- 阿里云服务器mail 命令发邮件
一.申请开通25端口 https://yundun.console.aliyun.com/?spm=5176.2020520001.aliyun_topbar.188.KbmgKc&p=sc# ...
- ajax动态给select赋值
<select name="elements" id="ele" style="width: 145px;"> ...
- F. Cooking Time 贪心
http://codeforces.com/gym/101498/problem/F 对于知道使用情况的置换算法,最优解是找一个最后需要使用的物品替换掉 也就是,如果一个物品后面已经不需要用到,就要拿 ...
- Docker Ubuntu/CentOS 下运行 java jar
官方安装方法 https://docs.docker.com/engine/installation/linux/ubuntu/ Ubuntu安装包 https://download.docker.c ...
- Ant,Maven与Gradle的概念的理解
转载地址:http://www.jianshu.com/p/cd8fe9b16369# 我们还是以AndroidStudio 2.1.1为例来讲. 用AndroidStudio就逃不开跟Gradle打 ...
- 使用vue Devtools
第一步: 在谷歌应用商店中查找 vue Devtools 并安装.安装之后,即使我们打开了vue项目发现vue标识是灰色的,说明并没有成功启动vue. 第二步: 默认安装的情况下,找到C:\Users ...
- HDU 5379——Mahjong tree——————【搜索】
Mahjong tree Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Tota ...
- 移动Web开发与适配笔记
项目要是适配手机端,想透彻的把相关内容弄清楚,现在总结一下. 一.移动端开发有如下特点: 1.跑在手机端的web 页面就是h5页面 2.具有跨平台性(web 安卓 iOS都适应) 3.基于webvie ...