64位驱动开发之R3与R0通信交换数据,读写数据测试

64位驱动开发目录

第一章 MFC读写代码
第二章 驱动读写代码

提示:以下是本篇文章正文内容,下面案例可供参考
内核主要由各种驱动(在磁盘上是.sys文件)组成,这些驱动有的是windows系统自带的(例如ntfs.sys、tcpip.sys、win32k.sys),有的是由第三方软件厂商提供的。驱动加载之后,会生成对应的设备对象,并可以选择向R3提供一个可供访问和打开的符号链接。常见的盘符C、D、E等其实都是文件系统驱动创建的设备对象的符号链接,对应的符号链接分别是 “??\C:\” “??\D:\” “??\E:\”等。
应用程序可以根据内核驱动的符号链接名调用CreateFile()函数打开。在获得一个句柄(handle)之后,程序就可以调用应用层函数与内核驱动进行通信了,例如ReadFile()、WriteFile()及DeviceIoControl()等。
我们知道和IRP有关的系统缓冲区(pirp->Associatedlrp.SystemBuffer)是一个读写共享的缓冲区

一、MFC读写代码

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

void CD00910MFCDlg::OnBnClickedButton3IoWr()
{
	// TODO: 在此添加控件通知处理程序代码
	//a+b+c=结果

	// TODO: 在此添加控件通知处理程序代码
	DWORD dwRetSize = 0;//返回字节数

	char buftest[256];
	sprintf_s(buftest, "yjx:EXE R3 读写测试 控制码=%X\n", 读写测试);
	OutputDebugStringA(buftest);

	//int 传入数据[3] = {3,7,8};
#pragma pack(4)
	struct 输入缓冲区
	{
		int a;
		int b;
		int c;
	};
#pragma pack()
	输入缓冲区 传入数据 = { 3,6,5 };

	//数组示例
	int OutBuf = 0 ;//输出缓冲区
	DeviceIoControl(
		DeviceHandle,//CreateFile打开驱动设备 返回的句柄
		读写测试,//控制码 CTL_CODE

		&传入数据,//输入缓冲区指针
		sizeof(传入数据),//输入缓冲区大小

		&OutBuf,//输出缓冲区
		sizeof(OutBuf),//返回缓冲区大小

		&dwRetSize, //返回字节数
		NULL);

	//sprintf_s(buftest, "yjx:%d+%d+%d=%d  读写测试-EXE", 传入数据[0], 传入数据[1], 传入数据[2], OutBuf);
	sprintf_s(buftest, "yjx:%d+%d+%d=%d  读写测试-EXE sizeof(传入数据)=%d", 传入数据.a, 传入数据.b, 传入数据.c, OutBuf, sizeof(传入数据));
	OutputDebugStringA(buftest);

}

在这里插入图片描述

二、驱动读写代码

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

void IRP_IO_读写测试(PIRP pirp)
{
	PIO_STACK_LOCATION irpStackL = IoGetCurrentIrpStackLocation(pirp);//获取应用层传来的参数;
	int* 缓冲区 = (int*)pirp->AssociatedIrp.SystemBuffer;//和IRP有关的系统缓冲区
	if (缓冲区)
	{
		int*p = (int*)缓冲区;
		int 结果 = p[0] + p[1] + p[2];
		
		KdPrint(("yjx:离开 IRP_IO_读写测试 (%d, %d, %d) 结果 = %d", p[0], p[1], p[2], 结果));
		//结果
		*(int*)缓冲区 = 结果;

		pirp->IoStatus.Status = STATUS_SUCCESS;
		pirp->IoStatus.Information = sizeof(int);//返回给DeviceIoControl中的倒数第二个参数lpBytesReturned
		IoCompleteRequest(pirp, IO_NO_INCREMENT);//调用方已完成所有I/O请求处理操作,并且不增加优先级
		

		

	}
	irpStackL;
}

在这里插入图片描述

2.然后在 IRP_CALL函数里直接调用,这里为了不影响上一节课的写入功能,使用了一个开关,可以根据控制码分别处理读数据和写数据功能。代码如下:

代码如下(示例):

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;
	}
	}
	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.虚拟机调试结果

在这里插入图片描述

总结

以上就是64位驱动开发之R3与R0通信交换数据,读写数据测试的全部代码了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

a756598009

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

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

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

打赏作者

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

抵扣说明:

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

余额充值