最近根据梦织未来论坛的驱动教程学习了一下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课 驱动的编程规范的更多相关文章

  1. 梦织未来Windows驱动编程 第05课 小结(读取另一驱动,遍历所有驱动)

    读取另一驱动 驱动通过"\\Driver\\XueTr"获取到了XueTr工具的驱动,并Hook了XueTr驱动的分发函数. 具体的驱动代码如下: //FilterDriver.c ...

  2. 梦织未来Windows驱动编程 第06课 驱动对磁盘文件的操作

    代码部分: 实现一个文件C:\\text.txt,并读取写入内容到文件,然后将文件设置为只读,并隐藏文件.代码如下: //MyCreateFile.c //2016.07.22 #include &l ...

  3. 梦织未来Windows驱动编程 第04课 驱动相关的数据结构

  4. 《天书夜读:从汇编语言到windows内核编程》五 WDM驱动开发环境搭建

    (原书)所有内核空间共享,DriverEntery是内核程序入口,在内核程序被加载时,这个函数被调用,加载入的进程为system进程,xp下它的pid是4.内核程序的编写有一定的规则: 不能调用win ...

  5. PL2303HX在Windows 10下面不装安装驱动的解决办法(Code:10)

    Prolific在很早之前推出了一款名为PL2303HX的芯片, 用于USB转RS232, 这款芯片使用的范围非常广, 并且年代久远. 但是这款芯片因为用的特别多, 所以中国就有很多厂家生产了仿造的P ...

  6. 重新想象 Windows 8 Store Apps (44) - 多线程之异步编程: 经典和最新的异步编程模型, IAsyncInfo 与 Task 相互转换

    [源码下载] 重新想象 Windows 8 Store Apps (44) - 多线程之异步编程: 经典和最新的异步编程模型, IAsyncInfo 与 Task 相互转换 作者:webabcd 介绍 ...

  7. 重新想象 Windows 8 Store Apps (45) - 多线程之异步编程: IAsyncAction, IAsyncOperation, IAsyncActionWithProgress, IAsyncOperationWithProgress

    [源码下载] 重新想象 Windows 8 Store Apps (45) - 多线程之异步编程: IAsyncAction, IAsyncOperation, IAsyncActionWithPro ...

  8. windows下编译qt的mysql驱动

    windows下编译qt的mysql驱动cd %QTDIR%\src\plugins\sqldrivers\mysqlqmake –o Makefile INCLUDEPATH+="C:\M ...

  9. Java并发编程实战 03互斥锁 解决原子性问题

    文章系列 Java并发编程实战 01并发编程的Bug源头 Java并发编程实战 02Java如何解决可见性和有序性问题 摘要 在上一篇文章02Java如何解决可见性和有序性问题当中,我们解决了可见性和 ...

随机推荐

  1. 75th LeetCode Weekly Contest Champagne Tower

    We stack glasses in a pyramid, where the first row has 1 glass, the second row has 2 glasses, and so ...

  2. Linux 文件系统的目录结构

    http://www.jb51.net/LINUXjishu/151820.htmlLinux下的文件系统为树形结构,入口为/ 树形结构下的文件目录: 无论哪个版本的Linux系统,都有这些目录,这些 ...

  3. 权限知识中的AIX ACL

    Aix ACL是对标准权限位的扩展.通过修改分配给个人或组的标准权限,对每个文件或目录进行更精细的控制. 对每个组或用户,有3种权限分配情况: PERMIT : 准许对文件或目录的特定权限. DEMY ...

  4. hdu2067 小兔的棋盘

    小兔的棋盘 时间限制:1000/1000 MS(Java / Others)内存限制:32768/32768 K(Java / Others)总提交内容:13029接受的提交内容:6517 问题描述 ...

  5. hdu2064 汉诺塔Ⅲ(递归)

    汉诺塔III Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Subm ...

  6. Autel MaxiSys Pro Description

    Autel MaxiSys pro MS908P is an evolutionary smart solution for specialized automotive diagnosis and ...

  7. UVA - 213解题报告

    题目链接:https://cn.vjudge.net/problem/UVA-213 Sample input TNM AEIOU 0010101100011 1010001001110110011 ...

  8. gitlab 邮件配置

    vim /etc/gitlab/gitlab.rb gitlab_rails['smtp_enable'] = true gitlab_rails['smtp_address'] = "sm ...

  9. Android NDK开发 环境配置(一) 之多重CPU的兼容性

    今天我学习Android Studio当中的NDK,为什么要学习NDK呢,是因为领导给我提了一个BUG,这个BUG就是Android 多重CPU怎样兼容性,我现在先说一下,Android Studio ...

  10. Factorization Machines with libFM 论文阅读

    Factorization Machines with libFM https://pan.baidu.com/s/1aAyhHGNSrZQFDfoz8VsHIQ libFM网站:http://www ...