finfo.c
来自「winNT技术操作系统,国外开放的原代码和LIUX一样」· C语言 代码 · 共 933 行 · 第 1/2 页
C
933 行
static NTSTATUS
VfatGetAllInformation(PFILE_OBJECT FileObject,
PVFATFCB Fcb,
PDEVICE_OBJECT DeviceObject,
PFILE_ALL_INFORMATION Info,
PULONG BufferLength)
/*
* FUNCTION: Retrieve the all file information
*/
{
NTSTATUS Status;
ULONG InitialBufferLength = *BufferLength;
ASSERT(Info);
ASSERT(Fcb);
if (*BufferLength < sizeof(FILE_ALL_INFORMATION) + Fcb->PathNameU.Length + sizeof(WCHAR))
return(STATUS_BUFFER_OVERFLOW);
/* Basic Information */
Status = VfatGetBasicInformation(FileObject, Fcb, DeviceObject, &Info->BasicInformation, BufferLength);
if (!NT_SUCCESS(Status)) return Status;
/* Standard Information */
Status = VfatGetStandardInformation(Fcb, &Info->StandardInformation, BufferLength);
if (!NT_SUCCESS(Status)) return Status;
/* Internal Information */
Status = VfatGetInternalInformation(Fcb, &Info->InternalInformation, BufferLength);
if (!NT_SUCCESS(Status)) return Status;
/* EA Information */
Info->EaInformation.EaSize = 0;
/* Access Information: The IO-Manager adds this information */
/* Position Information */
Status = VfatGetPositionInformation(FileObject, Fcb, DeviceObject, &Info->PositionInformation, BufferLength);
if (!NT_SUCCESS(Status)) return Status;
/* Mode Information: The IO-Manager adds this information */
/* Alignment Information: The IO-Manager adds this information */
/* Name Information */
Status = VfatGetNameInformation(FileObject, Fcb, DeviceObject, &Info->NameInformation, BufferLength);
if (!NT_SUCCESS(Status)) return Status;
*BufferLength = InitialBufferLength - (sizeof(FILE_ALL_INFORMATION) + Fcb->PathNameU.Length + sizeof(WCHAR));
return STATUS_SUCCESS;
}
static VOID UpdateFileSize(PFILE_OBJECT FileObject, PVFATFCB Fcb, ULONG Size, ULONG ClusterSize)
{
if (Size > 0)
{
Fcb->RFCB.AllocationSize.QuadPart = ROUND_UP(Size, ClusterSize);
}
else
{
Fcb->RFCB.AllocationSize.QuadPart = (LONGLONG)0;
}
if (!vfatFCBIsDirectory(Fcb))
{
if (Fcb->Flags & FCB_IS_FATX_ENTRY)
Fcb->entry.FatX.FileSize = Size;
else
Fcb->entry.Fat.FileSize = Size;
}
Fcb->RFCB.FileSize.QuadPart = Size;
Fcb->RFCB.ValidDataLength.QuadPart = Size;
if (FileObject->SectionObjectPointer->SharedCacheMap != NULL)
{
CcSetFileSizes(FileObject, (PCC_FILE_SIZES)&Fcb->RFCB.AllocationSize);
}
}
NTSTATUS
VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject,
PVFATFCB Fcb,
PDEVICE_EXTENSION DeviceExt,
PLARGE_INTEGER AllocationSize)
{
ULONG OldSize;
ULONG Cluster, FirstCluster;
NTSTATUS Status;
ULONG ClusterSize = DeviceExt->FatInfo.BytesPerCluster;
ULONG NewSize = AllocationSize->u.LowPart;
ULONG NCluster;
BOOLEAN AllocSizeChanged = FALSE;
DPRINT("VfatSetAllocationSizeInformation()\n");
if (Fcb->Flags & FCB_IS_FATX_ENTRY)
OldSize = Fcb->entry.FatX.FileSize;
else
OldSize = Fcb->entry.Fat.FileSize;
if (AllocationSize->u.HighPart > 0)
{
return STATUS_INVALID_PARAMETER;
}
if (OldSize == NewSize)
{
return(STATUS_SUCCESS);
}
FirstCluster = vfatDirEntryGetFirstCluster (DeviceExt, &Fcb->entry);
if (NewSize > Fcb->RFCB.AllocationSize.u.LowPart)
{
AllocSizeChanged = TRUE;
if (FirstCluster == 0)
{
Fcb->LastCluster = Fcb->LastOffset = 0;
Status = NextCluster (DeviceExt, FirstCluster, &FirstCluster, TRUE);
if (!NT_SUCCESS(Status))
{
DPRINT1("NextCluster failed. Status = %x\n", Status);
return Status;
}
if (FirstCluster == 0xffffffff)
{
return STATUS_DISK_FULL;
}
Status = OffsetToCluster(DeviceExt, FirstCluster,
ROUND_DOWN(NewSize - 1, ClusterSize),
&NCluster, TRUE);
if (NCluster == 0xffffffff || !NT_SUCCESS(Status))
{
/* disk is full */
NCluster = Cluster = FirstCluster;
Status = STATUS_SUCCESS;
while (NT_SUCCESS(Status) && Cluster != 0xffffffff && Cluster > 1)
{
Status = NextCluster (DeviceExt, FirstCluster, &NCluster, FALSE);
WriteCluster (DeviceExt, Cluster, 0);
Cluster = NCluster;
}
return STATUS_DISK_FULL;
}
if (Fcb->Flags & FCB_IS_FATX_ENTRY)
{
Fcb->entry.FatX.FirstCluster = FirstCluster;
}
else
{
if (DeviceExt->FatInfo.FatType == FAT32)
{
Fcb->entry.Fat.FirstCluster = (unsigned short)(FirstCluster & 0x0000FFFF);
Fcb->entry.Fat.FirstClusterHigh = FirstCluster >> 16;
}
else
{
ASSERT((FirstCluster >> 16) == 0);
Fcb->entry.Fat.FirstCluster = (unsigned short)(FirstCluster & 0x0000FFFF);
}
}
}
else
{
if (Fcb->LastCluster > 0)
{
if (Fcb->RFCB.AllocationSize.u.LowPart - ClusterSize == Fcb->LastOffset)
{
Cluster = Fcb->LastCluster;
Status = STATUS_SUCCESS;
}
else
{
Status = OffsetToCluster(DeviceExt, Fcb->LastCluster,
Fcb->RFCB.AllocationSize.u.LowPart - ClusterSize - Fcb->LastOffset,
&Cluster, FALSE);
}
}
else
{
Status = OffsetToCluster(DeviceExt, FirstCluster,
Fcb->RFCB.AllocationSize.u.LowPart - ClusterSize,
&Cluster, FALSE);
}
if (!NT_SUCCESS(Status))
{
return Status;
}
if (Fcb->LastCluster == 0)
{
Fcb->LastCluster = Cluster;
Fcb->LastOffset = Fcb->RFCB.AllocationSize.u.LowPart - ClusterSize;
}
/* FIXME: Check status */
/* Cluster points now to the last cluster within the chain */
Status = OffsetToCluster(DeviceExt, Cluster,
ROUND_DOWN(NewSize - 1, ClusterSize) - Fcb->LastOffset,
&NCluster, TRUE);
if (NCluster == 0xffffffff || !NT_SUCCESS(Status))
{
/* disk is full */
NCluster = Cluster;
Status = NextCluster (DeviceExt, FirstCluster, &NCluster, FALSE);
WriteCluster(DeviceExt, Cluster, 0xffffffff);
Cluster = NCluster;
while (NT_SUCCESS(Status) && Cluster != 0xffffffff && Cluster > 1)
{
Status = NextCluster (DeviceExt, FirstCluster, &NCluster, FALSE);
WriteCluster (DeviceExt, Cluster, 0);
Cluster = NCluster;
}
return STATUS_DISK_FULL;
}
}
UpdateFileSize(FileObject, Fcb, NewSize, ClusterSize);
}
else if (NewSize + ClusterSize <= Fcb->RFCB.AllocationSize.u.LowPart)
{
AllocSizeChanged = TRUE;
/* FIXME: Use the cached cluster/offset better way. */
Fcb->LastCluster = Fcb->LastCluster = 0;
UpdateFileSize(FileObject, Fcb, NewSize, ClusterSize);
if (NewSize > 0)
{
Status = OffsetToCluster(DeviceExt, FirstCluster,
ROUND_DOWN(NewSize - 1, ClusterSize),
&Cluster, FALSE);
NCluster = Cluster;
Status = NextCluster (DeviceExt, FirstCluster, &NCluster, FALSE);
WriteCluster(DeviceExt, Cluster, 0xffffffff);
Cluster = NCluster;
}
else
{
if (Fcb->Flags & FCB_IS_FATX_ENTRY)
{
Fcb->entry.FatX.FirstCluster = 0;
}
else
{
if (DeviceExt->FatInfo.FatType == FAT32)
{
Fcb->entry.Fat.FirstCluster = 0;
Fcb->entry.Fat.FirstClusterHigh = 0;
}
else
{
Fcb->entry.Fat.FirstCluster = 0;
}
}
NCluster = Cluster = FirstCluster;
Status = STATUS_SUCCESS;
}
while (NT_SUCCESS(Status) && 0xffffffff != Cluster && Cluster > 1)
{
Status = NextCluster (DeviceExt, FirstCluster, &NCluster, FALSE);
WriteCluster (DeviceExt, Cluster, 0);
Cluster = NCluster;
}
}
else
{
UpdateFileSize(FileObject, Fcb, NewSize, ClusterSize);
}
/* Update the on-disk directory entry */
Fcb->Flags |= FCB_IS_DIRTY;
if (AllocSizeChanged)
{
VfatUpdateEntry(Fcb);
}
return STATUS_SUCCESS;
}
NTSTATUS VfatQueryInformation(PVFAT_IRP_CONTEXT IrpContext)
/*
* FUNCTION: Retrieve the specified file information
*/
{
FILE_INFORMATION_CLASS FileInformationClass;
PVFATFCB FCB = NULL;
NTSTATUS RC = STATUS_SUCCESS;
PVOID SystemBuffer;
ULONG BufferLength;
/* PRECONDITION */
ASSERT(IrpContext);
/* INITIALIZATION */
FileInformationClass = IrpContext->Stack->Parameters.QueryFile.FileInformationClass;
FCB = (PVFATFCB) IrpContext->FileObject->FsContext;
DPRINT("VfatQueryInformation is called for '%s'\n",
FileInformationClass >= FileMaximumInformation - 1 ? "????" : FileInformationClassNames[FileInformationClass]);
SystemBuffer = IrpContext->Irp->AssociatedIrp.SystemBuffer;
BufferLength = IrpContext->Stack->Parameters.QueryFile.Length;
if (!(FCB->Flags & FCB_IS_PAGE_FILE))
{
if (!ExAcquireResourceSharedLite(&FCB->MainResource,
(BOOLEAN)(IrpContext->Flags & IRPCONTEXT_CANWAIT)))
{
return VfatQueueRequest (IrpContext);
}
}
switch (FileInformationClass)
{
case FileStandardInformation:
RC = VfatGetStandardInformation(FCB,
SystemBuffer,
&BufferLength);
break;
case FilePositionInformation:
RC = VfatGetPositionInformation(IrpContext->FileObject,
FCB,
IrpContext->DeviceObject,
SystemBuffer,
&BufferLength);
break;
case FileBasicInformation:
RC = VfatGetBasicInformation(IrpContext->FileObject,
FCB,
IrpContext->DeviceObject,
SystemBuffer,
&BufferLength);
break;
case FileNameInformation:
RC = VfatGetNameInformation(IrpContext->FileObject,
FCB,
IrpContext->DeviceObject,
SystemBuffer,
&BufferLength);
break;
case FileInternalInformation:
RC = VfatGetInternalInformation(FCB,
SystemBuffer,
&BufferLength);
break;
case FileNetworkOpenInformation:
RC = VfatGetNetworkOpenInformation(FCB,
IrpContext->DeviceExt,
SystemBuffer,
&BufferLength);
break;
case FileAllInformation:
RC = VfatGetAllInformation(IrpContext->FileObject,
FCB,
IrpContext->DeviceObject,
SystemBuffer,
&BufferLength);
break;
case FileEaInformation:
RC = VfatGetEaInformation(IrpContext->FileObject,
FCB,
IrpContext->DeviceObject,
SystemBuffer,
&BufferLength);
break;
case FileAlternateNameInformation:
RC = STATUS_NOT_IMPLEMENTED;
break;
default:
RC = STATUS_NOT_SUPPORTED;
}
if (!(FCB->Flags & FCB_IS_PAGE_FILE))
{
ExReleaseResourceLite(&FCB->MainResource);
}
IrpContext->Irp->IoStatus.Status = RC;
if (NT_SUCCESS(RC))
IrpContext->Irp->IoStatus.Information =
IrpContext->Stack->Parameters.QueryFile.Length - BufferLength;
else
IrpContext->Irp->IoStatus.Information = 0;
IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
VfatFreeIrpContext(IrpContext);
return RC;
}
NTSTATUS VfatSetInformation(PVFAT_IRP_CONTEXT IrpContext)
/*
* FUNCTION: Retrieve the specified file information
*/
{
FILE_INFORMATION_CLASS FileInformationClass;
PVFATFCB FCB = NULL;
NTSTATUS RC = STATUS_SUCCESS;
PVOID SystemBuffer;
BOOLEAN CanWait = (IrpContext->Flags & IRPCONTEXT_CANWAIT) != 0;
/* PRECONDITION */
ASSERT(IrpContext);
DPRINT("VfatSetInformation(IrpContext %x)\n", IrpContext);
/* INITIALIZATION */
FileInformationClass =
IrpContext->Stack->Parameters.SetFile.FileInformationClass;
FCB = (PVFATFCB) IrpContext->FileObject->FsContext;
SystemBuffer = IrpContext->Irp->AssociatedIrp.SystemBuffer;
DPRINT("VfatSetInformation is called for '%s'\n",
FileInformationClass >= FileMaximumInformation - 1 ? "????" : FileInformationClassNames[ FileInformationClass]);
DPRINT("FileInformationClass %d\n", FileInformationClass);
DPRINT("SystemBuffer %x\n", SystemBuffer);
if (!(FCB->Flags & FCB_IS_PAGE_FILE))
{
if (!ExAcquireResourceExclusiveLite(&FCB->MainResource,
(BOOLEAN)CanWait))
{
return(VfatQueueRequest (IrpContext));
}
}
switch (FileInformationClass)
{
case FilePositionInformation:
RC = VfatSetPositionInformation(IrpContext->FileObject,
SystemBuffer);
break;
case FileDispositionInformation:
RC = VfatSetDispositionInformation(IrpContext->FileObject,
FCB,
IrpContext->DeviceObject,
SystemBuffer);
break;
case FileAllocationInformation:
case FileEndOfFileInformation:
RC = VfatSetAllocationSizeInformation(IrpContext->FileObject,
FCB,
IrpContext->DeviceExt,
(PLARGE_INTEGER)SystemBuffer);
break;
case FileBasicInformation:
RC = VfatSetBasicInformation(IrpContext->FileObject,
FCB,
IrpContext->DeviceExt,
SystemBuffer);
break;
case FileRenameInformation:
RC = STATUS_NOT_IMPLEMENTED;
break;
default:
RC = STATUS_NOT_SUPPORTED;
}
if (!(FCB->Flags & FCB_IS_PAGE_FILE))
{
ExReleaseResourceLite(&FCB->MainResource);
}
IrpContext->Irp->IoStatus.Status = RC;
IrpContext->Irp->IoStatus.Information = 0;
IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
VfatFreeIrpContext(IrpContext);
return RC;
}
/* EOF */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?