当前位置:网站首页>创建一个基础WDM驱动,并使用MFC调用驱动
创建一个基础WDM驱动,并使用MFC调用驱动
2022-06-27 05:42:00 【小飞将】
首先参考文章:如何使用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 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个按钮,依次显示如下:
边栏推荐
猜你喜欢
Quick sort (non recursive) and merge sort
Go日志-Uber开源库zap使用
Using domain name forwarding mqtt protocol, pit avoidance Guide
Two position relay hjws-9440
Web3 has not been implemented yet, web5 suddenly appears!
齐纳二极管 稳压二极管 SOD123封装 正负区分
Dual position relay dls-34a dc0.5a 220VDC
思维的技术:如何破解工作生活中的两难冲突?
Two position relay xjls-8g/220
双位置继电器RXMD2-1MRK001984 DC220V
随机推荐
Nlp-d62-nlp competition d31 & question brushing D15
When STM32 turns off PWM output, it is a method to fix IO output at high or low level.
jq怎么获取元素的id名
Edge loads web pages in IE mode - edge sets ie compatibility
AcWing 第 57 场周赛---BC题挺好
《数据库原理与应用》第一版 马春梅……编著 期末复习笔记
【Cocos Creator 3.5.1】this. node. Use of getposition (this.\u curpos)
【NIPS 2017】PointNet++:度量空间中点集的深层次特征学习
STM32关闭PWM输出时,让IO输出固定高或低电平的方法。
【Cocos Creator 3.5.1】input.on的使用
牛客练习赛101-C 推理小丑---位运算+思维
NLP-D62-nlp比赛D31&刷题D15
Open the door small example to learn ten use case diagrams
C# netcore中 配置帮助类IConfiguration
Codeforces Round #802 (Div. 2)
微信小程序WebSocket使用案例
Unicast, multicast and broadcast of IP network communication
Unity中跨平台获取系统音量
体验 win10 下 oceanbase 数据库
齐纳二极管 稳压二极管 SOD123封装 正负区分