当从IO管理器里调用函数IopParseDevice来分析设备时,就可以找到相应的磁盘设备,并在这个函数里调用函数IopCheckVpbMounted来检查这个文件系统是否加载,如果没有加载,就会调用函数IopMountVolume来加载文件卷,那么在这个函数里就会构造一个IRP发送给文件系统驱动程序,驱动程序就收到主功能码为IRP_MJ_FILE_SYSTEM_CONTROL和次功能码为IRP_MN_MOUNT_VOLUME的IRP处理请求。在FAT文件系统里是通过函数VfatFileSystemControl来处理相应的功能码,具体实现如下:
#001 NTSTATUS VfatFileSystemControl(PVFAT_IRP_CONTEXT IrpContext)
#002 /*
#003 * FUNCTION: File system control
#004 */
#005 {
#006
#007 NTSTATUS Status;
#008
#009 DPRINT("VfatFileSystemControl(IrpContext %p)/n", IrpContext);
#010
#011 ASSERT(IrpContext);
#012 ASSERT(IrpContext->Irp);
#013 ASSERT(IrpContext->Stack);
#014
#015 IrpContext->Irp->IoStatus.Information = 0;
#016
这里区分次功能码,并分派给不同的函数处理。
#017 switch (IrpContext->MinorFunction)
#018 {
#019 case IRP_MN_USER_FS_REQUEST:
#020 switch(IrpContext->Stack->Parameters.DeviceIoControl.IoControlCode)
#021 {
#022 case FSCTL_GET_VOLUME_BITMAP:
#023 Status = VfatGetVolumeBitmap(IrpContext);
#024 break;
#025 case FSCTL_GET_RETRIEVAL_POINTERS:
#026 Status = VfatGetRetrievalPointers(IrpContext);
#027 break;
#028 case FSCTL_MOVE_FILE:
#029 Status = VfatMoveFile(IrpContext);
#030 break;
#031 #ifdef USE_ROS_CC_AND_FS
#032 case FSCTL_ROS_QUERY_LCN_MAPPING:
#033 Status = VfatRosQueryLcnMapping(IrpContext);
#034 break;
#035 #endif
#036 case FSCTL_IS_VOLUME_DIRTY:
#037 Status = VfatIsVolumeDirty(IrpContext);
#038 break;
#039 case FSCTL_MARK_VOLUME_DIRTY:
#040 Status = VfatMarkVolumeDirty(IrpContext);
#041 break;
#042 default:
#043 Status = STATUS_INVALID_DEVICE_REQUEST;
#044 }
#045 break;
#046
这里就是实现加载文件卷的功能码处理。
#047 case IRP_MN_MOUNT_VOLUME:
#048 Status = VfatMount(IrpContext);
#049 break;
#050
#051 case IRP_MN_VERIFY_VOLUME:
#052 DPRINT("VFATFS: IRP_MN_VERIFY_VOLUME/n");
#053 Status = VfatVerify(IrpContext);
#054 break;
#055
#056 default:
#057 DPRINT("VFAT FSC: MinorFunction %d/n", IrpContext->MinorFunction);
#058 Status = STATUS_INVALID_DEVICE_REQUEST;
#059 break;
#060 }
#061
#062 IrpContext->Irp->IoStatus.Status = Status;
#063
#064 IoCompleteRequest (IrpContext->Irp, IO_NO_INCREMENT);
#065 VfatFreeIrpContext(IrpContext);
#066 return (Status);
#067 }
#068