IRP 续一

贴一下上篇文章创建新设备的代码

#pragma  code_seg("INIT" ) 
void CreateDevice(PDRIVER_OBJECT driver)
{
    ULONG j;
    NTSTATUS statuss;
    UNICODE_STRING StDeviceName = {0};
    UNICODE_STRING StSysLinkName= {0};   
    PDEVICE_EXT pExt=NULL;
    PDEVICE_OBJECT pDeviceObj = NULL; 
    RtlInitUnicodeString(&StDeviceName, L"\\Device\\SmkDevice" ); //设别名称 内核模式下可访问的
    RtlInitUnicodeString(&StSysLinkName, L"\\??\\LinkSmkDevice" ); //符号链接名称 ring3下访问的 其中\\??需改成\\.
    statuss = IoCreateDevice( driver, sizeof(DEVICE_EXT), &StDeviceName,               
        FILE_DEVICE_UNKNOWN, 0, TRUE, &pDeviceObj ); //DEVICE_EXT扩展属性 记录用户自定义数据
    if (!NT_SUCCESS(statuss))
    {
        KdPrint(("create obj faile"));
        return;
    }
    pDeviceObj->Flags|=DO_BUFFERED_IO;//这边以缓冲区方式进行读取
    statuss=IoCreateSymbolicLink(&StSysLinkName,&StDeviceName);
    if (!NT_SUCCESS(statuss))
    {
        IoDeleteDevice( pDeviceObj ); 
        KdPrint(("create Symbolic faile"));
        return;
    }
    pExt=(PDEVICE_EXT)pDeviceObj->DeviceExtension;
    pExt->pDeviceObj=pDeviceObj;
    pExt->StSzDeviceName=StDeviceName;
    pExt->StSzSysLinkName=StSysLinkName;
    
 KdPrint(( "Create obj 执行成功!\n" )); 


}

pDeviceObj->Flags|=DO_BUFFERED_IO;是以缓冲区的方式进行读取,所以在read派遣函数中可直接将数据复制到irp->AssociatedIrp.SystemBuffer,在write中则是

if(buffer==NULL)
   buffer=(PCHAR)irp->AssociatedIrp.SystemBuffer;//缓冲区模式读取

如果是 直接读取 方式pDeviceObj->Flags|=DO_DIRECT_IO 则read write中可用MmGetSystemAddressForMdlSafe(irp->MdlAddress,NormalPagePriority);得到MDL在内核模式下的映射

具体的读代码为

 

#pragma  code_seg( "PAGE" )
NTSTATUS ReadDispatch(PDEVICE_OBJECT pDevice, PIRP irp)
{
PCHAR buffer=NULL;
        ULONG BufferLenth=0;
        ULONG ReadOffset=0;
        PDEVICE_EXT pDExt;
        PIO_STACK_LOCATION pStack = NULL;  

        pDExt=(PDEVICE_EXT)pDevice->DeviceExtension;
        pStack = IoGetCurrentIrpStackLocation( irp );        
        BufferLenth=pStack->Parameters.Read.Length;//获取指定的读取长度
//获取锁定缓冲区的长度
ULONG mdl_len=MmGetMdlByteCount(irp->MdlAddress);
//获取锁定缓冲区的首地址
ULONG mdl_add=MmGetMdlVirtualAddress(irp->MdlAddress);
//获取锁定缓冲区的偏移量
ULONG mdl_offset=MmGetMdlByteOffset(irp->MdlAddress);

//MDL长度应该和读取长度相等

         if (mdl_len!=BufferLenth)        
{ KdPrint((
"Read Size error\r\n")); BufferLenth=0; } else {        PVOID kernel_add=MmGetSystemAddressForMdlSafe(irp->MdlAddress,NormalPagePriority); RtlCopyMemory(kernel_add,pDExt->buffer+ReadOffset,BufferLenth); } irp->IoStatus.Information = BufferLenth; irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest( irp, IO_NO_INCREMENT ); KdPrint(( "Irp_DispatchRoutine 执行完毕" )); return STATUS_SUCCESS; }

 

Write下的代码基本类同

二、其他模式下的读取方式 Flags的设置既不是DO_DIRECT_IO也不是DO_BUFFERED_IO,上一篇中在Write派遣函数中 buffer=(PCHAR)irp->UserBuffer; 这就是其他模式下的缓存区,只需对此缓冲区进行操作即可实现,具体代码此处略。

posted on 2012-04-10 21:52  xmcc  阅读(437)  评论(0编辑  收藏  举报

导航