梦织未来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如何解决可见性和有序性问题当中,我们解决了可见性和 ...
随机推荐
- Nginx 基本 安装..
ubuntu 下 Nginx是高度自由化的Web服务器,它的功能是由许多模块来支持.如果使用了某个模块,这个模块使用了一些类似zlib或OpenSSL等的第三方库,那么就必须先安装这些软件.Ubunt ...
- 找到一篇关于 Oracle 全文检索实践 的文章
http://www.iteye.com/topic/1118055 有详细的例子记录了Oracle 全文检索的使用.
- 权限知识中的AIX ACL
Aix ACL是对标准权限位的扩展.通过修改分配给个人或组的标准权限,对每个文件或目录进行更精细的控制. 对每个组或用户,有3种权限分配情况: PERMIT : 准许对文件或目录的特定权限. DEMY ...
- Appium——appium之mac环境安装
一.安装brew:Homebrew是一款Mac OS平台下的软件包管理工具执行:/usr/bin/ruby -e "$(curl -fsSL https://raw.githubuserco ...
- Python查看类或Module的版本号
>>> import keras >>> print keras.__version__ 1.2.0
- CAD安装失败怎样卸载CAD 2016?错误提示某些产品无法安装
AUTODESK系列软件着实令人头疼,安装失败之后不能完全卸载!!!(比如maya,cad,3dsmax等).有时手动删除注册表重装之后还是会出现各种问题,每个版本的C++Runtime和.NET f ...
- Express中404页面
404页面是各大网站都需要的. 在做express项目时,应当注意,404页面在app.js中的判断是在最后的,使用这个中间件时,不需要next(),因为它是最后一个了. 它之前一般是router. ...
- pat05-图1. List Components (25)
05-图1. List Components (25) 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue For a ...
- Quartz使用(3) - Quartz核心接口Trigger
Trigger最常用的有两种SimpleTrigger和CronTrigger,首先介绍Trigger的一些基础的信息,然后会详细描述这两种Trigger. 1. 通用Trigger属性 quartz ...
- HDU 1045——Fire Net——————【最大匹配、构图、邻接矩阵做法】
Fire Net Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit Sta ...