驱动代码
#include<ntddk.h>
#define SYM_NAME L"\\??\\MaoYu"
// 驱动对象卸载的处理函数(回调)
void unLoad(PDRIVER_OBJECT pDriverObject)
{
// 如果驱动设备存在
if (pDriverObject->DeviceObject)
{
// 删除符号链接
UNICODE_STRING symName;
RtlInitUnicodeString(&symName, SYM_NAME); // 初始化字符结构
IoDeleteSymbolicLink(&symName); // 删除符号链接
// 删除驱动设备
IoDeleteDevice(pDriverObject->DeviceObject);
DbgPrint("删除设备成功"); // 打印调式信息
}
// 打印驱动卸载成功消息
DbgPrint("驱动卸载成功++++++++");
}
// IRP 请求 创建(回调) 1.驱动设备 2.rip对象
NTSTATUS myCreate(PDEVICE_OBJECT pDveice, PIRP prip)
{
DbgPrint("用户 创建动作");
// 将信息设置为0
prip->IoStatus.Information = 0L;
// IRP的处理状态
{
// 将请求设置为成功
prip->IoStatus.Status = STATUS_SUCCESS;
// 指示已完成了IO请求 1.IRP指针 2.系统定义的CCHAR常数
IoCompleteRequest(prip, IO_NO_INCREMENT);
}
return STATUS_SUCCESS;
}
// IRP 请求 清除 (回调) 1.驱动设备 2.rip对象
NTSTATUS myCleanUp(PDEVICE_OBJECT pDveice, PIRP prip)
{
DbgPrint("用户 清除动作");
// 将信息设置为0
prip->IoStatus.Information = 0L;
// IRP的处理状态
{
// 将请求设置为成功
prip->IoStatus.Status = STATUS_SUCCESS;
// 指示已完成了IO请求 1.IRP指针 2.系统定义的CCHAR常数
IoCompleteRequest(prip, IO_NO_INCREMENT);
}
return STATUS_SUCCESS;
}
// IRP 请求 关闭(回调) 1.驱动设备 2.rip对象
NTSTATUS myClose(PDEVICE_OBJECT pDveice, PIRP prip)
{
DbgPrint("用户 关闭动作");
// 将信息设置为0
prip->IoStatus.Information = 0L;
// IRP的处理状态
{
// 将请求设置为成功
prip->IoStatus.Status = STATUS_SUCCESS;
// 指示已完成了IO请求 1.IRP指针 2.系统定义的CCHAR常数
IoCompleteRequest(prip, IO_NO_INCREMENT);
}
return STATUS_SUCCESS;
}
// IRP 请求 读取(回调) 1.驱动设备 2.rip对象
NTSTATUS myRead(PDEVICE_OBJECT pDveice, PIRP prip)
{
DbgPrint("用户 读取动作");
// 返回一个指向呼叫者的I / O栈位置指定IRP,返回一个IO栈位置的结构体指针
PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(prip);
// 拿到IRP要读取的大小
ULONG size = pStack->Parameters.Read.Length;
// 处理IRP读取动作
{
// 拿到IRP的缓冲区 SystemBuffer 指向系统空间缓冲区的指针 PVOID类型
PVOID buffer = prip->AssociatedIrp.SystemBuffer;
// 定义一个字符串
const char* content = "我是大猫鱼";
// 计算字符串的长度
size_t count = strlen(content);
// 将数据写入到 IRP 缓冲区
RtlCopyMemory(buffer, content, strlen(content));
// IRP的格式信息 赋值为写入的长度
prip->IoStatus.Information = count;
}
// IRP结果的处理状态
{
// 将请求设置为成功
prip->IoStatus.Status = STATUS_SUCCESS;
// 指示已完成了IO请求 1.IRP指针 2.系统定义的CCHAR常数
IoCompleteRequest(prip, IO_NO_INCREMENT);
}
return STATUS_SUCCESS;
}
// IRP 请求 写入(回调) 1.驱动设备 2.rip对象
NTSTATUS myWrite(PDEVICE_OBJECT pDveice, PIRP prip)
{
DbgPrint("用户 写入动作");
// 返回一个指向呼叫者的I / O栈位置指定IRP,返回一个IO栈位置的结构体指针
PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(prip);
// 拿到IRP要写入的大小
ULONG size = pStack->Parameters.Write.Length;
// 拿到IRP的缓冲区 SystemBuffer 指向系统空间缓冲区的指针 PVOID类型
PVOID buffer = prip->AssociatedIrp.SystemBuffer;
// 处理IRP请求
{
// 将IRP缓冲区的内容拷贝到设备扩展字节缓冲区
RtlCopyMemory(pDveice->DeviceExtension, buffer, size);
// IRP的格式信息 赋值为写入的长度
prip->IoStatus.Information = size;
// 打印调式信息
DbgPrint("IRP:%s", (PCHAR)pDveice->DeviceExtension);
}
// IRP结果的处理状态
{
// 将请求设置为成功
prip->IoStatus.Status = STATUS_SUCCESS;
// 指示已完成了IO请求 1.IRP指针 2.系统定义的CCHAR常数
IoCompleteRequest(prip, IO_NO_INCREMENT);
}
return STATUS_SUCCESS;
}
// 驱动入口函数 1.驱动对象指针 2.路径的对象指针
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath)
{
// 设置驱动对象卸载回调以及打印调式信息
{
// 设置驱动对象的卸载函数
pDriverObject->DriverUnload = unLoad;
// 打印驱动加载成功消息
DbgPrint("驱动加载:%wS", pRegPath->Buffer);
}
// 驱动的名称
UNICODE_STRING deviceName;
// 驱动设备对象指针
PDEVICE_OBJECT pDevice = NULL;
// 创建驱动设备
{
// 初始化Unicode字符串的计数器
RtlInitUnicodeString(&deviceName, L"\\Device\\MaoYu");
// 创建一个驱动程序使用的设备对象。
NTSTATUS status = IoCreateDevice(
pDriverObject, // 驱动对象地址
1024L, // 设备扩展的字节数大小
&deviceName, // 驱动设备的名称
FILE_DEVICE_UNKNOWN, // 未知的设备
0L, // 有关设备的其它信息
TRUE, // 是否代表专业对象
&pDevice); // 驱动设备的指针
// 如果驱动设备创建失败
if (status != STATUS_SUCCESS)
{
DbgPrint("创建驱动设备失败"); // 打印错误信息
return status;
}
}
// 创建对外的符号链接
{
UNICODE_STRING symName; // 设备符号链接
// 初始化设备符号字符结构
RtlInitUnicodeString(&symName, SYM_NAME);
// 创建符号链接 1.符号链接的字符结构 2.驱动设备的名称
NTSTATUS status = IoCreateSymbolicLink(&symName, &deviceName);
if (status != STATUS_SUCCESS)
{
DbgPrint("创建符号链接失败"); // 打印错误信息
IoDeleteDevice(pDevice); // 删除设备
return status;
}
}
// 设置 驱动对象的标志类型 通过缓冲区进行 IO处理,注意要进行按位 或运算
pDevice->Flags |= DO_BUFFERED_IO;
// 处理IRP请求
{
// IRP创建动作
pDriverObject->MajorFunction[IRP_MJ_CREATE] = myCreate;
// IRP清除动作
pDriverObject->MajorFunction[IRP_MJ_CLEANUP] = myCleanUp;
// IRP关闭动作
pDriverObject->MajorFunction[IRP_MJ_CLOSE] = myClose;
// IRP读取动作
pDriverObject->MajorFunction[IRP_MJ_READ] = myRead;
// IRP写入动作
pDriverObject->MajorFunction[IRP_MJ_WRITE] = myWrite;
}
return STATUS_SUCCESS;
}
c++代码
#include<iostream>
#include<string>
#include<Windows.h>
int main(const int argc, const char** argv)
{
HANDLE hFile = NULL;
hFile = ::CreateFileW(
L"\\\\.\\MaoYu",
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
std::cout << "设备打开失败" << std::endl;
system("pause");
return 1;
}
else
{
std::cout << "设备打开成功" << std::endl;
}
system("pause");
// 读取
{
PCHAR buffer[1024]{ 0 };
if (::ReadFile(hFile, buffer, sizeof(buffer), NULL, NULL))
{
printf("%s", buffer);
}
else
{
std::cout << "读取错误" << std::endl;
system("pause");
::CloseHandle(hFile);
return 1;
}
system("pause");
}
// 写入
{
std::string str = "hello word";
if (::WriteFile(hFile, str.c_str(), str.length(), NULL, NULL))
{
std::cout << "写入成功" << std::endl;
}
else
{
std::cout << "写入失败" << std::endl;
}
}
system("pause");
::CloseHandle(hFile);
}
这简单的实例,简单的流程解释
// 驱动端
1.创建一个驱动设备
2.创建这个设备的外部符号链接
3.设置这个设备的通信标志(Flags)
4.设置IRP请求的回调函数
// 用户端
1.打开一个设备
2.读取设备的数据
3.写入数据到设备
它们直接的交互,则是通过一个缓冲区。