将IRP分解成多个IRP

来源:互联网 发布:库里2015 2016数据 编辑:程序博客网 时间:2024/05/17 08:29

将IRP分解成多个IRP



将IRP分解成多个IRP

#pragma PAGEDCODE
NTSTATUS HelloDDKRead(IN PDEVICE_OBJECT pDevObj,
        IN PIRP pIrp)
{
 KdPrint(("DriverA:Enter AHelloDDKRead\n"));
 NTSTATUS status = STATUS_SUCCESS;

 PIO_STACK_LOCATION stack =IoGetCurrentIrpStackLocation(pIrp);

 ULONG totalLength;
 PVOID virtualAddress;
 if (!pIrp->MdlAddress)
 {
  status =STATUS_UNSUCCESSFUL;
  totalLength = 0;
  goto HelloDDKRead_EXIT;
 }
 
 virtualAddress =MmGetMdlVirtualAddress(pIrp->MdlAddress);
 totalLength =MmGetMdlByteCount(pIrp->MdlAddress);

 RtlFillMemory(virtualAddress,totalLength,0xFF);

 KdPrint(("DriverA:virtualAddress:%x\n",virtualAddress));
 KdPrint(("DriverA:totalLength:%d\n",totalLength));

HelloDDKRead_EXIT:
 // 完成IRP
 pIrp->IoStatus.Status =status;
 pIrp->IoStatus.Information =totalLength; //bytes xfered
 IoCompleteRequest( pIrp, IO_NO_INCREMENT );
 KdPrint(("DriverA:Leave AHelloDDKRead\n"));
 return status;
}
将IRP分解成多个IRP

将IRP分解成多个IRP
#pragma PAGEDCODE
NTSTATUS HelloDDKRead(IN PDEVICE_OBJECT pDevObj,
        IN PIRP pIrp)
{
 KdPrint(("DriverB:Enter BHelloDDKRead\n"));
 NTSTATUS status = STATUS_SUCCESS;

 PDEVICE_EXTENSION pDevExt =(PDEVICE_EXTENSION)
  pDevObj->DeviceExtension;

 PIO_STACK_LOCATION stack =IoGetCurrentIrpStackLocation(pIrp);
 
 ULONG totalLength;
 ULONG stageLength;
 PMDL mdl;
 PVOID virtualAddress;
 PMYDRIVER_RW_CONTEXT rwContext = NULL;
 PIO_STACK_LOCATION nextStack;

 if (!pIrp->MdlAddress)
 {
  status =STATUS_UNSUCCESSFUL;
  totalLength = 0;
  goto HelloDDKRead_EXIT;
 }

 //获取MDL的虚拟地址
 virtualAddress =MmGetMdlVirtualAddress(pIrp->MdlAddress);
 //获取MDL的长度
 totalLength =MmGetMdlByteCount(pIrp->MdlAddress);

 KdPrint(("DriverB:(pIrp->MdlAddress)MmGetMdlVirtualAddress:X\n",MmGetMdlVirtualAddress(pIrp->MdlAddress)));
 KdPrint(("DriverB:(pIrp->MdlAddress)MmGetMdlByteCount:%d\n",MmGetMdlByteCount(pIrp->MdlAddress)));

 //将总的传输,分成几个阶段,这里设定每次阶段的长度
   if(totalLength > MAX_PACKAGE_SIZE)
 {
       stageLength = MAX_PACKAGE_SIZE;
    }else
 {
       stageLength = totalLength;
    }

 //创建新的MDL
    mdl =IoAllocateMdl((PVOID) virtualAddress,
                       totalLength,
                       FALSE,
                       FALSE,
                       NULL);

 KdPrint(("DriverB:(newmdl)MmGetMdlVirtualAddress:X\n",MmGetMdlVirtualAddress(mdl)));
 KdPrint(("DriverB:(newmdl)MmGetMdlByteCount:%d\n",MmGetMdlByteCount(mdl)));

    if(mdl ==NULL)
 {
  KdPrint(("DriverB:Failed toalloc mem for mdl\n"));
  status =STATUS_INSUFFICIENT_RESOURCES;
  goto HelloDDKRead_EXIT;
    }

 //将IRP的MDL做重新映射
   IoBuildPartialMdl(pIrp->MdlAddress,
                     mdl,
                     (PVOID) virtualAddress,
                     stageLength);
 KdPrint(("DriverB:(newmdl)MmGetMdlVirtualAddress:X\n",MmGetMdlVirtualAddress(mdl)));
 KdPrint(("DriverB:(newmdl)MmGetMdlByteCount:%d\n",MmGetMdlByteCount(mdl)));

 rwContext = (PMYDRIVER_RW_CONTEXT)
               ExAllocatePool(NonPagedPool,sizeof(MYDRIVER_RW_CONTEXT));

   rwContext->NewMdl   =mdl;
 rwContext->PreviousMdl  =pIrp->MdlAddress;
   rwContext->Length   =totalLength - stageLength;//还剩下多少没读取
   rwContext->Numxfer   =0;      //读了多少字节
   rwContext->VirtualAddress =((ULONG_PTR)virtualAddress + stageLength);//下一阶段开始读取的地址
 rwContext->DeviceExtension =pDevExt;

 //拷贝到底层堆栈
 IoCopyCurrentIrpStackLocationToNext(pIrp);

 nextStack =IoGetNextIrpStackLocation(pIrp);
 //根据底层驱动的实现,底层驱动有可能读取这个数值,也有可能读取mdl的length。
 nextStack->Parameters.Read.Length= stageLength;

 pIrp->MdlAddress = mdl;
 
 //设定完成例程
   IoSetCompletionRoutine(pIrp,
                          (PIO_COMPLETION_ROUTINE)HelloDDKReadCompletion,
                          rwContext,
                          TRUE,
                          TRUE,
                          TRUE);

   IoCallDriver(pDevExt->TargetDevice,pIrp);
 
 pIrp->MdlAddress =rwContext->PreviousMdl;
 IoFreeMdl(rwContext->NewMdl);

HelloDDKRead_EXIT:
 // 完成IRP
 pIrp->IoStatus.Status =status;
 pIrp->IoStatus.Information =totalLength; // bytes xfered
 IoCompleteRequest( pIrp, IO_NO_INCREMENT );
 KdPrint(("DriverB:Leave BHelloDDKRead\n"));
 return status;
}
将IRP分解成多个IRP
const int MAX_PACKAGE_SIZE=1024;

#pragma PAGEDCODE
NTSTATUS
HelloDDKReadCompletion(
    INPDEVICE_OBJECT DeviceObject,
    INPIRP          Irp,
    INPVOID         Context
    )
{
 KdPrint(("DriverB:Enter BHelloDDKReadCompletion\n"));

 PMYDRIVER_RW_CONTEXT rwContext =(PMYDRIVER_RW_CONTEXT) Context;
    NTSTATUSntStatus = Irp->IoStatus.Status;

 ULONG stageLength;

 if(rwContext&& NT_SUCCESS(ntStatus))
 {
  //已经传送了多少字节
  rwContext->Numxfer+= Irp->IoStatus.Information;

      if(rwContext->Length)
    {
    //设定下一阶段读取字节数
           if(rwContext->Length >MAX_PACKAGE_SIZE)
   {
    stageLength= MAX_PACKAGE_SIZE;
           }
           else
   {
               stageLength = rwContext->Length;
           }
   //重新利用MDL
           MmPrepareMdlForReuse(rwContext->NewMdl);

           IoBuildPartialMdl(Irp->MdlAddress,
                             rwContext->NewMdl,
                             (PVOID) rwContext->VirtualAddress,
                             stageLength);
       
           rwContext->VirtualAddress += stageLength;
           rwContext->Length -= stageLength;

   IoCopyCurrentIrpStackLocationToNext(Irp);
           PIO_STACK_LOCATION nextStack = IoGetNextIrpStackLocation(Irp);

   nextStack->Parameters.Read.Length= stageLength;

           IoSetCompletionRoutine(Irp,
                                  HelloDDKReadCompletion,
                                  rwContext,
                                  TRUE,
                                  TRUE,
                                  TRUE);

           IoCallDriver(rwContext->DeviceExtension->TargetDevice,
                        Irp);

           return STATUS_MORE_PROCESSING_REQUIRED;
       }
       else
  {
   //最后一次传输
           Irp->IoStatus.Information =rwContext->Numxfer;
       }
 }

 KdPrint(("DriverB:Leave BHelloDDKReadCompletion\n"));
 returnSTATUS_MORE_PROCESSING_REQUIRED; 
}

将IRP分解成多个IRP

将IRP分解成多个IRP

将IRP分解成多个IRP

原创粉丝点击