reactos操作系统实现(131)
VfatRead函数用来读取FAT文件系统里的文件数据,如果缓冲区里有数据就直接从缓冲区里读取,否则就从磁盘上读取。具体实现如下: #001 NTSTATUS #002 VfatRead(PVFAT_IRP_CONTEXT IrpContext) #003 { #004 NTSTATUS Status; #005 PVFATFCB Fcb; #006 ULONG Length = 0; #007 ULONG ReturnedLength = 0; #008 PERESOURCE Resource = NULL; #009 LARGE_INTEGER ByteOffset; #010 PVOID Buffer; #011 PDEVICE_OBJECT DeviceToVerify; #012 ULONG BytesPerSector; #013 #014 ASSERT(IrpContext); #015 #016 DPRINT("VfatRead(IrpContext %p)/n",IrpContext); #017 #018 ASSERT(IrpContext->DeviceObject); #019
如果是主设备对象,是不允许进行读取的操作。 #020 // This request is not allowed on the main device object #021 if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject) #022 { #023 DPRINT("VfatRead is called with the main device object./n"); #024 Status = STATUS_INVALID_DEVICE_REQUEST; #025 goto ByeBye; #026 } #027
获取当前文件对象的文件控制块。 #028 ASSERT(IrpContext->DeviceExt); #029 ASSERT(IrpContext->FileObject); #030 Fcb = IrpContext->FileObject->FsContext; #031 ASSERT(Fcb); #032 #033 DPRINT("<%wZ>/n",&Fcb->PathNameU); #034
如果当前文件是分页文件,就直接传送给下层驱动程序。 #035 if (Fcb->Flags & FCB_IS_PAGE_FILE) #036 { #037 PFATINFO FatInfo = &IrpContext->DeviceExt->FatInfo; #038 IrpContext->Stack->Parameters.Read.ByteOffset.QuadPart += FatInfo->dataStart * FatInfo->BytesPerSector; #039 IoSkipCurrentIrpStackLocation(IrpContext->Irp); #040 DPRINT("Read from page file,disk offset %I64x/n",IrpContext->Stack->Parameters.Read.ByteOffset.QuadPart); #041 Status = IoCallDriver(IrpContext->DeviceExt->StorageDevice,IrpContext->Irp); #042 VfatFreeIrpContext(IrpContext); #043 return Status; #044 } #045
获取读取的偏移位置。 #046 ByteOffset = IrpContext->Stack->Parameters.Read.ByteOffset;
获取读取的长度。 #047 Length = IrpContext->Stack->Parameters.Read.Length;
获取每个扇区的大小。 #048 BytesPerSector = IrpContext->DeviceExt->FatInfo.BytesPerSector; #049
如果当前是目录,但没有页可以读取,就返回出错。 #050 /* fail if file is a directory and no paged read */ #051 if (*Fcb->Attributes & FILE_ATTRIBUTE_DIRECTORY && !(IrpContext->Irp->Flags & IRP_PAGING_IO)) #052 { #053 Status = STATUS_INVALID_PARAMETER; #054 goto ByeBye; #055 } #056 #057 #058 DPRINT("'%wZ',Offset: %d,Length %d/n",&Fcb->PathNameU,ByteOffset.u.LowPart,Length); #059 #060 if (ByteOffset.u.HighPart && !(Fcb->Flags & FCB_IS_VOLUME)) #061 { #062 Status = STATUS_INVALID_PARAMETER; #063 goto ByeBye; #064 } #065 if (ByteOffset.QuadPart >= Fcb->RFCB.FileSize.QuadPart) #066 { #067 IrpContext->Irp->IoStatus.Information = 0; #068 Status = STATUS_END_OF_FILE; #069 goto ByeBye; #070 } #071 if (IrpContext->Irp->Flags & (IRP_PAGING_IO | IRP_NOCACHE) || (Fcb->Flags & FCB_IS_VOLUME)) #072 { #073 if (ByteOffset.u.LowPart % BytesPerSector != 0 || Length % BytesPerSector != 0) #074 { #075 DPRINT("%d %d/n",Length); #076 // non cached read must be sector aligned #077 Status = STATUS_INVALID_PARAMETER; #078 goto ByeBye; #079 } #080 } #081 if (Length == 0) #082 { #083 IrpContext->Irp->IoStatus.Information = 0; #084 Status = STATUS_SUCCESS; #085 goto ByeBye; #086 } #087
获取共享资源。 #088 if (Fcb->Flags & FCB_IS_VOLUME) #089 { #090 Resource = &IrpContext->DeviceExt->DirResource; #091 } #092 else if (IrpContext->Irp->Flags & IRP_PAGING_IO) #093 { #094 Resource = &Fcb->PagingIoResource; #095 } #096 else #097 { #098 Resource = &Fcb->MainResource; #099 }
判断共享资源是否允许读取。 #100 if (!ExAcquireResourceSharedLite(Resource, #101 IrpContext->Flags & IRPCONTEXT_CANWAIT ? TRUE : FALSE)) #102 { #103 Resource = NULL; #104 Status = STATUS_PENDING; #105 goto ByeBye; #106 } #107 #108 if (!(IrpContext->Irp->Flags & IRP_PAGING_IO) && #109 FsRtlAreThereCurrentFileLocks(&Fcb->FileLock)) #110 { #111 if (!FsRtlCheckLockForReadAccess(&Fcb->FileLock,IrpContext->Irp)) #112 { #113 Status = STATUS_FILE_LOCK_CONFLICT; #114 goto ByeBye; #115 } #116 } #117
获取用户接收数据的缓冲区。 #118 Buffer = VfatGetUserBuffer(IrpContext->Irp); #119 if (!Buffer) #120 { #121 Status = STATUS_INVALID_USER_BUFFER; #122 goto ByeBye; #123 } #124 #125 if (!(IrpContext->Irp->Flags & (IRP_NOCACHE|IRP_PAGING_IO)) && #126 !(Fcb->Flags & (FCB_IS_PAGE_FILE|FCB_IS_VOLUME))) #127 { #128 // cached read #129 Status = STATUS_SUCCESS; #130 if (ByteOffset.u.LowPart + Length > Fcb->RFCB.FileSize.u.LowPart) #131 { #132 Length = Fcb->RFCB.FileSize.u.LowPart - ByteOffset.u.LowPart; #133 Status = /*STATUS_END_OF_FILE*/STATUS_SUCCESS; #134 } #135 #136 if (IrpContext->FileObject->PrivateCacheMap == NULL) #137 { #138 CcInitializeCacheMap(IrpContext->FileObject, #139 (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize), #140 FALSE, #141 &(VfatGlobalData->CacheMgrCallbacks), #142 Fcb); #143 }
从缓存里读取磁盘数据。 #144 if (!CcCopyRead(IrpContext->FileObject,&ByteOffset,Length, #145 (BOOLEAN)(IrpContext->Flags & IRPCONTEXT_CANWAIT),Buffer, #146 &IrpContext->Irp->IoStatus)) #147 { #148 Status = STATUS_PENDING; #149 goto ByeBye; #150 } #151 if (!NT_SUCCESS(IrpContext->Irp->IoStatus.Status)) #152 { #153 Status = IrpContext->Irp->IoStatus.Status; #154 } #155 } #156 else #157 {
否则从磁盘文件里读取。 #158 // non cached read #159 if (ByteOffset.QuadPart + Length > ROUND_UP(Fcb->RFCB.FileSize.QuadPart,BytesPerSector)) #160 { #161 Length = (ULONG)(ROUND_UP(Fcb->RFCB.FileSize.QuadPart,BytesPerSector) - ByteOffset.QuadPart); #162 } #163 #164 Status = VfatLockUserBuffer(IrpContext->Irp,IoWriteAccess); #165 if (!NT_SUCCESS(Status)) #166 { #167 goto ByeBye; #168 } #169
从FAT管理的磁盘里读取文件数据。 #170 Status = VfatReadFileData(IrpContext,ByteOffset,&ReturnedLength); #171 /**/ #172 if (Status == STATUS_VERIFY_REQUIRED) #173 {
如果有校验的请求,就进行校验。 #174 DPRINT("VfatReadFile returned STATUS_VERIFY_REQUIRED/n"); #175 DeviceToVerify = IoGetDeviceToVerify(PsGetCurrentThread()); #176 IoSetDeviceToVerify(PsGetCurrentThread(),DeviceToVerify); #177 Status = IoVerifyVolume (DeviceToVerify,FALSE); #178 #179 if (NT_SUCCESS(Status)) #180 { #181 Status = VfatReadFileData(IrpContext, #182 ByteOffset,&ReturnedLength); #183 } #184 #185 } #186 /**/ #187 if (NT_SUCCESS(Status)) #188 { #189 IrpContext->Irp->IoStatus.Information = ReturnedLength; #190 } #191 } #192
下面是退出处理。 #193 ByeBye: #194 if (Resource) #195 { #196 ExReleaseResourceLite(Resource); #197 } #198
如果读取的操作,还在阻塞状态,就进行等待队列。 #199 if (Status == STATUS_PENDING) #200 { #201 Status = VfatLockUserBuffer(IrpContext->Irp,IoWriteAccess); #202 if (NT_SUCCESS(Status)) #203 { #204 Status = VfatQueueRequest(IrpContext); #205 } #206 else #207 { #208 IrpContext->Irp->IoStatus.Status = Status; #209 IoCompleteRequest(IrpContext->Irp,IO_NO_INCREMENT); #210 VfatFreeIrpContext(IrpContext); #211 } #212 } #213 else #214 { #215 IrpContext->Irp->IoStatus.Status = Status; #216 if (IrpContext->FileObject->Flags & FO_SYNCHRONOUS_IO && #217 !(IrpContext->Irp->Flags & IRP_PAGING_IO) && #218 (NT_SUCCESS(Status) || Status==STATUS_END_OF_FILE)) #219 { #220 IrpContext->FileObject->CurrentByteOffset.QuadPart = #221 ByteOffset.QuadPart + IrpContext->Irp->IoStatus.Information; #222 } #223
完成这个IRP请求。 #224 IoCompleteRequest(IrpContext->Irp, #225 (CCHAR)(NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT)); #226 VfatFreeIrpContext(IrpContext); #227 } #228 DPRINT("%x/n",Status); #229 return Status; #230} (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |