首先参考文章:如何使用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;
}

程序完成了几项工作:

  1. 定义了Device Control Code,读写code分别为0x801和0x802,微软为用户开放了0x800~0xfff的control code;
  2. 定义了DeviceName和SymbolLinkName,device/symbolink name一旦创建成功,可以通过WinObj查看,这个工具可以查看系统中的Device和用于用户调用(File IO) device别名symbolink name:

  3. DriverEntry入口函数创建了device和symbolink,并配置了分派函数用于响应用户的各种请求。
  4. DispatchPassThru函数响应IRP,处理了Device open和close请求。
  5. DispatchDevCTL函数响应用户的IO请求。具体是指读写请求,这里会用到之前定义的Device Control Code。
  6. 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调用驱动相关推荐

  1. 如何创建一个基础jQuery插件

    如何创建一个基础插件 How to Create a Basic Plugin 有时你想使一块功能性的代码在你代码的任何地方有效.比如,也许你想调用jQuery对象的一个方法,对该对象进行一系列的操作 ...

  2. UE4-如何做一个简单的TPS角色(一)-创建一个基础角色

    打开UE4进入创建项目界面,选择游戏,第三人称项目进入下一步 按照以下配置创建一个项目,命名任意,一定要包含初学者内容!!!关系到后面素材使用 项目创建完成后,先创建一个Level文件夹,在文件夹中创 ...

  3. 【Django快速开发实战】(1~29)使用Django创建一个基础应用:职位管理系统

    1.总体描述 1.1产品需求: 1.2职位管理系统-建模 1.3 Django项目代码结构 新增recruitment项目 django-admin startproject recruitment ...

  4. data的值 如何初始化vue_vue 创建一个基础实例【02】

    学习要点:1.框架理解    2.options    3.生命周期 本节课我们来开始学习 Vue 声明对象,并且理解传递选项对象的方法. 一.框架理解 1. 所有的前端框架基本都是为了简化:模版渲染 ...

  5. 1 创建一个存储过程,以及对存储过程的调用 MySQL

    1  首先创建一张tb1表  sql语句如下 CREATE TABLE `tb1` (   `Id` int(11) NOT NULL AUTO_INCREMENT,   `age` int(11) ...

  6. python创建一个relu激活函数的类并进行调用

    本文通过对relu激活函数的剖析,学习类的创建与实例化,数组与列表的区别,copy函数的用法等知识,均在注释中有所提及: import numpy as np class ReLU:def __ini ...

  7. python不能创建集合的有哪些_Python3基础 frozenset() 创建一个不可更改的集合

    镇场诗: 诚听如来语,顿舍世间名与利.愿做地藏徒,广演是经阎浮提. 愿尽吾所学,成就一良心博客.愿诸后来人,重现智慧清净体. ------------------------------------- ...

  8. 用Odoo创建一个网站

    原贴地址:https://www.odoo.com/documentation/10.0/howtos/website.html 声明:这篇指导假设你有python的知识并安装了Odoo,请注意文件的 ...

  9. Minecraft 1.12.2模组开发(三) 创建一个物品(item)+物品栏

    本次我们来介绍一下如何创建一个基础物品: 演示包名:com.Joy187.newmod (之后都简称为包名) 1. 新建 -> 创建一个 包名.init 包 2.在刚刚创建的init包中新建一个 ...

  10. yy神曲url解析php_使用PHP来简单的创建一个RPC服务

    RPC全称为Remote Procedure Call,翻译过来为"远程过程调用".主要应用于不同的系统之间的远程通信和相互调用. 比如有两个系统,一个是PHP写的,一个是JAVA ...

最新文章

  1. SAP MM 条件类型中PB00的‘Group Cond.‘标记的作用?
  2. python一个月能挣多少钱-零基础学python,我可以让你一个月上手做项目!
  3. 汇总内表数据:at end of方法和collect方法
  4. 一文读懂“新一代人工智能地图” ,让AI真正走进用户的生活
  5. 【输入一个年份,判断是否为闰年(leap year)】
  6. iTOP-i.MX6Q开发板支持安卓Android6.0系统
  7. mapbox 将坐标转换成米
  8. 电脑右击文件夹无反应
  9. paip.asp 项目流程及管理工具总结
  10. centos ipython tab键上下键不起作用
  11. H3C交换机配置SSH
  12. Kafka原理以及分区分配策略剖析
  13. Meta http-equiv属性详解(转)
  14. USB 驱动程序(转贴)
  15. CCS 3.3 创建DSP TMSC6726B工程
  16. Bert入门:使用Bert运行MRPC的demo成功案例
  17. 人脸识别技术发展及实用方案设计
  18. windows 中开机自启动命令行(CLI)
  19. 二分查找、求上界和下界(包括内置函数lower_bound、和upper_bound的使用)
  20. 目前最新《Swift4打造今日头条视频实战教程》

热门文章

  1. 计算机word excel试题,计算机基础WORD、EXCEL试题
  2. List数据去重的五种有效方法
  3. java地图 热力图,Spring Boot+高德地图热力图静态数据展示
  4. PMP课程笔记:第11章 项目风险管理
  5. android 打印机 万能驱动,万能打印机驱动专家
  6. 和cc2500通信时总是读入0F
  7. 安装VMware虚拟机及镜像文件
  8. dedecms如何制作中英文切换的网站?
  9. oppo强制升级android版本,OPPO R17升级更新安卓9.0固件rom刷机包:正式版本-C.10
  10. Reactor 线程模型