创建一个基础WDM驱动,并使用MFC调用驱动
首先参考文章:如何使用WinDbg和Virtual Box进行Windows驱动debug,搭建开发环境。
创建一个Empty WDM项目,在solution下添加一个MFC项目:
其中FirstDriver是一个简单的WDM驱动项目,而App是一个MFC程序,用于调用驱动。
Source.c是驱动源码:
#include "ntddk.h"#define DEVICE_SEND CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_WRITE_DATA)
#define DEVICE_REC CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_READ_DATA)UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\mydevice123");
UNICODE_STRING SymLinkName = RTL_CONSTANT_STRING(L"\\??\\mydevicelink123");
PDEVICE_OBJECT DeviceObject = NULL;VOID Unload(IN PDRIVER_OBJECT DriverObject) {IoDeleteSymbolicLink(&SymLinkName);IoDeleteDevice(DeviceObject);DbgPrint("Driver unload\r\n");
}NTSTATUS DispatchPassThru(PDEVICE_OBJECT DeviceObject, PIRP Irp) {PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation(Irp);NTSTATUS status = STATUS_SUCCESS;switch (irpsp->MajorFunction) {case IRP_MJ_CREATE:DbgPrint("Create request\r\n");/*KdPrint(("Create request\r\n"));*/break;case IRP_MJ_CLOSE:DbgPrint("Close request\r\n");/*KdPrint(("Close request\r\n"));*/break;//case IRP_MJ_READ:// DbgPrint("Read request\r\n");// KdPrint(("Read request\r\n"));// break;default:status = STATUS_INVALID_PARAMETER;break;}Irp->IoStatus.Information = 0;Irp->IoStatus.Status = status;IoCompleteRequest(Irp, IO_NO_INCREMENT);return status;
}NTSTATUS DispathDevCTL(PDEVICE_OBJECT DeviceObject, PIRP Irp) {PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation(Irp);NTSTATUS status = STATUS_SUCCESS;ULONG returnLength = 0;PVOID buffer = Irp->AssociatedIrp.SystemBuffer;ULONG inLength = irpsp->Parameters.DeviceIoControl.InputBufferLength;ULONG outLength = irpsp->Parameters.DeviceIoControl.OutputBufferLength;WCHAR *demo = L"sample return from driver";switch (irpsp->Parameters.DeviceIoControl.IoControlCode) {case DEVICE_SEND:DbgPrint("Send data is %ws \r\n", buffer);returnLength = (wcsnlen(buffer, 511) + 1) * 2;break;case DEVICE_REC:wcsncpy(buffer, demo, 511);returnLength = (wcsnlen(buffer, 511) + 1) * 2;DbgPrint("receive data is %ws \r\n", buffer);break;default:status = STATUS_INVALID_PARAMETER;}Irp->IoStatus.Status = status;Irp->IoStatus.Information = returnLength;IoCompleteRequest(Irp, IO_NO_INCREMENT);return status;
}NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) // main
{DriverObject->DriverUnload = Unload;UNICODE_STRING string = RTL_CONSTANT_STRING(L"hello driver\r\n");DbgPrint("%wZ", &string); // printf()NTSTATUS status = IoCreateDevice(DriverObject, 0, &DeviceName,FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN,FALSE, &DeviceObject);if (!NT_SUCCESS(status)) {DbgPrint("Create device failed\r\n");return status;}status = IoCreateSymbolicLink(&SymLinkName, &DeviceName);if (!NT_SUCCESS(status)) {DbgPrint("create symbolic link failed\r\n");IoDeleteDevice(DeviceObject);return status;}for (int i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; ++i) {DriverObject->MajorFunction[i] = DispatchPassThru;}DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispathDevCTL;DbgPrint("Driver load\r\n");return STATUS_SUCCESS;
}
程序完成了几项工作:
- 定义了Device Control Code,读写code分别为0x801和0x802,微软为用户开放了0x800~0xfff的control code;
- 定义了DeviceName和SymbolLinkName,device/symbolink name一旦创建成功,可以通过WinObj查看,这个工具可以查看系统中的Device和用于用户调用(File IO) device别名symbolink name:
- DriverEntry入口函数创建了device和symbolink,并配置了分派函数用于响应用户的各种请求。
- DispatchPassThru函数响应IRP,处理了Device open和close请求。
- DispatchDevCTL函数响应用户的IO请求。具体是指读写请求,这里会用到之前定义的Device Control Code。
- Unload函数删除symbolink和device对象。
MFC应用程序
界面:
一共4个按钮,分别执行device open/close,以及通过IO发送和接收数据。
#include "winioctl.h"#define DEVICE_SEND CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_WRITE_DATA)
#define DEVICE_REC CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_READ_DATA)HANDLE devicehandle = NULL;void CAppDlg::OnBnClickedButton1()
{// TODO: Add your control notification handler code heredevicehandle = CreateFile(L"\\\\.\\mydevicelink123", GENERIC_ALL, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM,0);if (devicehandle == INVALID_HANDLE_VALUE) {MessageBox(L"Not valid value", 0, 0);return;}MessageBox(L"valid value", 0, 0);
}void CAppDlg::OnBnClickedButton2()
{// TODO: Add your control notification handler code hereif (devicehandle != INVALID_HANDLE_VALUE) {CloseHandle(devicehandle);}
}void CAppDlg::OnBnClickedButton3()
{// TODO: Add your control notification handler code hereWCHAR *message = L"send sample from mfc";WCHAR returnMessage[1024] = { 0 };ULONG returnLength = 0;char wr[4] = { 0 };if (devicehandle != NULL && devicehandle != INVALID_HANDLE_VALUE) {if (!DeviceIoControl(devicehandle, DEVICE_SEND, message,(wcslen(message) + 1) * 2,returnMessage,1024,&returnLength,0)) {MessageBox(L"Device io control failed", 0, 0);}else {MessageBox(returnMessage, 0, 0);_itoa_s(returnLength, wr, 10);MessageBoxA(0, wr, 0, 0);}}
}void CAppDlg::OnBnClickedButton4()
{// TODO: Add your control notification handler code hereWCHAR message[1024] = { 0 };ULONG returnLength = 0;if (devicehandle != NULL && devicehandle != INVALID_HANDLE_VALUE) {if (!DeviceIoControl(devicehandle, DEVICE_REC, NULL,0,message,1024,&returnLength,0)) {MessageBox(L"Device io control failed", 0, 0);}else {MessageBox(message, 0, 0);}}
}
需要注意的是,这里要使用DeviceIoControl函数用于和device进行IO控制,所以include头文件winioctl.h,并且Device control code要和WDM驱动里的code一致。
将编译好的driver.sys和App放入虚拟机,以管理员权限打开OSRLOADER,Register Service和Start Service,以管理员权限打开App,点击4个按钮,依次显示如下:
创建一个基础WDM驱动,并使用MFC调用驱动相关推荐
- 如何创建一个基础jQuery插件
如何创建一个基础插件 How to Create a Basic Plugin 有时你想使一块功能性的代码在你代码的任何地方有效.比如,也许你想调用jQuery对象的一个方法,对该对象进行一系列的操作 ...
- UE4-如何做一个简单的TPS角色(一)-创建一个基础角色
打开UE4进入创建项目界面,选择游戏,第三人称项目进入下一步 按照以下配置创建一个项目,命名任意,一定要包含初学者内容!!!关系到后面素材使用 项目创建完成后,先创建一个Level文件夹,在文件夹中创 ...
- 【Django快速开发实战】(1~29)使用Django创建一个基础应用:职位管理系统
1.总体描述 1.1产品需求: 1.2职位管理系统-建模 1.3 Django项目代码结构 新增recruitment项目 django-admin startproject recruitment ...
- data的值 如何初始化vue_vue 创建一个基础实例【02】
学习要点:1.框架理解 2.options 3.生命周期 本节课我们来开始学习 Vue 声明对象,并且理解传递选项对象的方法. 一.框架理解 1. 所有的前端框架基本都是为了简化:模版渲染 ...
- 1 创建一个存储过程,以及对存储过程的调用 MySQL
1 首先创建一张tb1表 sql语句如下 CREATE TABLE `tb1` ( `Id` int(11) NOT NULL AUTO_INCREMENT, `age` int(11) ...
- python创建一个relu激活函数的类并进行调用
本文通过对relu激活函数的剖析,学习类的创建与实例化,数组与列表的区别,copy函数的用法等知识,均在注释中有所提及: import numpy as np class ReLU:def __ini ...
- python不能创建集合的有哪些_Python3基础 frozenset() 创建一个不可更改的集合
镇场诗: 诚听如来语,顿舍世间名与利.愿做地藏徒,广演是经阎浮提. 愿尽吾所学,成就一良心博客.愿诸后来人,重现智慧清净体. ------------------------------------- ...
- 用Odoo创建一个网站
原贴地址:https://www.odoo.com/documentation/10.0/howtos/website.html 声明:这篇指导假设你有python的知识并安装了Odoo,请注意文件的 ...
- Minecraft 1.12.2模组开发(三) 创建一个物品(item)+物品栏
本次我们来介绍一下如何创建一个基础物品: 演示包名:com.Joy187.newmod (之后都简称为包名) 1. 新建 -> 创建一个 包名.init 包 2.在刚刚创建的init包中新建一个 ...
- yy神曲url解析php_使用PHP来简单的创建一个RPC服务
RPC全称为Remote Procedure Call,翻译过来为"远程过程调用".主要应用于不同的系统之间的远程通信和相互调用. 比如有两个系统,一个是PHP写的,一个是JAVA ...
最新文章
- SAP MM 条件类型中PB00的‘Group Cond.‘标记的作用?
- python一个月能挣多少钱-零基础学python,我可以让你一个月上手做项目!
- 汇总内表数据:at end of方法和collect方法
- 一文读懂“新一代人工智能地图” ,让AI真正走进用户的生活
- 【输入一个年份,判断是否为闰年(leap year)】
- iTOP-i.MX6Q开发板支持安卓Android6.0系统
- mapbox 将坐标转换成米
- 电脑右击文件夹无反应
- paip.asp 项目流程及管理工具总结
- centos ipython tab键上下键不起作用
- H3C交换机配置SSH
- Kafka原理以及分区分配策略剖析
- Meta http-equiv属性详解(转)
- USB 驱动程序(转贴)
- CCS 3.3 创建DSP TMSC6726B工程
- Bert入门:使用Bert运行MRPC的demo成功案例
- 人脸识别技术发展及实用方案设计
- windows 中开机自启动命令行(CLI)
- 二分查找、求上界和下界(包括内置函数lower_bound、和upper_bound的使用)
- 目前最新《Swift4打造今日头条视频实战教程》