reactos操作系统实现(133)

来源:互联网 发布:linux 启动apache服务 编辑:程序博客网 时间:2024/06/04 19:12

 VfatReadDiskPartial函数主要用来构造一个IRP给底层驱动程序去读取数据返回。具体实现代码如下:

#001  NTSTATUS

#002  VfatReadDiskPartial (INPVFAT_IRP_CONTEXT IrpContext,

#003              IN PLARGE_INTEGER ReadOffset,

#004              IN ULONG ReadLength,

#005              ULONG BufferOffset,

#006              IN BOOLEAN Wait)

#007  {

#008    PIRP Irp;

#009    PIO_STACK_LOCATIONStackPtr;

#010    NTSTATUS Status;

#011    PVOID Buffer;

#012 

#013    DPRINT("VfatReadDiskPartial(IrpContext %p, ReadOffset %I64x, ReadLength %d,BufferOffset %x, Wait %d)/n",

#014       IrpContext,ReadOffset->QuadPart, ReadLength, BufferOffset, Wait);

#015 

#016    DPRINT ("Buildingasynchronous FSD Request.../n");

#017 

 

IRPMDL地址获取内存缓冲区。

#018    Buffer =(PCHAR)MmGetMdlVirtualAddress(IrpContext->Irp->MdlAddress) +BufferOffset;

#019 

 

创建一个新的IRP

#020    Irp =IoAllocateIrp(IrpContext->DeviceExt->StorageDevice->StackSize, TRUE);

#021    if (Irp == NULL)

#022      {

#023        DPRINT("IoAllocateIrpfailed/n");

#024       return(STATUS_UNSUCCESSFUL);

#025      }

#026 

 

设置IRP属性。

#027    Irp->UserIosb = NULL;

#028   Irp->Tail.Overlay.Thread = PsGetCurrentThread();

#029 

#030    StackPtr =IoGetNextIrpStackLocation(Irp);

#031    StackPtr->MajorFunction= IRP_MJ_READ;

#032    StackPtr->MinorFunction= 0;

#033    StackPtr->Flags = 0;

#034    StackPtr->Control = 0;

 

设置访问设备对象。

#035    StackPtr->DeviceObject= IrpContext->DeviceExt->StorageDevice;

#036    StackPtr->FileObject =NULL;

#037   StackPtr->CompletionRoutine = NULL;

#038   StackPtr->Parameters.Read.Length = ReadLength;

#039   StackPtr->Parameters.Read.ByteOffset = *ReadOffset;

#040 

 

创建一个直接内存访问MDL

#041    if (!IoAllocateMdl(Buffer,ReadLength, FALSE, FALSE, Irp))

#042      {

#043       DPRINT("IoAllocateMdl failed/n");

#044        IoFreeIrp(Irp);

#045        returnSTATUS_UNSUCCESSFUL;

#046      }

#047 

#048   IoBuildPartialMdl(IrpContext->Irp->MdlAddress, Irp->MdlAddress,Buffer, ReadLength);

#049 

 

设置I/O完成端口函数。

#050   IoSetCompletionRoutine(Irp,

#051                          VfatReadWritePartialCompletion,

#052              IrpContext,

#053              TRUE,

#054              TRUE,

#055              TRUE);

#056 

#057    if (Wait)

#058      {

#059       KeInitializeEvent(&IrpContext->Event, NotificationEvent, FALSE);

#060       IrpContext->RefCount = 1;

#061      }

#062    else

#063      {

#064       InterlockedIncrement((PLONG)&IrpContext->RefCount);

#065      }

#066 

 

调储存驱动程序来读取文件数据。

#067    DPRINT ("Calling IODriver... with irp %p/n", Irp);

#068    Status = IoCallDriver(IrpContext->DeviceExt->StorageDevice, Irp);

#069 

 

如果读取数据在阻塞状态,就等底层驱动程序完成。

#070    if (Wait && Status== STATUS_PENDING)

#071      {

#072       KeWaitForSingleObject(&IrpContext->Event, Executive, KernelMode,FALSE, NULL);

#073        Status =IrpContext->Irp->IoStatus.Status;

#074      }

#075 

#076    DPRINT("%x/n",Status);

#077    return Status;

#078  }

原创粉丝点击