64位驱动开发之读写驱动程序IRP_MJ_READ和IRP_MJ_WRITE的IO

64位驱动开发之读写驱动程序IRP_MJ_READ和IRP_MJ_WRITE的IO

提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
例如:第一章 64位驱动开发之读写驱动程序IRP_MJ_READ和IRP_MJ_WRITE的IO


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档


64位驱动开发之读写驱动程序IRP_MJ_READ和IRP_MJ_WRITE的IO

一、64位驱动开发之读写驱动程序IRP_MJ_READ和IRP_MJ_WRITE的IO

MFC读写代码
这边用了两个按钮
具体实现步骤如下:
第一步:在用户层(MFC工程项目里)选“资源视图”,在对话框里双击“IRP_MJ_READ”按钮和IRP_MJ_WRITE按钮,在里面添加如下代码:

void CD00910MFCDlg::OnBnClickedButton1IrpMjWrite()
{
	// TODO: 在此添加控件通知处理程序代码
	char 输入缓冲区[] = "yjx:R3 WriteFile写测试";
	DWORD len = 0;//返回实际写如字节集数量
	BOOL ret = WriteFile(DeviceHandle, 输入缓冲区, sizeof(输入缓冲区), &len, 0);
}


void CD00910MFCDlg::OnBnClickedButton1IrpMjRead()
{
	// TODO: 在此添加控件通知处理程序代码
	char 输出缓冲区[512] = { 0 };
	DWORD len = 0;//返回实际写如字节集数量
	BOOL ret = ReadFile(DeviceHandle, 输出缓冲区, sizeof(输出缓冲区), &len/*返回实际读取大小*/, 0);
	char buf[256];
	sprintf_s(buf, "ret=%d 输入缓冲区=%s,len=%d yjx", ret, 输出缓冲区,len);
	OutputDebugStringA(buf);
}

在这里插入图片描述

二、驱动读写代码

第二步:在驱动层写相应的操作代码,这里我们可以把读写取数据的代码单独写到一个函数里,代码如下:

	//READ WRITE
	DriverObject->MajorFunction[IRP_MJ_READ] = IRP_CALL;   //ReadFile ReadFileEx
	DriverObject->MajorFunction[IRP_MJ_WRITE] = IRP_CALL;   //WriteFile NtWriteFile ZwWriteFile

完整代码

	//加载驱动时被调用
NTSTATUS
DriverEntry(
	_In_ PDRIVER_OBJECT DriverObject,
	_In_ PUNICODE_STRING RegistryPath
)
{
	RegistryPath;

	DriverObject->DriverUnload = DriverUnload;//注册卸载例程-回调函数
	DriverObject->MajorFunction[IRP_MJ_CREATE] = IRP_CALL;
	DriverObject->MajorFunction[IRP_MJ_CLOSE] = IRP_CALL;
	DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IRP_CALL;
	
	//READ WRITE
	DriverObject->MajorFunction[IRP_MJ_READ] = IRP_CALL;   //ReadFile ReadFileEx
	DriverObject->MajorFunction[IRP_MJ_WRITE] = IRP_CALL;   //WriteFile NtWriteFile ZwWriteFile
	CreateDevice(DriverObject);//创建驱动设备

	KdPrint(("yjx:进入DriverEntry入口点 DriverObject=%p 行号=%d\n", DriverObject, __LINE__));//Debug
	//KdPrint(("yjx:RegistryPath=%s\n, RegistryPath->Buffer"));//多字节字符集
	KdPrint(("yjx:RegistryPath=%ws\n", RegistryPath->Buffer));//Unicode 宽字符
	return 0;//返回成功
}ZwWriteFile

在这里插入图片描述

2.然后在 IRP_CALL函数里直接调用,这里为了不影响上一节课的写入功能,加了case IRP_MJ_READ: case IRP_MJ_WRITE: 。代码如下:

代码如下(示例):

	case IRP_MJ_READ:
	{
		char* 指针1 = (char*)pirp->AssociatedIrp.SystemBuffer;//和IRP有关的系统缓冲区
		char* 指针2 = (char*)pirp->MdlAddress;//和IRP有关的系统缓冲区
		char* 指针3 = (char*)pirp->UserBuffer;//和IRP有关的系统缓冲区

		KdPrint(("yjx:SYS IRP_MJ_READ (%p,%p,%p)", 指针1, 指针2, 指针3));
		char 返回字符串[] = "SYS IRP_MJ_READ返回的字符串";
		ULONG 长度 = sizeof(返回字符串);
		if (指针3 && irpStackL->Parameters.Read.Length >= 长度)
		{
			//irpStackL->Parameters.Read.Length;
			irpStackL->Parameters.Read.Length;
			RtlCopyMemory(指针3, 返回字符串, 长度);
		}
		pirp->IoStatus.Status = STATUS_SUCCESS;
		pirp->IoStatus.Information = 长度;//strlen//对应ReadFile 第4个参数 len
		IoCompleteRequest(pirp, IO_NO_INCREMENT);//调用方已完成所有I/O请求处理操作,并且不增加优先级
		KdPrint(("yjx:IRP_MJ_READ 离开派遣函数"));
		return STATUS_SUCCESS;//返回0,表示成功

		break;
	}
	case IRP_MJ_WRITE://DevieIoControl  输入数据
	{
		char* 指针1 = (char*)pirp->AssociatedIrp.SystemBuffer;//和IRP有关的系统缓冲区
		char* 指针2 = (char*)pirp->MdlAddress;//和IRP有关的系统缓冲区
		char* 指针3 = (char*)pirp->UserBuffer;//和IRP有关的系统缓冲区

		KdPrint(("yjx:SYS IRP_MJ_WRITE (%p,%p,%p)", 指针1, 指针2, 指针3));
		KdPrint(("yjx:SYS IRP_MJ_WRITE (%s,%s,%s)", 指针1, 指针2, 指针3));
		break;
	}
	}
	pirp->IoStatus.Status = STATUS_SUCCESS;
	pirp->IoStatus.Information = 4;//返回给DeviceIoControl中的倒数第二个参数lpBytesReturned
	IoCompleteRequest(pirp, IO_NO_INCREMENT);//调用方已完成所有I/O请求处理操作,并且不增加优先级
	KdPrint(("yjx:离开派遣函数"));
	return STATUS_SUCCESS;//返回0,表示成功

在这里插入图片描述

完整代码

NTSTATUS IRP_CALL(PDEVICE_OBJECT device, PIRP pirp)
{
	device;

	KdPrint(("yjx:进入派遣函数"));
	PIO_STACK_LOCATION irpStackL;

	irpStackL = IoGetCurrentIrpStackLocation(pirp);//获取应用层传来的参数

	switch (irpStackL->MajorFunction)
	{
	case IRP_MJ_DEVICE_CONTROL://DeviceIoControl
	{
		UINT32 控制码 = irpStackL->Parameters.DeviceIoControl.IoControlCode;

		if (控制码 == 读测试)
		{
			IRP_IO_读测试(pirp);
			return STATUS_SUCCESS;
		}
		else if (控制码 == 写测试)
		{
			char* 缓冲区 = (char*)pirp->AssociatedIrp.SystemBuffer;//和IRP有关的系统缓冲区
			KdPrint(("R0 yjx:用户层调用了DeviceIoControl  控制码=%X", 控制码));
			KdPrint(("R0 yjx:用户层调用了DeviceIoControl  控制码=%X 缓冲区=%s", 控制码, 缓冲区));
		}
		else if (控制码 == 读写测试)
		{
			IRP_IO_读写测试(pirp);
			return STATUS_SUCCESS;
		}
		break;
	}
	case IRP_MJ_CREATE://CreateFile
	{
		KdPrint(("yjx:用户层调用了CreateFile"));
		break;
	}
	case IRP_MJ_CLOSE://CloseHandle
	{
		KdPrint(("yjx:用户层调用了CloseHandle"));
		break;
	}
	case IRP_MJ_READ:
	{
		char* 指针1 = (char*)pirp->AssociatedIrp.SystemBuffer;//和IRP有关的系统缓冲区
		char* 指针2 = (char*)pirp->MdlAddress;//和IRP有关的系统缓冲区
		char* 指针3 = (char*)pirp->UserBuffer;//和IRP有关的系统缓冲区

		KdPrint(("yjx:SYS IRP_MJ_READ (%p,%p,%p)", 指针1, 指针2, 指针3));
		char 返回字符串[] = "SYS IRP_MJ_READ返回的字符串";
		ULONG 长度 = sizeof(返回字符串);
		if (指针3 && irpStackL->Parameters.Read.Length >= 长度)
		{
			//irpStackL->Parameters.Read.Length;
			irpStackL->Parameters.Read.Length;
			RtlCopyMemory(指针3, 返回字符串, 长度);
		}
		pirp->IoStatus.Status = STATUS_SUCCESS;
		pirp->IoStatus.Information = 长度;//strlen//对应ReadFile 第4个参数 len
		IoCompleteRequest(pirp, IO_NO_INCREMENT);//调用方已完成所有I/O请求处理操作,并且不增加优先级
		KdPrint(("yjx:IRP_MJ_READ 离开派遣函数"));
		return STATUS_SUCCESS;//返回0,表示成功

		break;
	}
	case IRP_MJ_WRITE://DevieIoControl  输入数据
	{
		char* 指针1 = (char*)pirp->AssociatedIrp.SystemBuffer;//和IRP有关的系统缓冲区
		char* 指针2 = (char*)pirp->MdlAddress;//和IRP有关的系统缓冲区
		char* 指针3 = (char*)pirp->UserBuffer;//和IRP有关的系统缓冲区

		KdPrint(("yjx:SYS IRP_MJ_WRITE (%p,%p,%p)", 指针1, 指针2, 指针3));
		KdPrint(("yjx:SYS IRP_MJ_WRITE (%s,%s,%s)", 指针1, 指针2, 指针3));
		break;
	}
	}
	pirp->IoStatus.Status = STATUS_SUCCESS;
	pirp->IoStatus.Information = 4;//返回给DeviceIoControl中的倒数第二个参数lpBytesReturned
	IoCompleteRequest(pirp, IO_NO_INCREMENT);//调用方已完成所有I/O请求处理操作,并且不增加优先级
	KdPrint(("yjx:离开派遣函数"));
	return STATUS_SUCCESS;//返回0,表示成功
}

##3.虚拟机调试结果


在这里插入图片描述

总结

提示:这里对文章进行总结:

以上就是今天要讲的内容。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

a756598009

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值