?? fileinfo.c
字號:
Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == FFSVCB) &&
(Vcb->Identifier.Size == sizeof(FFS_VCB)));
ASSERT(IsMounted(Vcb));
FileObject = IrpContext->FileObject;
Fcb = (PFFS_FCB)FileObject->FsContext;
ASSERT(Fcb != NULL);
//
// This request is not allowed on volumes
//
if (Fcb->Identifier.Type == FFSVCB)
{
FFSBreakPoint();
Status = STATUS_INVALID_PARAMETER;
__leave;
}
ASSERT((Fcb->Identifier.Type == FFSFCB) &&
(Fcb->Identifier.Size == sizeof(FFS_FCB)));
if (IsFlagOn(Fcb->Flags, FCB_FILE_DELETED))
{
Status = STATUS_FILE_DELETED;
__leave;
}
Ccb = (PFFS_CCB)FileObject->FsContext2;
ASSERT(Ccb != NULL);
ASSERT((Ccb->Identifier.Type == FFSCCB) &&
(Ccb->Identifier.Size == sizeof(FFS_CCB)));
Irp = IrpContext->Irp;
IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
FileInformationClass =
IoStackLocation->Parameters.SetFile.FileInformationClass;
Length = IoStackLocation->Parameters.SetFile.Length;
Buffer = Irp->AssociatedIrp.SystemBuffer;
if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY))
{
if (FileInformationClass == FileDispositionInformation ||
FileInformationClass == FileRenameInformation ||
FileInformationClass == FileLinkInformation)
{
if (!ExAcquireResourceExclusiveLite(
&Vcb->MainResource,
IrpContext->IsSynchronous))
{
Status = STATUS_PENDING;
__leave;
}
VcbResourceAcquired = TRUE;
}
}
else if (!FlagOn(Fcb->Flags, FCB_PAGE_FILE))
{
if (!ExAcquireResourceExclusiveLite(
&Fcb->MainResource,
IrpContext->IsSynchronous))
{
Status = STATUS_PENDING;
__leave;
}
FcbMainResourceAcquired = TRUE;
}
if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY))
{
if (FileInformationClass != FilePositionInformation)
{
Status = STATUS_MEDIA_WRITE_PROTECTED;
__leave;
}
}
if (FileInformationClass == FileDispositionInformation ||
FileInformationClass == FileRenameInformation ||
FileInformationClass == FileLinkInformation ||
FileInformationClass == FileAllocationInformation ||
FileInformationClass == FileEndOfFileInformation)
{
if (!ExAcquireResourceExclusiveLite(
&Fcb->PagingIoResource,
IrpContext->IsSynchronous))
{
Status = STATUS_PENDING;
__leave;
}
FcbPagingIoResourceAcquired = TRUE;
}
/*
if (FileInformationClass != FileDispositionInformation
&& FlagOn(Fcb->Flags, FCB_DELETE_PENDING))
{
Status = STATUS_DELETE_PENDING;
__leave;
}
*/
switch (FileInformationClass)
{
case FileBasicInformation:
{
PFILE_BASIC_INFORMATION FBI = (PFILE_BASIC_INFORMATION)Buffer;
if (FS_VERSION == 1)
{
PFFSv1_INODE dinode1 = Fcb->dinode1;
if(FBI->CreationTime.QuadPart)
{
dinode1->di_ctime = (ULONG)(FFSInodeTime(FBI->CreationTime));
}
if(FBI->LastAccessTime.QuadPart)
{
dinode1->di_atime = (ULONG)(FFSInodeTime(FBI->LastAccessTime));
}
if(FBI->LastWriteTime.QuadPart)
{
dinode1->di_mtime = (ULONG)(FFSInodeTime(FBI->LastWriteTime));
}
if (IsFlagOn(FBI->FileAttributes, FILE_ATTRIBUTE_READONLY))
{
FFSSetReadOnly(Fcb->dinode1->di_mode);
SetFlag(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_READONLY);
}
else
{
FFSSetWritable(Fcb->dinode1->di_mode);
ClearFlag(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_READONLY);
}
if(FFSv1SaveInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, dinode1))
{
Status = STATUS_SUCCESS;
}
if (FBI->FileAttributes & FILE_ATTRIBUTE_TEMPORARY)
{
SetFlag(FileObject->Flags, FO_TEMPORARY_FILE);
}
else
{
ClearFlag(FileObject->Flags, FO_TEMPORARY_FILE);
}
}
else
{
PFFSv2_INODE dinode2 = Fcb->dinode2;
if(FBI->CreationTime.QuadPart)
{
dinode2->di_ctime = (ULONG)(FFSInodeTime(FBI->CreationTime));
}
if(FBI->LastAccessTime.QuadPart)
{
dinode2->di_atime = (ULONG)(FFSInodeTime(FBI->LastAccessTime));
}
if(FBI->LastWriteTime.QuadPart)
{
dinode2->di_mtime = (ULONG)(FFSInodeTime(FBI->LastWriteTime));
}
if (IsFlagOn(FBI->FileAttributes, FILE_ATTRIBUTE_READONLY))
{
FFSSetReadOnly(Fcb->dinode2->di_mode);
SetFlag(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_READONLY);
}
else
{
FFSSetWritable(Fcb->dinode2->di_mode);
ClearFlag(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_READONLY);
}
if(FFSv2SaveInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, dinode2))
{
Status = STATUS_SUCCESS;
}
if (FBI->FileAttributes & FILE_ATTRIBUTE_TEMPORARY)
{
SetFlag(FileObject->Flags, FO_TEMPORARY_FILE);
}
else
{
ClearFlag(FileObject->Flags, FO_TEMPORARY_FILE);
}
}
NotifyFilter = FILE_NOTIFY_CHANGE_ATTRIBUTES |
FILE_NOTIFY_CHANGE_CREATION |
FILE_NOTIFY_CHANGE_LAST_ACCESS |
FILE_NOTIFY_CHANGE_LAST_WRITE ;
Status = STATUS_SUCCESS;
}
break;
case FileAllocationInformation:
{
PFILE_ALLOCATION_INFORMATION FAI = (PFILE_ALLOCATION_INFORMATION)Buffer;
if (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
{
Status = STATUS_INVALID_DEVICE_REQUEST;
__leave;
}
if (FAI->AllocationSize.QuadPart ==
Fcb->Header.AllocationSize.QuadPart)
{
Status = STATUS_SUCCESS;
}
else if (FAI->AllocationSize.QuadPart >
Fcb->Header.AllocationSize.QuadPart)
{
if(FFSExpandFile(IrpContext,
Vcb, Fcb,
&(FAI->AllocationSize)))
{
if (FFSv1SaveInode(IrpContext,
Vcb,
Fcb->FFSMcb->Inode,
Fcb->dinode1))
{
Status = STATUS_SUCCESS;
}
}
else
{
Status = STATUS_INSUFFICIENT_RESOURCES;
}
}
else
{
if (MmCanFileBeTruncated(&(Fcb->SectionObject), &(FAI->AllocationSize)))
{
LARGE_INTEGER EndOfFile;
EndOfFile.QuadPart = FAI->AllocationSize.QuadPart +
(LONGLONG)(Vcb->BlockSize - 1);
if(FFSTruncateFile(IrpContext, Vcb, Fcb, &(EndOfFile)))
{
if (FAI->AllocationSize.QuadPart <
Fcb->Header.FileSize.QuadPart)
{
Fcb->Header.FileSize.QuadPart =
FAI->AllocationSize.QuadPart;
}
FFSv1SaveInode(IrpContext,
Vcb,
Fcb->FFSMcb->Inode,
Fcb->dinode1);
Status = STATUS_SUCCESS;
}
}
else
{
Status = STATUS_USER_MAPPED_FILE;
__leave;
}
}
if (NT_SUCCESS(Status))
{
CcSetFileSizes(FileObject,
(PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
NotifyFilter = FILE_NOTIFY_CHANGE_SIZE |
FILE_NOTIFY_CHANGE_LAST_WRITE ;
}
}
break;
case FileEndOfFileInformation:
{
PFILE_END_OF_FILE_INFORMATION FEOFI = (PFILE_END_OF_FILE_INFORMATION) Buffer;
BOOLEAN CacheInitialized = FALSE;
if (IsDirectory(Fcb))
{
Status = STATUS_INVALID_DEVICE_REQUEST;
__leave;
}
if (FEOFI->EndOfFile.HighPart != 0)
{
Status = STATUS_INVALID_PARAMETER;
__leave;
}
if (IoStackLocation->Parameters.SetFile.AdvanceOnly)
{
Status = STATUS_SUCCESS;
__leave;
}
if ((FileObject->SectionObjectPointer->DataSectionObject != NULL) &&
(FileObject->SectionObjectPointer->SharedCacheMap == NULL) &&
!FlagOn(Irp->Flags, IRP_PAGING_IO)) {
ASSERT(!FlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE));
CcInitializeCacheMap(
FileObject,
(PCC_FILE_SIZES)&(Fcb->Header.AllocationSize),
FALSE,
&(FFSGlobal->CacheManagerNoOpCallbacks),
Fcb);
CacheInitialized = TRUE;
}
if (FEOFI->EndOfFile.QuadPart ==
Fcb->Header.AllocationSize.QuadPart)
{
Status = STATUS_SUCCESS;
}
else if (FEOFI->EndOfFile.QuadPart >
Fcb->Header.AllocationSize.QuadPart)
{
LARGE_INTEGER FileSize = Fcb->Header.FileSize;
if(FFSExpandFile(IrpContext, Vcb, Fcb, &(FEOFI->EndOfFile)))
{
{
Fcb->Header.FileSize.QuadPart =
FEOFI->EndOfFile.QuadPart;
Fcb->dinode1->di_size = (ULONG)FEOFI->EndOfFile.QuadPart;
Fcb->Header.ValidDataLength.QuadPart =
(LONGLONG)(0x7fffffffffffffff);
}
if (FFSv1SaveInode(IrpContext,
Vcb,
Fcb->FFSMcb->Inode,
Fcb->dinode1))
{
Status = STATUS_SUCCESS;
}
}
else
{
Status = STATUS_INSUFFICIENT_RESOURCES;
}
if (NT_SUCCESS(Status))
{
CcSetFileSizes(FileObject,
(PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
FFSZeroHoles(IrpContext,
Vcb, FileObject,
FileSize.QuadPart,
Fcb->Header.AllocationSize.QuadPart -
FileSize.QuadPart);
NotifyFilter = FILE_NOTIFY_CHANGE_SIZE |
FILE_NOTIFY_CHANGE_LAST_WRITE ;
}
}
else
{
if (MmCanFileBeTruncated(&(Fcb->SectionObject), &(FEOFI->EndOfFile)))
{
LARGE_INTEGER EndOfFile = FEOFI->EndOfFile;
EndOfFile.QuadPart = EndOfFile.QuadPart +
(LONGLONG)(Vcb->BlockSize - 1);
if(FFSTruncateFile(IrpContext, Vcb, Fcb, &(EndOfFile)))
{
Fcb->Header.FileSize.QuadPart =
FEOFI->EndOfFile.QuadPart;
Fcb->dinode1->di_size = (ULONG)FEOFI->EndOfFile.QuadPart;
FFSv1SaveInode(IrpContext,
Vcb,
Fcb->FFSMcb->Inode,
Fcb->dinode1);
Status = STATUS_SUCCESS;
}
}
else
{
Status = STATUS_USER_MAPPED_FILE;
__leave;
}
if (NT_SUCCESS(Status))
{
CcSetFileSizes(FileObject,
(PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
NotifyFilter = FILE_NOTIFY_CHANGE_SIZE |
FILE_NOTIFY_CHANGE_LAST_WRITE ;
}
}
}
break;
case FileDispositionInformation:
{
PFILE_DISPOSITION_INFORMATION FDI = (PFILE_DISPOSITION_INFORMATION)Buffer;
Status = FFSSetDispositionInfo(IrpContext, Vcb, Fcb, FDI->DeleteFile);
}
break;
case FileRenameInformation:
{
Status = FFSSetRenameInfo(IrpContext, Vcb, Fcb);
}
break;
//
// This is the only set file information request supported on read
// only file systems
//
case FilePositionInformation:
{
PFILE_POSITION_INFORMATION FilePositionInformation;
if (Length < sizeof(FILE_POSITION_INFORMATION))
{
Status = STATUS_INVALID_PARAMETER;
__leave;
}
FilePositionInformation = (PFILE_POSITION_INFORMATION) Buffer;
if ((FlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING)) &&
(FilePositionInformation->CurrentByteOffset.LowPart &
DeviceObject->AlignmentRequirement))
{
Status = STATUS_INVALID_PARAMETER;
__leave;
}
FileObject->CurrentByteOffset =
FilePositionInformation->CurrentByteOffset;
Status = STATUS_SUCCESS;
__leave;
}
break;
default:
Status = STATUS_INVALID_INFO_CLASS;
}
}
__finally
{
if (FcbPagingIoResourceAcquired)
{
ExReleaseResourceForThreadLite(
&Fcb->PagingIoResource,
ExGetCurrentResourceThread());
}
if (NT_SUCCESS(Status) && (NotifyFilter != 0))
{
FFSNotifyReportChange(
IrpContext,
Vcb,
Fcb,
NotifyFilter,
FILE_ACTION_MODIFIED);
}
if (FcbMainResourceAcquired)
{
ExReleaseResourceForThreadLite(
&Fcb->MainResource,
ExGetCurrentResourceThread());
}
if (VcbResourceAcquired)
{
ExReleaseResourceForThreadLite(
&Vcb->MainResource,
ExGetCurrentResourceThread());
}
if (!IrpContext->ExceptionInProgress)
{
if (Status == STATUS_PENDING)
{
FFSQueueRequest(IrpContext);
}
else
{
FFSCompleteIrpContext(IrpContext, Status);
}
}
}
return Status;
}
BOOLEAN
FFSExpandFile(
PFFS_IRP_CONTEXT IrpContext,
PFFS_VCB Vcb,
PFFS_FCB Fcb,
PLARGE_INTEGER AllocationSize)
{
ULONG dwRet = 0;
BOOLEAN bRet = TRUE;
if (AllocationSize->QuadPart <= Fcb->Header.AllocationSize.QuadPart)
{
return TRUE;
}
if (((LONGLONG)SUPER_BLOCK->fs_size - (LONGLONG)SUPER_BLOCK->fs_dsize) * Vcb->BlockSize <=
(AllocationSize->QuadPart - Fcb->Header.AllocationSize.QuadPart))
{
FFSPrint((DBG_ERROR, "FFSExpandFile: There is no enough disk space available.\n"));
return FALSE;
}
while (bRet && (AllocationSize->QuadPart > Fcb->Header.AllocationSize.QuadPart))
{
bRet = FFSExpandInode(IrpContext, Vcb, Fcb, &dwRet);
}
return bRet;
}
BOOLEAN
FFSTruncateFile(
PFFS_IRP_CONTEXT IrpContext,
PFFS_VCB Vcb,
PFFS_FCB Fcb,
PLARGE_INTEGER AllocationSize)
{
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -