IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 创建一个基础WDM驱动,并使用MFC调用驱动 -> 正文阅读

[C++知识库]创建一个基础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;
}

程序完成了几项工作:

  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 here
   devicehandle = 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 here
   if (devicehandle != INVALID_HANDLE_VALUE) {
      CloseHandle(devicehandle);
   }
}


void CAppDlg::OnBnClickedButton3()
{
   // TODO: Add your control notification handler code here
   WCHAR *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 here
   WCHAR 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个按钮,依次显示如下:
在这里插入图片描述

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-06-29 18:48:02  更:2022-06-29 18:50:04 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年4日历 -2024/4/26 4:32:14-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码