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}