DeviceIoControl_苹果无法与此应用程序通信

DeviceIoControl_苹果无法与此应用程序通信驱动开发之用DeviceIoControl实现应用程序与驱动程序通信1.readfile和writefile可以实现应用程序与驱动程序通信,另外一个Win32API是DeviceIoControl。应用程序自定义一中IO控制码,然后调用DeviceIoControl函数,IO管理器会产生一个MajorFunction为IRP_MJ_DEVICE_CONTROL,MinorFun

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

驱动开发之 用DeviceIoControl实现应用程序与驱动程序通信

1.

readfile和writefile可以实现应用程序与驱动程序通信,另外一个Win32 API 是DeviceIoControl。

应用程序自定义一中IO控制码,然后调用DeviceIoControl函数,IO管理器会产生一个MajorFunction 为IRP_MJ_DEVICE_CONTROL,MinorFunction 为自己定义的控制码的IRP,系统就调用相应的处理IRP_MJ_DEVICE_CONTROL的派遣函数,你在派遣函数中判断MinorFunction ,是自定义的控制码你就进行相应的处理。

2.

首先介绍一下DeviceIoControl函数

BOOL WINAPI DeviceIoControl(
  _In_         HANDLE hDevice,      //已经打开的设备句柄
  _In_         DWORD dwIoControlCode,//自定义的控制码,稍后介绍怎么定义
  _In_opt_     LPVOID lpInBuffer,    //输入缓冲区
  _In_         DWORD nInBufferSize,  //输入缓冲区的大小
  _Out_opt_    LPVOID lpOutBuffer,   //输出缓冲区
  _In_         DWORD nOutBufferSize, //输出缓冲区的大小
  _Out_opt_    LPDWORD lpBytesReturned, //实际返回的字节数,对应驱动程序中pIrp->IoStatus.Information。
  _Inout_opt_  LPOVERLAPPED lpOverlapped //重叠操作结构指针。同步设为NULL,DeviceIoControl将进行阻塞调用;否则,应在编程时按异步操作设计
);

例如:

UCHAR InputBuffer[10];
UCHAR OutputBuffer[10];

//将输入缓冲区全部置成0XBB
memset(InputBuffer,0xBB,10);
DWORD dwOutput;
//输入缓冲区作为输入,输出缓冲区作为输出
BOOL bRet = DeviceIoControl(hDevice, IOCTL_TEST, InputBuffer, 10, &OutputBuffer, 10, &dwOutput, (LPOVERLAPPED)NULL);


3.

定义IO控制码

#define IOCTL_Device_Function CTL_CODE(DeviceType, Function, Method, Access)

IOCTL_Device_Function:生成的IRP的MinorFunction 

DeviceType:设备对象的类型。设备类型可参考:http://blog.csdn.net/liyun123gx/article/details/38058965

Function :自定义的IO控制码。自己定义时取0x800到0xFFF,因为0x0到0x7FF是微软保留的。

Method :数据的操作模式。

              METHOD_BUFFERED:缓冲区模式

              METHOD_IN_DIRECT:直接写模式

              METHOD_OUT_DIRECT:直接读模式

              METHOD_NEITHER :Neither模式

Access:访问权限,可取值有:

            FILE_ANY_ACCESS:表明用户拥有所有的权限

            FILE_READ_DATA:表明权限为只读

            FILE_WRITE_DATA:表明权限为可写

            也可以 FILE_WRITE_DATA | FILE_READ_DATA:表明权限为可读可写,但还没达到FILE_ANY_ACCESS的权限。

例如:#define IOCTL_TEST     CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)

4.下面介绍不同的数据操作模式

(1).METHOD_BUFFERED:缓冲区模式

用户提供的输入缓冲区的内容被复制到IRP中的pIrp->AssociatedIrp.SystemBuffer内存地址,复制的长度是DeviceIoControl指定的输入字节数。

驱动程序输出数据时,还可以向pIrp->AssociatedIrp.SystemBuffer中写入,操作系统会将此地址的数据复制到DeviceIoControl的输出缓冲区。

复制的字节数通过设置pIrp->IoStatus.Information来指定。

派遣函数中通过下面代码得到输入缓冲区输出缓冲的大小以及IOCTL

//得到当前堆栈
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);
//得到输入缓冲区大小
ULONG cbin = stack->Parameters.DeviceIoControl.InputBufferLength;
//得到输出缓冲区大小
ULONG cbout = stack->Parameters.DeviceIoControl.OutputBufferLength;
//得到IOCTL码
ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;

通过操作pIrp->AssociatedIrp.SystemBuffer来进行数据的输入输出

UCHAR* InputBuffer = (UCHAR*)pIrp->AssociatedIrp.SystemBuffer;
for (ULONG i=0;i<cbin;i++)
{
	KdPrint(("%X\n",InputBuffer[i]));
}

//操作输出缓冲区,输出缓冲区和输入缓冲区是一个缓冲区
UCHAR* OutputBuffer = (UCHAR*)pIrp->AssociatedIrp.SystemBuffer;
memset(OutputBuffer,0xAA,cbout);
//设置实际操作输出缓冲区长度
 pIrp->IoStatus.Information  = 	cbout;		

(2) METHOD_IN_DIRECT与METHOD_OUT_DIRECT  直接内存模式

与缓冲模式相同,用户提供的输入缓冲区的内容被复制到IRP中的pIrp->AssociatedIrp.SystemBuffer内存地址,复制的长度是DeviceIoControl指定的输入字节数。

直接内存模式中,操作系统会将DeviceIoControl指定的输出缓冲区锁定,然后在内核模式地址下重新映射一段地址。

派遣函数中IRP中的pIrp->MdlAddress记录DeviceIoControl指定的输出缓冲区。派遣函数应该使用MmGetSystemAddressForMdlSafe将这段内存映射到内核模式下的内存地址。

得到输入输出缓冲区的大小以及IOCTL的方式与缓冲区模式相同。

另外需要注意CTL_CODE设置的权限问题,若以只读方式打开设备,METHOD_IN_DIRECT的IOCTL操作会失败。

派遣函数中处理直接内存模式:

//显示输入缓冲区数据
UCHAR* InputBuffer = (UCHAR*)pIrp->AssociatedIrp.SystemBuffer;
for (ULONG i=0;i<cbin;i++)
{
	KdPrint(("%X\n",InputBuffer[i]));
}
//pIrp->MdlAddress为DeviceIoControl输出缓冲区地址相同
KdPrint(("User Address:0X%08X\n",MmGetMdlVirtualAddress(pIrp->MdlAddress)));
UCHAR* OutputBuffer = (UCHAR*)MmGetSystemAddressForMdlSafe(pIrp->MdlAddress,NormalPagePriority);
//InputBuffer被映射到内核模式下的内存地址,必定在0X80000000-0XFFFFFFFF之间
memset(OutputBuffer,0xAA,cbout);


(3)METHOD_NEITHER :Neither模式

因为此模式直接访问用户模式地址,这是很危险的,所以此模式很少被用到。

使用用户模式地址必须保证调用DeviceIoControl 的线程与派遣函数运行在同一个线程上下文中。

派遣函数得到输入缓冲区的方式与前两种不同,此模式是通过IO堆栈的stack->Parameters.DeviceIoControl.Type3InputBuffer;得到输入缓冲区。

驱动通过pIrp->UserBuffer得到输出缓冲区。

得到输入输出缓冲区的长度与IOCTL的方式与前两种相同。

由于驱动程序的派遣函数不能保证传递进来的用户地址是合法地址,所以要对传入的用户模式地址进行可读写判断。这就需要ProbeForRead函数和ProbeForWrite函数与_try _execpt 结合使用。

下面是驱动派遣函数中Neither模式

//显示输入缓冲区数据
UCHAR* UserInputBuffer = (UCHAR*)stack->Parameters.DeviceIoControl.Type3InputBuffer;
KdPrint(("UserInputBuffer:0X%0X\n",UserInputBuffer));

//得到用户模式地址
PVOID UserOutputBuffer = pIrp->UserBuffer;
KdPrint(("UserOutputBuffer:0X%0X\n",UserOutputBuffer));

__try
{
	KdPrint(("Enter __try block\n"));

	//判断指针是否可读
	ProbeForRead(UserInputBuffer,cbin,4);
	//显示输入缓冲区内容
	for (ULONG i=0;i<cbin;i++)
	{
		KdPrint(("%X\n",UserInputBuffer[i]));
	}

	//判断指针是否可写
	ProbeForWrite(UserOutputBuffer,cbout,4);

	//操作输出缓冲区
	memset(UserOutputBuffer,0xAA,cbout);

	//如果在上面引发异常,所以以后语句不会被执行!
	pIrp->IoStatus.Information = cbout;

	KdPrint(("Leave __try block\n"));
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
	KdPrint(("Catch the exception\n"));
	KdPrint(("The program will keep going\n"));
	status = STATUS_UNSUCCESSFUL;
}

pIrp->IoStatus.Information = cbout;

注:有不妥之处望指正。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/196522.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • vim 设置搜索高亮_vim取消搜索后高亮持续

    vim 设置搜索高亮_vim取消搜索后高亮持续vim搜索设置高亮linuxvim打开文档搜索字符串时,设置被搜索到字符串高亮显示。有两种方法:1、临时设置:vim打开文档–>命令行形式输入sethlsearch。缺点:关闭文档后,下次打开,又需要重新设置一遍。2、永久设置(推荐):在~/.vimrc中配制vim~/.vimrc在文件中加上sethlsearch 然后保存退出便可。

    2022年9月24日
    4
  • 安装并配置SQL Server 2005群集

    安装并配置SQL Server 2005群集

    2021年8月19日
    57
  • 谷歌 analytics.js 部分解密版

    谷歌 analytics.js 部分解密版源:http://www.google-analytics.com/analytics.js(function(){varaa=encodeURIComponent,f=window,ba=setTimeout,n=Math;functionPc(a,b){returna.href=b}functionfa(a,b){returna.name=b}varQc=”repla…

    2022年7月26日
    13
  • 福利 | 这些网站有免费代理IP!「建议收藏」

    福利 | 这些网站有免费代理IP!「建议收藏」闲来无事,为大家整理了一些免费代理IP的网站,比较适用于对ip质量要求不高,时效要求不长的小伙伴,日常经常用的小伙伴赶紧收藏啦!http://www.66ip.cn/index.htmlhttps://seofangfa.com/proxy/https://ip.jiangxianli.com/http://www.xiladaili.com/gaoni/6/http://www.xsdaili.cn/dayProxy/ip/2459.htmlhttp://www.dailii.

    2022年6月16日
    72
  • iocomp-Crack|New Version最新【2021】「建议收藏」

    iocomp-Crack|New Version最新【2021】「建议收藏」使用IocompComponents5.0以上能够助程序员开发出逼真的工控仪表和工控图表,让程序开发不再消耗时间和精力,有了这个控件不仅能节约开发时间,而且还降低了项目风险,最重要的是第三方控件写的程序更专业,工控图表图像更精细。他们用于生成具有专家级外观的仪器控件,并能紧密整合到Microsoft’s.NETFramework之中。您无需辛苦的在属性窗口中寻找该属性,其自定义的属性编辑器提供了简单快速的属性配置方法。Ultra控件包提供了70种专家级控件以及绘图控件包组件非常强大的

    2022年7月25日
    12
  • idea最新激活码2022【2021免费激活】

    (idea最新激活码2022)最近有小伙伴私信我,问我这边有没有免费的intellijIdea的激活码,然后我将全栈君台教程分享给他了。激活成功之后他一直表示感谢,哈哈~https://javaforall.net/100143.htmlIntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,上面是详细链接哦~0HKL…

    2022年3月31日
    54

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号