其他缓冲区方式模拟文件操作
还有一种操作内存的方式, 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/x-agan/comments.php on line 66
您必须登录 才能进行评论。