fsctl.c
来自「一个类似windows」· C语言 代码 · 共 928 行 · 第 1/3 页
C
928 行
static NTSTATUS
VfatVerify (PVFAT_IRP_CONTEXT IrpContext)
/*
* FUNCTION: Verify the filesystem
*/
{
PDEVICE_OBJECT DeviceToVerify;
NTSTATUS Status = STATUS_SUCCESS;
FATINFO FatInfo;
BOOLEAN RecognizedFS;
PDEVICE_EXTENSION DeviceExt = IrpContext->DeviceExt;
DPRINT("VfatVerify(IrpContext %x)\n", IrpContext);
DeviceToVerify = IrpContext->Stack->Parameters.VerifyVolume.DeviceObject;
Status = VfatBlockDeviceIoControl(DeviceToVerify,
IOCTL_DISK_CHECK_VERIFY,
NULL,
0,
NULL,
0,
TRUE);
DeviceToVerify->Flags &= ~DO_VERIFY_VOLUME;
if (!NT_SUCCESS(Status) && Status != STATUS_VERIFY_REQUIRED)
{
DPRINT("VfatBlockDeviceIoControl() failed (Status %lx)\n", Status);
Status = STATUS_WRONG_VOLUME;
}
else
{
Status = VfatHasFileSystem(DeviceToVerify, &RecognizedFS, &FatInfo);
if (!NT_SUCCESS(Status) || RecognizedFS == FALSE)
{
Status = STATUS_WRONG_VOLUME;
}
else if (sizeof(FATINFO) == RtlCompareMemory(&FatInfo, &DeviceExt->FatInfo, sizeof(FATINFO)))
{
/*
* FIXME:
* Preformated floppy disks have very often a serial number of 0000:0000.
* We should calculate a crc sum over the sectors from the root directory as secondary volume number.
* Each write to the root directory must update this crc sum.
*/
}
else
{
Status = STATUS_WRONG_VOLUME;
}
}
return Status;
}
static NTSTATUS
VfatGetVolumeBitmap(PVFAT_IRP_CONTEXT IrpContext)
{
DPRINT("VfatGetVolumeBitmap (IrpContext %x)\n", IrpContext);
return STATUS_INVALID_DEVICE_REQUEST;
}
static NTSTATUS
VfatGetRetrievalPointers(PVFAT_IRP_CONTEXT IrpContext)
{
PIO_STACK_LOCATION Stack;
LARGE_INTEGER Vcn;
PRETRIEVAL_POINTERS_BUFFER RetrievalPointers;
PFILE_OBJECT FileObject;
ULONG MaxExtentCount;
PVFATFCB Fcb;
PDEVICE_EXTENSION DeviceExt;
ULONG FirstCluster;
ULONG CurrentCluster;
ULONG LastCluster;
NTSTATUS Status;
DPRINT("VfatGetRetrievalPointers(IrpContext %x)\n", IrpContext);
DeviceExt = IrpContext->DeviceExt;
FileObject = IrpContext->FileObject;
Stack = IrpContext->Stack;
if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(STARTING_VCN_INPUT_BUFFER) ||
Stack->Parameters.DeviceIoControl.Type3InputBuffer == NULL)
{
return STATUS_INVALID_PARAMETER;
}
if (IrpContext->Irp->UserBuffer == NULL ||
Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(RETRIEVAL_POINTERS_BUFFER))
{
return STATUS_BUFFER_TOO_SMALL;
}
Fcb = FileObject->FsContext;
ExAcquireResourceSharedLite(&Fcb->MainResource, TRUE);
Vcn = ((PSTARTING_VCN_INPUT_BUFFER)Stack->Parameters.DeviceIoControl.Type3InputBuffer)->StartingVcn;
RetrievalPointers = IrpContext->Irp->UserBuffer;
MaxExtentCount = ((Stack->Parameters.DeviceIoControl.OutputBufferLength - sizeof(RetrievalPointers->ExtentCount) - sizeof(RetrievalPointers->StartingVcn)) / sizeof(RetrievalPointers->Extents[0]));
if (Vcn.QuadPart >= Fcb->RFCB.AllocationSize.QuadPart / DeviceExt->FatInfo.BytesPerCluster)
{
Status = STATUS_INVALID_PARAMETER;
goto ByeBye;
}
CurrentCluster = FirstCluster = vfatDirEntryGetFirstCluster(DeviceExt, &Fcb->entry);
Status = OffsetToCluster(DeviceExt, FirstCluster,
Vcn.u.LowPart * DeviceExt->FatInfo.BytesPerCluster,
&CurrentCluster, FALSE);
if (!NT_SUCCESS(Status))
{
goto ByeBye;
}
RetrievalPointers->StartingVcn = Vcn;
RetrievalPointers->ExtentCount = 0;
RetrievalPointers->Extents[0].Lcn.u.HighPart = 0;
RetrievalPointers->Extents[0].Lcn.u.LowPart = CurrentCluster - 2;
LastCluster = 0;
while (CurrentCluster != 0xffffffff && RetrievalPointers->ExtentCount < MaxExtentCount)
{
LastCluster = CurrentCluster;
Status = NextCluster(DeviceExt, CurrentCluster, &CurrentCluster, FALSE);
Vcn.QuadPart++;
if (!NT_SUCCESS(Status))
{
goto ByeBye;
}
if (LastCluster + 1 != CurrentCluster)
{
RetrievalPointers->Extents[RetrievalPointers->ExtentCount].NextVcn = Vcn;
RetrievalPointers->ExtentCount++;
if (RetrievalPointers->ExtentCount < MaxExtentCount)
{
RetrievalPointers->Extents[RetrievalPointers->ExtentCount].Lcn.u.HighPart = 0;
RetrievalPointers->Extents[RetrievalPointers->ExtentCount].Lcn.u.LowPart = CurrentCluster - 2;
}
}
}
IrpContext->Irp->IoStatus.Information = sizeof(RETRIEVAL_POINTERS_BUFFER) + (sizeof(RetrievalPointers->Extents[0]) * (RetrievalPointers->ExtentCount - 1));
Status = STATUS_SUCCESS;
ByeBye:
ExReleaseResourceLite(&Fcb->MainResource);
return Status;
}
static NTSTATUS
VfatMoveFile(PVFAT_IRP_CONTEXT IrpContext)
{
DPRINT("VfatMoveFile(IrpContext %x)\n", IrpContext);
return STATUS_INVALID_DEVICE_REQUEST;
}
#ifdef USE_ROS_CC_AND_FS
static NTSTATUS
VfatRosQueryLcnMapping(PVFAT_IRP_CONTEXT IrpContext)
{
PDEVICE_EXTENSION DeviceExt;
PROS_QUERY_LCN_MAPPING LcnQuery;
PIO_STACK_LOCATION Stack;
DPRINT("VfatRosQueryLcnMapping(IrpContext %x)\n", IrpContext);
DeviceExt = IrpContext->DeviceExt;
Stack = IrpContext->Stack;
if (IrpContext->Irp->AssociatedIrp.SystemBuffer == NULL ||
Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ROS_QUERY_LCN_MAPPING))
{
return STATUS_BUFFER_TOO_SMALL;
}
LcnQuery = (PROS_QUERY_LCN_MAPPING)(IrpContext->Irp->AssociatedIrp.SystemBuffer);
LcnQuery->LcnDiskOffset.QuadPart = DeviceExt->FatInfo.dataStart * DeviceExt->FatInfo.BytesPerSector;
IrpContext->Irp->IoStatus.Information = sizeof(ROS_QUERY_LCN_MAPPING);
return(STATUS_SUCCESS);
}
#endif
static NTSTATUS
VfatIsVolumeDirty(PVFAT_IRP_CONTEXT IrpContext)
{
PULONG Flags;
DPRINT("VfatIsVolumeDirty(IrpContext %x)\n", IrpContext);
if (IrpContext->Stack->Parameters.FileSystemControl.OutputBufferLength != sizeof(ULONG))
return STATUS_INVALID_BUFFER_SIZE;
else if (!IrpContext->Irp->AssociatedIrp.SystemBuffer)
return STATUS_INVALID_USER_BUFFER;
Flags = (PULONG)IrpContext->Irp->AssociatedIrp.SystemBuffer;
*Flags = 0;
if (IrpContext->DeviceExt->VolumeFcb->Flags & VCB_IS_DIRTY
&& !(IrpContext->DeviceExt->VolumeFcb->Flags & VCB_CLEAR_DIRTY))
{
*Flags |= VOLUME_IS_DIRTY;
}
return STATUS_SUCCESS;
}
static NTSTATUS
VfatMarkVolumeDirty(PVFAT_IRP_CONTEXT IrpContext)
{
ULONG eocMark;
PDEVICE_EXTENSION DeviceExt;
NTSTATUS Status = STATUS_SUCCESS;
DPRINT("VfatMarkVolumeDirty(IrpContext %x)\n", IrpContext);
DeviceExt = IrpContext->DeviceExt;
if (!(DeviceExt->VolumeFcb->Flags & VCB_IS_DIRTY))
{
Status = GetNextCluster(DeviceExt, 1, &eocMark);
if (NT_SUCCESS(Status))
{
/* unset clean shutdown bit */
eocMark &= ~DeviceExt->CleanShutBitMask;
Status = WriteCluster(DeviceExt, 1, eocMark);
}
}
DeviceExt->VolumeFcb->Flags &= ~VCB_CLEAR_DIRTY;
return Status;
}
NTSTATUS VfatFileSystemControl(PVFAT_IRP_CONTEXT IrpContext)
/*
* FUNCTION: File system control
*/
{
NTSTATUS Status;
DPRINT("VfatFileSystemControl(IrpContext %x)\n", IrpContext);
ASSERT(IrpContext);
ASSERT(IrpContext->Irp);
ASSERT(IrpContext->Stack);
IrpContext->Irp->IoStatus.Information = 0;
switch (IrpContext->MinorFunction)
{
case IRP_MN_USER_FS_REQUEST:
switch(IrpContext->Stack->Parameters.DeviceIoControl.IoControlCode)
{
case FSCTL_GET_VOLUME_BITMAP:
Status = VfatGetVolumeBitmap(IrpContext);
break;
case FSCTL_GET_RETRIEVAL_POINTERS:
Status = VfatGetRetrievalPointers(IrpContext);
break;
case FSCTL_MOVE_FILE:
Status = VfatMoveFile(IrpContext);
break;
#ifdef USE_ROS_CC_AND_FS
case FSCTL_ROS_QUERY_LCN_MAPPING:
Status = VfatRosQueryLcnMapping(IrpContext);
break;
#endif
case FSCTL_IS_VOLUME_DIRTY:
Status = VfatIsVolumeDirty(IrpContext);
break;
case FSCTL_MARK_VOLUME_DIRTY:
Status = VfatMarkVolumeDirty(IrpContext);
break;
default:
Status = STATUS_INVALID_DEVICE_REQUEST;
}
break;
case IRP_MN_MOUNT_VOLUME:
Status = VfatMount(IrpContext);
break;
case IRP_MN_VERIFY_VOLUME:
DPRINT("VFATFS: IRP_MN_VERIFY_VOLUME\n");
Status = VfatVerify(IrpContext);
break;
default:
DPRINT("VFAT FSC: MinorFunction %d\n", IrpContext->MinorFunction);
Status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
IrpContext->Irp->IoStatus.Status = Status;
IoCompleteRequest (IrpContext->Irp, IO_NO_INCREMENT);
VfatFreeIrpContext(IrpContext);
return (Status);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?