当前位置:网站首页>驱动与应用程序通信
驱动与应用程序通信
2022-07-03 15:20:00 【宇龍_】
前言
本文讲述的是Windows操作系统下驱动程序与应用程序之间的通信,说简单点就是相互发送数据。
正文
在应用程序中,可以通过CreateFile来打开设备,然后通过DeviceIoControl来向驱动发送或接收数据;而驱动程序则需要通过创建控制设备对象,并创建符号链接,通过分发函数来处理应用程序的数据,总之按这个流程来就完事儿了,还是相对比较简单,直接上代码,不清楚的可以留言。
注意:
关于符号链接和设备对象是否创建成功,可以通过微软提供的winobj工具进行查看
【WinObj - Windows Sysinternals | Microsoft Docs】
驱动的注册、加载则可以使用KmdManager工具完成。
实例
应用程序代码(main.cpp):
#include <iostream>
#include <Windows.h>
#define DEVICE_NAME L"\\\\.\\MsgCenterKernal"
//读设备
#define READ_CTL_CODE CTL_CODE(FILE_DEVICE_UNKNOWN,0x830,METHOD_BUFFERED,FILE_READ_ACCESS)
//写设备
#define WRITE_CTL_CODE CTL_CODE(FILE_DEVICE_UNKNOWN,0x831,METHOD_BUFFERED,FILE_WRITE_ACCESS)
DWORD WriteDevice(HANDLE hDevice, char *szBuff, DWORD dwLen)
{
DWORD dwWrite = 0;
DeviceIoControl(hDevice, WRITE_CTL_CODE, szBuff, dwLen, NULL, 0, &dwWrite, NULL);
return dwWrite;
}
DWORD ReadDevice(HANDLE hDevice, char *szBuff, DWORD dwLen)
{
DWORD dwRead = 0;
DeviceIoControl(hDevice, READ_CTL_CODE, NULL, 0, szBuff, dwLen, &dwRead, NULL);
return dwRead;
}
int main()
{
HANDLE hDevice = CreateFile(DEVICE_NAME, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_DEVICE, NULL);
if (hDevice == INVALID_HANDLE_VALUE)
{
printf("open Device error!\n");
return 0;
}
do
{
char szData[100] = "Hello Driver,I am App!";
char szCache[1024];
system("pause");
//DeviceIoControl read write
DWORD dwWriteNumber = WriteDevice(hDevice, szData, strlen(szData)+1);
printf("DeviceIoControl Write:%s,size:%d\n",szData,dwWriteNumber);
system("pause");
memset(szCache, 0, sizeof(szCache));
DWORD dwReadNumber = ReadDevice(hDevice, szCache, sizeof(szCache) - 1);
printf("DeviceIoControl Read:%s,size:%d\n", szCache, dwReadNumber);
system("pause");
} while (FALSE);
CloseHandle(hDevice);
return 0;
}
驱动程序代码(Driver.c):
#include <ntddk.h>
#define DEVICE_NAME L"\\Device\\MsgCenterKernal"
#define SYMBOLIC_LINK_NAME L"\\??\\MsgCenterKernal"
//读设备
#define READ_CTL_CODE CTL_CODE(FILE_DEVICE_UNKNOWN,0x830,METHOD_BUFFERED,FILE_READ_ACCESS)
//写设备
#define WRITE_CTL_CODE CTL_CODE(FILE_DEVICE_UNKNOWN,0x831,METHOD_BUFFERED,FILE_WRITE_ACCESS)
//全局变量
//设备控制对象
PDEVICE_OBJECT g_pControlDeviceObj = NULL;
void DriverUnload(PDRIVER_OBJECT pDriverObject)
{
DbgPrint("Driver Unload...\n");
UNICODE_STRING strSymbolicLinkName;
RtlInitUnicodeString(&strSymbolicLinkName, SYMBOLIC_LINK_NAME);
IoDeleteSymbolicLink(&strSymbolicLinkName);
if (pDriverObject->DeviceObject)
{
IoDeleteDevice(pDriverObject->DeviceObject);
g_pControlDeviceObj = NULL;
}
}
NTSTATUS OnMsgDispatch(PDEVICE_OBJECT pDeviceObject, IRP* pIrp)
{
NTSTATUS nStatus = STATUS_SUCCESS;
ULONG lRetLen = 0;
//请求当前栈空间
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);
//判断是否是发送给控制设备对象的
if (pDeviceObject == g_pControlDeviceObj)
{
do
{
//判断请求的种类
//打开和关闭都返回成功
if (stack->MajorFunction == IRP_MJ_CREATE || stack->MajorFunction == IRP_MJ_CLOSE)
{
break;
}
//处理DeviceIoControl
if (stack->MajorFunction == IRP_MJ_DEVICE_CONTROL)
{
//根据IoControlCode进行处理
ULONG ioControlCode = stack->Parameters.DeviceIoControl.IoControlCode;
//数据
PVOID pBuffer = pIrp->AssociatedIrp.SystemBuffer;
//输入内核的数据大小
ULONG lInLen = stack->Parameters.DeviceIoControl.InputBufferLength;
//内核输出的数据大小
ULONG lOutLen = stack->Parameters.DeviceIoControl.OutputBufferLength;
switch (ioControlCode)
{
case WRITE_CTL_CODE:
{
//读取发送到内核的数据
if (pBuffer != NULL && lInLen > 0)
{
//一般要对输入的数据大小进行判断,超过长度的的就返回错误!这里未做相关处理
DbgPrint("App write to Driver size:%d,data:%s", lInLen, pBuffer);
//更新内核处理的数据大小
lRetLen = lInLen;
}
break;
}
case READ_CTL_CODE:
{
//内核发送到应用层
DbgPrint("app want to read from driver size:%d", lOutLen);
const char*pData = "Hello App,I am Driver";
int len = strlen(pData) + 1;
memcpy(pBuffer, pData, len);
//更新内核处理的数据大小
lRetLen = len;
break;
}
default:
{
//不接受的请求,一律返回非法
nStatus = STATUS_INVALID_PARAMETER;
break;
}
}
break;
}
//剩余一律返回参数错误
nStatus = STATUS_INVALID_PARAMETER;
} while (FALSE);
}
//结束请求
pIrp->IoStatus.Information = lRetLen;
pIrp->IoStatus.Status = nStatus;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return nStatus;
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath)
{
NTSTATUS nStatus = STATUS_UNSUCCESSFUL;
DbgPrint("Driver Entry...\n");
do
{
UNICODE_STRING strDeviceName, strSymbolLinkName;
RtlInitUnicodeString(&strDeviceName, DEVICE_NAME);
RtlInitUnicodeString(&strSymbolLinkName, SYMBOLIC_LINK_NAME);
//或替换成IoCreateDeviceSecure
nStatus = IoCreateDevice(pDriverObject, 0, &strDeviceName, FILE_DEVICE_UNKNOWN, 0, TRUE, &g_pControlDeviceObj);
if (!NT_SUCCESS(nStatus))
{
DbgPrint("Create Device Object Error:%x\n",nStatus);
break;
}
g_pControlDeviceObj->Flags |= DO_BUFFERED_IO;
//创建符号链接
nStatus = IoCreateSymbolicLink(&strSymbolLinkName, &strDeviceName);
if (!NT_SUCCESS(nStatus))
{
DbgPrint("Create SymbolicLink Error:%x\n", nStatus);
IoDeleteDevice(g_pControlDeviceObj);
g_pControlDeviceObj = NULL;
break;
}
//设置统一的分发函数
for (int i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; ++i)
{
pDriverObject->MajorFunction[i] = OnMsgDispatch;
}
pDriverObject->DriverUnload = DriverUnload;
} while (FALSE);
return nStatus;
}
边栏推荐
- [attention mechanism] [first vit] Detr, end to end object detection with transformers the main components of the network are CNN and transformer
- Global and Chinese markets for indoor HDTV antennas 2022-2028: Research Report on technology, participants, trends, market size and share
- 整形和浮点型是如何在内存中的存储
- 什么是embedding(把物体编码为一个低维稠密向量),pytorch中nn.Embedding原理及使用
- SQL server安装位置改不了
- "Seven weapons" in the "treasure chest" of machine learning: Zhou Zhihua leads the publication of the new book "machine learning theory guide"
- 【注意力机制】【首篇ViT】DETR,End-to-End Object Detection with Transformers网络的主要组成是CNN和Transformer
- 视觉上位系统设计开发(halcon-winform)-6.节点与宫格
- What is one hot encoding? In pytoch, there are two ways to turn label into one hot coding
- Center and drag linked global and Chinese markets 2022-2028: Research Report on technology, participants, trends, market size and share
猜你喜欢
北京共有产权房出租新规实施的租赁案例
Summary of concurrent full knowledge points
什么是embedding(把物体编码为一个低维稠密向量),pytorch中nn.Embedding原理及使用
Halcon与Winform学习第一节
Concurrency-02-visibility, atomicity, orderliness, volatile, CAS, atomic class, unsafe
Halcon与Winform学习第二节
Incluxdb2 buckets create database
Concurrency-01-create thread, sleep, yield, wait, join, interrupt, thread state, synchronized, park, reentrantlock
Kubernetes advanced training camp pod Foundation
[pytorch learning notes] datasets and dataloaders
随机推荐
SQL server安装位置改不了
The method of parameter estimation of user-defined function in MATLAB
Global and Chinese market of postal automation systems 2022-2028: Research Report on technology, participants, trends, market size and share
[set theory] inclusion exclusion principle (complex example)
Besides lying flat, what else can a 27 year old do in life?
Apache ant extension tutorial
北京共有产权房出租新规实施的租赁案例
官网MapReduce实例代码详细批注
Redis主从、哨兵、集群模式介绍
[cloud native training camp] module 7 kubernetes control plane component: scheduler and controller
Enable multi-threaded download of chrome and edge browsers
redis缓存穿透,缓存击穿,缓存雪崩解决方案
Visual upper system design and development (Halcon WinForm) -4 Communication management
Leetcode sword offer find the number I (nine) in the sorted array
Redis cache penetration, cache breakdown, cache avalanche solution
Influxdb2 sources add data sources
App global exception capture
Construction of operation and maintenance system
Visual upper system design and development (Halcon WinForm) -5 camera
Incluxdb2 buckets create database