创建驱动设备(打开、关闭、读取。写入)

驱动代码

#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.写入数据到设备

它们直接的交互,则是通过一个缓冲区。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值