驱动开发之 设备读写方式:Neither方式

设备读写的第三种方式是Neither方式,在PDevObj中不设置Flags.这种方式很少被用到。

1.在Neither方式中,派遣函数直接读写应用程序提供的缓冲区地址。你很可能看到有人这样说过:决不(或几乎从不)直接引用用户模式的内存地址。因为缓冲区内存是用户模式的内存地址,驱动程序如果直接引用这段内存是十分危险的。原因是windows操作系统是多任务的,它可能随时切换到别的进程。如果驱动程序访问这段内存时操作系统已经切换到其他进程,那么驱动程序访问的内存地址必定是错误的,系统会毫不留情的出现死亡蓝屏(BSOD blue screen of death)。

这种方式只有驱动程序和应用程序运行在相同的线程上下文时,才能被使用。所以呢,驱动程序在使用用户模式地址前一定要检测这段内存是否可读或可写。这就需要用到ProbeForRead函数和ProbeForWrite函数。

VOID 
  ProbeForRead(
    IN CONST VOID  *Address,
    IN SIZE_T  Length,
    IN ULONG  Alignment
    );

VOID 
  ProbeForWrite(
    IN CONST VOID  *Address,
    IN SIZE_T  Length,
    IN ULONG  Alignment
    );

ProbeForRead函数和ProbeForWrite函数与try_except 块配合来检验内存是否可读写。

在派遣函数中通过IRP的pIrp->UserBuffer字段得到用户模式提供的缓冲区的内存地址。

stack_>Parameters.Read.Length字段得到读取的字节数。

下面是IRP_MJ_READ的派遣函数:

NTSTATUS DispatchRead(IN PDEVICE_OBJECT pDevObj,IN PIRP pIrp) 
{
	KdPrint(("Enter DispatchRead\n"));

	PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
	NTSTATUS status = STATUS_SUCCESS;

	//得到当前堆栈
	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);
	//得到读的长度
	ULONG ulReadLength = stack->Parameters.Read.Length;
	//得到读的偏移量
	ULONG ulReadOffset = (ULONG)stack->Parameters.Read.ByteOffset.QuadPart;
	//得到用户模式地址
	PVOID user_address = pIrp->UserBuffer;

	KdPrint(("user_address:0X%0X\n",user_address));

	__try
	{
		KdPrint(("Enter __try block\n"));
		//判断空指针是否可写,显然会导致异常
		ProbeForWrite(user_address,ulReadLength,4);

		memset(user_address,0xAA,ulReadLength);

		//由于在上面引发异常,所以以后语句不会被执行!
		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.Status = status;
	pIrp->IoStatus.Information = ulReadLength;	// bytes xfered
	IoCompleteRequest( pIrp, IO_NO_INCREMENT );
	KdPrint(("Leave DispatchRead\n"));

	return status;
}

另外两种设备读取方式

缓冲区方式:http://blog.csdn.net/liyun123gx/article/details/38042125

直接读取方式:http://blog.csdn.net/liyun123gx/article/details/38043849




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值