reactos操作系统实现(132)

前端之家收集整理的这篇文章主要介绍了reactos操作系统实现(132)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

VfatReadFileData函数主要用来从磁盘上读取文件数据,具体实现代码如下:

#001 static NTSTATUS

#002 VfatReadFileData (PVFAT_IRP_CONTEXT IrpContext,

#003 ULONG Length,

#004 LARGE_INTEGER ReadOffset,

#005 PULONG LengthRead)

#006 /*

#007 * FUNCTION: Reads data from a file

#008 */

#009 {

#010 ULONG CurrentCluster;

#011 ULONG FirstCluster;

#012 ULONG StartCluster;

#013 ULONG ClusterCount;

#014 LARGE_INTEGER StartOffset;

#015 PDEVICE_EXTENSION DeviceExt;

#016 BOOLEAN First = TRUE;

#017 PVFATFCB Fcb;

#018 PVFATCCB Ccb;

#019 NTSTATUS Status;

#020 ULONG BytesDone;

#021 ULONG BytesPerSector;

#022 ULONG BytesPerCluster;

#023 ULONG LastCluster;

#024 ULONG LastOffset;

#025

#026 /* PRECONDITION */

#027 ASSERT(IrpContext);

获取扩展设备。

#028 DeviceExt = IrpContext->DeviceExt;

#029 ASSERT(DeviceExt);

#030 ASSERT(DeviceExt->FatInfo.BytesPerCluster);

#031 ASSERT(IrpContext->FileObject);

#032 ASSERT(IrpContext->FileObject->FsContext2 != NULL);

#033

#034 DPRINT("VfatReadFileData(DeviceExt %p,FileObject %p,"

#035 "Length %d,ReadOffset 0x%I64x)/n",DeviceExt,

#036 IrpContext->FileObject,Length,ReadOffset.QuadPart);

#037

#038 *LengthRead = 0;

#039

文件系统控制块。

#040 Ccb = (PVFATCCB)IrpContext->FileObject->FsContext2;

获取文件控制块。

#041 Fcb = IrpContext->FileObject->FsContext;

每个扇区有多少字节。

#042 BytesPerSector = DeviceExt->FatInfo.BytesPerSector;

每一簇有多少字节。

#043 BytesPerCluster = DeviceExt->FatInfo.BytesPerCluster;

#044

#045 ASSERT(ReadOffset.QuadPart + Length <= ROUND_UP(Fcb->RFCB.FileSize.QuadPart,BytesPerSector));

#046 ASSERT(ReadOffset.u.LowPart % BytesPerSector == 0);

#047 ASSERT(Length % BytesPerSector == 0);

#048

是否读取FAT

#049 /* Is this a read of the FAT? */

#050 if (Fcb->Flags & FCB_IS_FAT)

#051 {

计算读取偏移位置,主要添加FAT的开始位置。。

#052 ReadOffset.QuadPart += DeviceExt->FatInfo.FATStart * BytesPerSector;

创建IRP调用底层磁盘驱动程序。

#053 Status = VfatReadDiskPartial(IrpContext,&ReadOffset,TRUE);

#054

如果读取成功,返回相应的长度数据。

#055 if (NT_SUCCESS(Status))

#056 {

#057 *LengthRead = Length;

#058 }

#059 else

#060 {

#061 DPRINT1("FAT reading Failed,Status %x/n",Status);

#062 }

#063 return Status;

#064 }

是否读取卷数据,这样不需要添加FAT的偏移位置。

#065 /* Is this a read of the Volume ? */

#066 if (Fcb->Flags & FCB_IS_VOLUME)

#067 {

#068 Status = VfatReadDiskPartial(IrpContext,TRUE);

#069 if (NT_SUCCESS(Status))

#070 {

#071 *LengthRead = Length;

#072 }

#073 else

#074 {

#075 DPRINT1("Volume reading Failed,Status);

#076 }

#077 return Status;

#078 }

#079

下面读取文件中数据。

#080 /*

#081 * Find the first cluster

#082 */

找到FAT的入口第一簇。

#083 FirstCluster = CurrentCluster =

#084 vfatDirEntryGetFirstCluster (DeviceExt,&Fcb->entry);

#085

如果是第一簇,在FAT12/FAT16需要做特别的处理。

#086 if (FirstCluster == 1)

#087 {

#088 // Directory of FAT12/16 needs a special handling

#089 if (ReadOffset.u.LowPart + Length > DeviceExt->FatInfo.rootDirectorySectors * BytesPerSector)

#090 {

#091 Length = DeviceExt->FatInfo.rootDirectorySectors * BytesPerSector - ReadOffset.u.LowPart;

#092 }

#093 ReadOffset.u.LowPart += DeviceExt->FatInfo.rootStart * BytesPerSector;

#094

#095 // Fire up the read command

#096

#097 Status = VfatReadDiskPartial (IrpContext,TRUE);

#098 if (NT_SUCCESS(Status))

#099 {

#100 *LengthRead = Length;

#101 }

#102 return Status;

#103 }

#104

文件控制块里获取最后一次读取的簇数和最后偏移位置。

#105 ExAcquireFastMutex(&Fcb->LastMutex);

#106 LastCluster = Fcb->LastCluster;

#107 LastOffset = Fcb->LastOffset;

#108 ExReleaseFastMutex(&Fcb->LastMutex);

#109

#110 /*

#111 * Find the cluster to start the read from

#112 */

查找开始读取数据的簇开始位置。

#113 if (LastCluster > 0 && ReadOffset.u.LowPart >= LastOffset)

#114 {

#115 Status = OffsetToCluster(DeviceExt,LastCluster,

#116 ROUND_DOWN(ReadOffset.u.LowPart,BytesPerCluster) -

#117 LastOffset,

#118 &CurrentCluster,FALSE);

#119 #ifdef DEBUG_VERIFY_OFFSET_CACHING

#120 /* DEBUG VERIFICATION */

#121 {

#122 ULONG CorrectCluster;

#123 OffsetToCluster(DeviceExt,FirstCluster,

#124 ROUND_DOWN(ReadOffset.u.LowPart,BytesPerCluster),

#125 &CorrectCluster,FALSE);

#126 if (CorrectCluster != CurrentCluster)

#127 KeBugCheck(FAT_FILE_SYSTEM);

#128 }

#129 #endif

#130 }

#131 else

#132 {

#133 Status = OffsetToCluster(DeviceExt,

#134 ROUND_DOWN(ReadOffset.u.LowPart,

#135 &CurrentCluster,FALSE);

#136 }

#137 if (!NT_SUCCESS(Status))

#138 {

#139 return(Status);

#140 }

#141

更新最后一次读取的簇位置。

#142 ExAcquireFastMutex(&Fcb->LastMutex);

#143 Fcb->LastCluster = CurrentCluster;

#144 Fcb->LastOffset = ROUND_DOWN (ReadOffset.u.LowPart,BytesPerCluster);

#145 ExReleaseFastMutex(&Fcb->LastMutex);

#146

添加IRP的引用计数。

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

#148 IrpContext->RefCount = 1;

#149

找到合适的开始簇位置。

#150 while (Length > 0 && CurrentCluster != 0xffffffff)

#151 {

#152 StartCluster = CurrentCluster;

#153 StartOffset.QuadPart = ClusterToSector(DeviceExt,StartCluster) * BytesPerSector;

#154 BytesDone = 0;

#155 ClusterCount = 0;

#156

#157 do

#158 {

#159 ClusterCount++;

#160 if (First)

#161 {

#162 BytesDone = min (Length,BytesPerCluster - (ReadOffset.u.LowPart % BytesPerCluster));

#163 StartOffset.QuadPart += ReadOffset.u.LowPart % BytesPerCluster;

#164 First = FALSE;

#165 }

#166 else

#167 {

#168 if (Length - BytesDone > BytesPerCluster)

#169 {

#170 BytesDone += BytesPerCluster;

#171 }

#172 else

#173 {

#174 BytesDone = Length;

#175 }

#176 }

#177 Status = NextCluster(DeviceExt,&CurrentCluster,FALSE);

#178 }

#179 while (StartCluster + ClusterCount == CurrentCluster && NT_SUCCESS(Status) && Length > BytesDone);

#180 DPRINT("start %08x,next %08x,count %d/n",

#181 StartCluster,CurrentCluster,ClusterCount);

#182

#183 ExAcquireFastMutex(&Fcb->LastMutex);

#184 Fcb->LastCluster = StartCluster + (ClusterCount - 1);

#185 Fcb->LastOffset = ROUND_DOWN(ReadOffset.u.LowPart,BytesPerCluster) + (ClusterCount - 1) * BytesPerCluster;

#186 ExReleaseFastMutex(&Fcb->LastMutex);

#187

#188 // Fire up the read command

#189 Status = VfatReadDiskPartial (IrpContext,&StartOffset,BytesDone,*LengthRead,FALSE);

#190 if (!NT_SUCCESS(Status) && Status != STATUS_PENDING)

#191 {

#192 break;

#193 }

#194 *LengthRead += BytesDone;

#195 Length -= BytesDone;

#196 ReadOffset.u.LowPart += BytesDone;

#197 }

如果这个IRP还有在其它地方有引用,说明读取还在阻塞状态。

#198 if (0 != InterlockedDecrement((PLONG)&IrpContext->RefCount))

#199 {

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

#201 }

#202 if (NT_SUCCESS(Status) || Status == STATUS_PENDING)

#203 {

#204 if (Length > 0)

#205 {

#206 Status = STATUS_UNSUCCESSFUL;

#207 }

#208 else

#209 {

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

#211 }

#212 }

#213 return Status;

#214}

猜你在找的React相关文章