忆杰的博客

忆杰的博客

其他缓冲区方式模拟文件操作


还有一种操作内存的方式, MicroSoft没有给其起名字, 然后Windows驱动编程详解上面就叫这种方式为其他方式, 其实什么方式没有什么所谓了.. 不过据说这种方式用的是非常少了. 一般需要快的时候使用MDL就已经很好了. 除非那种内核和用户态大量进行交互的程序才会想着用这个款式吧,貌似文件系统之类的驱动应该搞这个比较合适. 反正这个也只有学习的时候使用下了. 平时应该是用不到的.
 

 
一直说用户态的地址直接传递进内核里面是会出问题的, 我至今没有搞明白, 不是说驱动的分发函数会一直在发起调用的进程空间运行么? 怎么会无缘无故的切换了呢?哪怕是进程调度, 回头再运行这个内核代码, 不是说也可以保证在发起调用的内存地址空间运行么? 这个问题一直没有搞明白..
 
 
其他的话款式和上两篇是一样的, 就是模拟Windows那个文件读写的款式. 没有什么好说的, 直接上代码比较合适, 这里是内核态的代码, 用户层和前两篇是一样的, 就不列出了!

 

        http://www.joenchen.com/JoenTools/OtherIo.rar

/*
	Windows内核下模拟文件的读写操作, IRP的处理(直接使用3环地址) 0环代码
	编译方法参见makefile. TAB = 8
*/
#include <ntddk.h>

#define  DEVICE_NAME	L"\\Device\\DevJoenDevice"
#define  SYS_LINK_NAME	L"\\??\\SysLinkJoenDevice"
#define  MAX_LENGTH	1024

typedef struct tagDeviceExt {
	ULONG		dwFileCurrentLength;
	CHAR*		pBuffer;
	PDEVICE_OBJECT	pDeviceObj;
	UNICODE_STRING	USzDeviceName;
	UNICODE_STRING	USzSysLinkName;
}DEVICEEXT, *PDEVICEEXT;

//===========================================================================
//	驱动卸载例程
VOID DriverUnLoad( PDRIVER_OBJECT pDriverObj ) {
	PDEVICEEXT pDeviceExt;
	PDEVICE_OBJECT pNextDeviceObj;

	pNextDeviceObj = pDriverObj->DeviceObject;

	while ( pNextDeviceObj != NULL ) {
		pDeviceExt = pNextDeviceObj->DeviceExtension;

		IoDeleteDevice( pDeviceExt->pDeviceObj );
		IoDeleteSymbolicLink( &pDeviceExt->USzSysLinkName );
		pNextDeviceObj = pNextDeviceObj->NextDevice;

		KdPrint( ( "删除%wZ设备成功!\n", &pDeviceExt->USzSysLinkName ) );
	}
}

//===========================================================================
//	所有我们不关心的IRP处理, 直接放过
NTSTATUS DispatchRoutin( PDEVICE_OBJECT pDeviceObj, PIRP pIrp ) {

	pIrp->IoStatus.Information = 0;
	pIrp->IoStatus.Status = STATUS_SUCCESS;
	IoCompleteRequest( pIrp, IO_NO_INCREMENT );
	return STATUS_SUCCESS;
}

//===========================================================================
//	读请求过滤
NTSTATUS DispatchRead( PDEVICE_OBJECT pDeviceObj, PIRP pIrp ) {
	ULONG ulReadLen;
	ULONG ulReadOffset;
	PVOID pAddress;
	PDEVICEEXT pDeviceExt;
	NTSTATUS Status;
	PIO_STACK_LOCATION Stack;

	Stack = IoGetCurrentIrpStackLocation( pIrp );

	//得到读取的长度和偏移量, 和地址
	ulReadLen = Stack->Parameters.Read.Length;
	ulReadOffset = ( ULONG )Stack->Parameters.Read.ByteOffset.QuadPart;
	pAddress = pIrp->UserBuffer;

	KdPrint( ( "用户态传递的地址是%p\n", pAddress ) );

	do {
		//如果欲读取的长度大于最大长度
		if ( ulReadLen + ulReadOffset > MAX_LENGTH ) {
			Status = STATUS_FILE_INVALID;
			ulReadLen = 0;
			break;
		}

		__try {

			pDeviceExt = pDeviceObj->DeviceExtension;

			//测试用户地址是否可写, 如果不可写会异常
			ProbeForWrite( pAddress, ulReadLen, 4 );

			//copy数据到用户层
			RtlCopyMemory( pAddress, pDeviceExt->pBuffer + ulReadOffset, ulReadLen );
			Status = STATUS_SUCCESS;

		}__except( EXCEPTION_EXECUTE_HANDLER ) {
			//如果发生异常. 说明不可写
			Status = STATUS_UNSUCCESSFUL;
			ulReadLen = 0;
			KdPrint( ( "用户层传递的地址不可写而发生异常!\n" ) );
		}
	} while ( FALSE );

	pIrp->IoStatus.Information = ulReadLen;

	pIrp->IoStatus.Status = Status;

	IoCompleteRequest( pIrp, IO_NO_INCREMENT );

	KdPrint( ( "读取请求处理完毕!\n" ) );

	return Status;
}

//===========================================================================
//	写请求的过滤
NTSTATUS DispatchWrite( PDEVICE_OBJECT pDeviceObj, PIRP pIrp ) {
	ULONG ulWriteLen;
	ULONG ulWriteOffset;
	PVOID pAddress;
	NTSTATUS Status;
	PDEVICEEXT pDeviceExt;
	PIO_STACK_LOCATION Stack;

	Stack = IoGetCurrentIrpStackLocation( pIrp );

	//得到用户层的缓冲区地址和写入长度与偏移
	ulWriteLen = Stack->Parameters.Write.Length;
	ulWriteOffset = ( ULONG )Stack->Parameters.Write.ByteOffset.QuadPart;
	pAddress = pIrp->UserBuffer;

	KdPrint( ( "用户层地址是%p\n", pAddress ) );

	pDeviceExt = pDeviceObj->DeviceExtension;

	do {
		if ( ulWriteLen + ulWriteOffset > MAX_LENGTH ) {
			ulWriteLen = 0;
			Status = STATUS_UNSUCCESSFUL;
			break;
		}

		__try {

			//测试是否可读
			ProbeForRead( pAddress, ulWriteLen, 4 );

			//Copy到内核缓冲区中
			RtlCopyMemory( pDeviceExt->pBuffer + ulWriteOffset, pAddress, ulWriteLen  );

			if ( ulWriteOffset + ulWriteLen > pDeviceExt->dwFileCurrentLength ) {
				pDeviceExt->dwFileCurrentLength = ulWriteOffset + ulWriteLen;
			}

			Status = STATUS_SUCCESS;

		}__except( EXCEPTION_EXECUTE_HANDLER ) {
			Status = STATUS_UNSUCCESSFUL;
			ulWriteLen = 0;
		}

	} while ( FALSE );

	//完成IRP
	pIrp->IoStatus.Information = ulWriteLen;

	pIrp->IoStatus.Status = Status;

	IoCompleteRequest( pIrp, IO_NO_INCREMENT );

	return Status;
}

//===========================================================================
//	驱动入口函数
NTSTATUS DriverEntry( PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pUSzRegPath ) {
	ULONG i;
	NTSTATUS Status;
	PDEVICEEXT pDeviceExt;
	PDEVICE_OBJECT PDeviceObj;
	UNICODE_STRING USzDeviceName = RTL_CONSTANT_STRING( DEVICE_NAME );
	UNICODE_STRING USzSysLinkName = RTL_CONSTANT_STRING( SYS_LINK_NAME );

	Status = IoCreateDevice( pDriverObj, sizeof( DEVICEEXT ), &USzDeviceName,
	                         FILE_DEVICE_UNKNOWN, 0, 0, &PDeviceObj );

	if ( !NT_SUCCESS( Status ) ) {
		KdPrint( ( "创建设备失败!\n" ) );
		return Status;
	}

	Status = IoCreateSymbolicLink( &USzSysLinkName, &USzDeviceName );

	if ( !NT_SUCCESS( Status ) ) {
		KdPrint( ( "创建符号链接失败!\n" ) );
	}

	//设置设备扩展属性
	pDeviceExt = PDeviceObj->DeviceExtension;

	pDeviceExt->USzDeviceName = USzDeviceName;

	pDeviceExt->USzSysLinkName = USzSysLinkName;

	pDeviceExt->pDeviceObj = PDeviceObj;

	pDeviceExt->pBuffer = ExAllocatePool( PagedPool, MAX_LENGTH );

	pDeviceExt->dwFileCurrentLength = 0;

	//设置分发例程
	for ( i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++ ) {
		pDriverObj->MajorFunction[i] = &DispatchRoutin;
	}

	pDriverObj->DriverUnload = DriverUnLoad;

	pDriverObj->MajorFunction[IRP_MJ_READ] = &DispatchRead;
	pDriverObj->MajorFunction[IRP_MJ_WRITE] = &DispatchWrite;
	return Status;
}

 

 

发表评论


Warning: Undefined variable $user_ID in /www/wwwroot/joenchen.com/wp-content/themes/agan/comments.php on line 66

您必须登录 才能进行评论。