VfatMount函数主要用来安装FAT文件卷,具体实现代码如下:
#001 static NTSTATUS
#002 VfatMount (PVFAT_IRP_CONTEXT IrpContext)
#003 /*
#004 * FUNCTION: Mount the filesystem
#005 */
#006 {
#007 PDEVICE_OBJECT DeviceObject = NULL;
#008 PDEVICE_EXTENSION DeviceExt = NULL;
#009 BOOLEAN RecognizedFS;
#010 NTSTATUS Status;
#011 PVFATFCB Fcb = NULL;
#012 PVFATFCB VolumeFcb = NULL;
#013 PVFATCCB Ccb = NULL;
#014 PDEVICE_OBJECT DeviceToMount;
#015 PVPB Vpb;
FAT的文件系统名称。
#016 UNICODE_STRING NameU = RTL_CONSTANT_STRING(L"//$$Fat$$");
操作系统文件卷名称。
#017 UNICODE_STRING VolumeNameU = RTL_CONSTANT_STRING(L"//$$Volume$$");
#018 ULONG HashTableSize;
#019 ULONG eocMark;
#020 FATINFO FatInfo;
#021
#022 DPRINT("VfatMount(IrpContext %p)/n", IrpContext);
#023
#024 ASSERT(IrpContext);
#025
如果当前请求的设备与FAT的设备不一致,就返回出错。
#026 if (IrpContext->DeviceObject != VfatGlobalData->DeviceObject)
#027 {
#028 Status = STATUS_INVALID_DEVICE_REQUEST;
#029 goto ByeBye;
#030 }
#031
获取当前要加载的设备。
#032 DeviceToMount = IrpContext->Stack->Parameters.MountVolume.DeviceObject;
获取卷描述信息。
#033 Vpb = IrpContext->Stack->Parameters.MountVolume.Vpb;
#034
在这里调用函数VfatHasFileSystem来判断要加载的设备是否为FAT文件系统设备,如果为FAT文件系统,RecognizedFS就返回TRUE,并且FatInfo返回FAT文件系统描述信息。
#035 Status = VfatHasFileSystem (DeviceToMount, &RecognizedFS, &FatInfo);
#036 if (!NT_SUCCESS(Status))
#037 {
#038 goto ByeBye;
#039 }
#040
如果不认识这个FAT的文件系统,就返回出错。
#041 if (RecognizedFS == FALSE)
#042 {
#043 DPRINT("VFAT: Unrecognized Volume/n");
#044 Status = STATUS_UNRECOGNIZED_VOLUME;
#045 goto ByeBye;
#046 }
#047
根据文件系统的类型来设置HASH表项的大小。
#048 /* Use prime numbers for the table size */
#049 if (FatInfo.FatType == FAT12)
#050 {
#051 HashTableSize = 4099; // 4096 = 4 * 1024
#052 }
#053 else if (FatInfo.FatType == FAT16 ||
#054 FatInfo.FatType == FATX16)
#055 {
#056 HashTableSize = 16411; // 16384 = 16 * 1024
#057 }
#058 else
#059 {
#060 HashTableSize = 65537; // 65536 = 64 * 1024;
#061 }
#062 HashTableSize = FCB_HASH_TABLE_SIZE;
#063 DPRINT("VFAT: Recognized volume/n");
为当前的文件卷创建一个文件设备。
#064 Status = IoCreateDevice(VfatGlobalData->DriverObject,
#065 ROUND_UP(sizeof (DEVICE_EXTENSION), sizeof(ULONG)) + sizeof(HASHENTRY*) * HashTableSize,
#066 NULL,
#067 FILE_DEVICE_DISK_FILE_SYSTEM,
#068 0,
#069 FALSE,
#070 &DeviceObject);
#071 if (!NT_SUCCESS(Status))
#072 {
#073 goto ByeBye;
#074 }
#075
设置设备属性。
#076 DeviceObject->Flags = DeviceObject->Flags | DO_DIRECT_IO;
#077 DeviceExt = (PVOID) DeviceObject->DeviceExtension;
#078 RtlZeroMemory(DeviceExt, ROUND_UP(sizeof(DEVICE_EXTENSION), sizeof(ULONG)) + sizeof(HASHENTRY*) * HashTableSize);
#079 DeviceExt->FcbHashTable = (HASHENTRY**)((ULONG_PTR)DeviceExt + ROUND_UP(sizeof(DEVICE_EXTENSION), sizeof(ULONG)));
#080 DeviceExt->HashTableSize = HashTableSize;
#081
文件卷设备和磁盘设备使用同样的VPB。
#082 /* use same vpb as device disk */
#083 DeviceObject->Vpb = Vpb;
#084 DeviceToMount->Vpb = Vpb;
#085
安装磁盘设备到这个文件卷功能设备上。
#086 Status = VfatMountDevice(DeviceExt, DeviceToMount);
#087 if (!NT_SUCCESS(Status))
#088 {
#089 /* FIXME: delete device object */
#090 goto ByeBye;
#091 }
#092
#093 DPRINT("BytesPerSector: %d/n", DeviceExt->FatInfo.BytesPerSector);
#094 DPRINT("SectorsPerCluster: %d/n", DeviceExt->FatInfo.SectorsPerCluster);
#095 DPRINT("FATCount: %d/n", DeviceExt->FatInfo.FATCount);
#096 DPRINT("FATSectors: %d/n", DeviceExt->FatInfo.FATSectors);
#097 DPRINT("RootStart: %d/n", DeviceExt->FatInfo.rootStart);
#098 DPRINT("DataStart: %d/n", DeviceExt->FatInfo.dataStart);
#099 if (DeviceExt->FatInfo.FatType == FAT32)
#100 {
#101 DPRINT("RootCluster: %d/n", DeviceExt->FatInfo.RootCluster);
#102 }
#103
根据不同的文件系统类型来进行回调函数设置。
#104 switch (DeviceExt->FatInfo.FatType)
#105 {
#106 case FAT12:
#107 DeviceExt->GetNextCluster = FAT12GetNextCluster;
#108 DeviceExt->FindAndMarkAvailableCluster = FAT12FindAndMarkAvailableCluster;
#109 DeviceExt->WriteCluster = FAT12WriteCluster;
#110 DeviceExt->CleanShutBitMask = 0;
#111 break;
#112
#113 case FAT16:
#114 case FATX16:
#115 DeviceExt->GetNextCluster = FAT16GetNextCluster;
#116 DeviceExt->FindAndMarkAvailableCluster = FAT16FindAndMarkAvailableCluster;
#117 DeviceExt->WriteCluster = FAT16WriteCluster;
#118 DeviceExt->CleanShutBitMask = 0x8000;
#119 break;
#120
#121 case FAT32:
#122 case FATX32:
#123 DeviceExt->GetNextCluster = FAT32GetNextCluster;
#124 DeviceExt->FindAndMarkAvailableCluster = FAT32FindAndMarkAvailableCluster;
#125 DeviceExt->WriteCluster = FAT32WriteCluster;
#126 DeviceExt->CleanShutBitMask = 0x80000000;
#127 break;
#128 }
#129
#130 if (DeviceExt->FatInfo.FatType == FATX16
#131 || DeviceExt->FatInfo.FatType == FATX32)
#132 {
#133 DeviceExt->Flags |= VCB_IS_FATX;
#134 DeviceExt->GetNextDirEntry = FATXGetNextDirEntry;
#135 DeviceExt->BaseDateYear = 2000;
#136 }
#137 else
#138 {
#139 DeviceExt->GetNextDirEntry = FATGetNextDirEntry;
#140 DeviceExt->BaseDateYear = 1980;
#141 }
#142
设置文件系统功能设备的底层设备,以便把IRP传送给底层驱动处理。
#143 DeviceExt->StorageDevice = DeviceToMount;
#144 DeviceExt->StorageDevice->Vpb->DeviceObject = DeviceObject;
#145 DeviceExt->StorageDevice->Vpb->RealDevice = DeviceExt->StorageDevice;
#146 DeviceExt->StorageDevice->Vpb->Flags |= VPB_MOUNTED;
#147 DeviceObject->StackSize = DeviceExt->StorageDevice->StackSize + 1;
#148 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
#149
#150 DPRINT("FsDeviceObject %p/n", DeviceObject);
#151
初始化设备清除使用的共享资源。
#152 /* Initialize this resource early ... it's used in VfatCleanup */
#153 ExInitializeResourceLite(&DeviceExt->DirResource);
#154
创建流文件对象用来表示一个文件卷。
#155 DeviceExt->FATFileObject = IoCreateStreamFileObject(NULL, DeviceExt->StorageDevice);
创建一块文件控制块。
#156 Fcb = vfatNewFCB(DeviceExt, &NameU);
#157 if (Fcb == NULL)
#158 {
#159 Status = STATUS_INSUFFICIENT_RESOURCES;
#160 goto ByeBye;
#161 }
#162 Ccb = ExAllocateFromNPagedLookasideList(&VfatGlobalData->CcbLookasideList);
#163 if (Ccb == NULL)
#164 {
#165 Status = STATUS_INSUFFICIENT_RESOURCES;
#166 goto ByeBye;
#167 }
#168
设置扩展属性。
#169 RtlZeroMemory(Ccb, sizeof (VFATCCB));
#170 DeviceExt->FATFileObject->FsContext = Fcb;
#171 DeviceExt->FATFileObject->FsContext2 = Ccb;
#172 DeviceExt->FATFileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;
#173 DeviceExt->FATFileObject->PrivateCacheMap = NULL;
#174 DeviceExt->FATFileObject->Vpb = DeviceObject->Vpb;
#175 Fcb->FileObject = DeviceExt->FATFileObject;
#176
设置为FAT标识。
#177 Fcb->Flags |= FCB_IS_FAT;
#178
#179 Fcb->RFCB.FileSize.QuadPart = DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector;
#180 Fcb->RFCB.ValidDataLength = Fcb->RFCB.FileSize;
#181 Fcb->RFCB.AllocationSize = Fcb->RFCB.FileSize;
#182
初始化文件读写的缓冲区。
#183 CcInitializeCacheMap(DeviceExt->FATFileObject,
#184 (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize),
#185 TRUE,
#186 &VfatGlobalData->CacheMgrCallbacks,
#187 Fcb);
#188
#189 DeviceExt->LastAvailableCluster = 2;
#190 ExInitializeResourceLite(&DeviceExt->FatResource);
#191
#192 InitializeListHead(&DeviceExt->FcbListHead);
#193
创建文件卷控制块。
#194 VolumeFcb = vfatNewFCB(DeviceExt, &VolumeNameU);
#195 if (VolumeFcb == NULL)
#196 {
#197 Status = STATUS_INSUFFICIENT_RESOURCES;
#198 goto ByeBye;
#199 }
#200 VolumeFcb->Flags = FCB_IS_VOLUME;
#201 VolumeFcb->RFCB.FileSize.QuadPart = DeviceExt->FatInfo.Sectors * DeviceExt->FatInfo.BytesPerSector;
#202 VolumeFcb->RFCB.ValidDataLength = VolumeFcb->RFCB.FileSize;
#203 VolumeFcb->RFCB.AllocationSize = VolumeFcb->RFCB.FileSize;
#204 DeviceExt->VolumeFcb = VolumeFcb;
#205
#206 ExAcquireResourceExclusiveLite(&VfatGlobalData->VolumeListLock, TRUE);
#207 InsertHeadList(&VfatGlobalData->VolumeListHead, &DeviceExt->VolumeListEntry);
#208 ExReleaseResourceLite(&VfatGlobalData->VolumeListLock);
#209
读取文件卷序号。
#210 /* read serial number */
#211 DeviceObject->Vpb->SerialNumber = DeviceExt->FatInfo.VolumeID;
#212
读取文件卷标。
#213 /* read volume label */
#214 ReadVolumeLabel(DeviceExt, DeviceObject->Vpb);
#215
读取并清除关闭标志。
#216 /* read clean shutdown bit status */
#217 Status = GetNextCluster(DeviceExt, 1, &eocMark);
#218 if (NT_SUCCESS(Status))
#219 {
#220 if (eocMark & DeviceExt->CleanShutBitMask)
#221 {
#222 /* unset clean shutdown bit */
#223 eocMark &= ~DeviceExt->CleanShutBitMask;
#224 WriteCluster(DeviceExt, 1, eocMark);
#225 VolumeFcb->Flags |= VCB_CLEAR_DIRTY;
#226 }
#227 }
#228 VolumeFcb->Flags |= VCB_IS_DIRTY;
#229
#230 Status = STATUS_SUCCESS;
#231 ByeBye:
#232
#233 if (!NT_SUCCESS(Status))
#234 {
#235 // cleanup
#236 if (DeviceExt && DeviceExt->FATFileObject)
#237 ObDereferenceObject (DeviceExt->FATFileObject);
#238 if (Fcb)
#239 vfatDestroyFCB(Fcb);
#240 if (Ccb)
#241 vfatDestroyCCB(Ccb);
#242 if (DeviceObject)
#243 IoDeleteDevice(DeviceObject);
#244 if (VolumeFcb)
#245 vfatDestroyFCB(VolumeFcb);
#246 }
#247 return Status;
#248 }