zl程序教程

您现在的位置是:首页 >  系统

当前栏目

reactos操作系统实现(133)

操作系统 实现 reactos
2023-09-14 09:10:38 时间

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

#001  NTSTATUS

#002  VfatReadDiskPartial (IN PVFAT_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_LOCATION StackPtr;

#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 ("Building asynchronous 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("IoAllocateIrp failed/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        return STATUS_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 IO Driver... 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  }