reactos/drivers/filesystems/ffs/src/fileinfo.c

1789 lines
40 KiB
C

/*
* FFS File System Driver for Windows
*
* fileinfo.c
*
* 2004.5.6 ~
*
* Lee Jae-Hong, http://www.pyrasis.com
*
* See License.txt
*
*/
#include "ntifs.h"
#include "ffsdrv.h"
/* Globals */
extern PFFS_GLOBAL FFSGlobal;
/* Definitions */
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FFSQueryInformation)
#pragma alloc_text(PAGE, FFSSetInformation)
#pragma alloc_text(PAGE, FFSExpandFile)
#pragma alloc_text(PAGE, FFSTruncateFile)
#pragma alloc_text(PAGE, FFSSetDispositionInfo)
#pragma alloc_text(PAGE, FFSSetRenameInfo)
#pragma alloc_text(PAGE, FFSDeleteFile)
#endif
__drv_mustHoldCriticalRegion
NTSTATUS
FFSQueryInformation(
IN PFFS_IRP_CONTEXT IrpContext)
{
PDEVICE_OBJECT DeviceObject;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PFILE_OBJECT FileObject;
PFFS_VCB Vcb;
PFFS_FCB Fcb = 0;
PFFS_CCB Ccb;
PIRP Irp;
PIO_STACK_LOCATION IoStackLocation;
FILE_INFORMATION_CLASS FileInformationClass;
ULONG Length;
PVOID Buffer;
BOOLEAN FcbResourceAcquired = FALSE;
PAGED_CODE();
_SEH2_TRY
{
ASSERT(IrpContext != NULL);
ASSERT((IrpContext->Identifier.Type == FFSICX) &&
(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject;
//
// This request is not allowed on the main device object
//
if (DeviceObject == FFSGlobal->DeviceObject)
{
Status = STATUS_INVALID_DEVICE_REQUEST;
_SEH2_LEAVE;
}
FileObject = IrpContext->FileObject;
Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL);
Fcb = (PFFS_FCB)FileObject->FsContext;
ASSERT(Fcb != NULL);
//
// This request is not allowed on volumes
//
if (Fcb->Identifier.Type == FFSVCB)
{
Status = STATUS_INVALID_PARAMETER;
_SEH2_LEAVE;
}
ASSERT((Fcb->Identifier.Type == FFSFCB) &&
(Fcb->Identifier.Size == sizeof(FFS_FCB)));
/*
if (!IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY) &&
!FlagOn(Fcb->Flags, FCB_PAGE_FILE))
*/
{
if (!ExAcquireResourceSharedLite(
&Fcb->MainResource,
IrpContext->IsSynchronous))
{
Status = STATUS_PENDING;
_SEH2_LEAVE;
}
FcbResourceAcquired = TRUE;
}
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.QueryFile.FileInformationClass;
Length = IoStackLocation->Parameters.QueryFile.Length;
Buffer = Irp->AssociatedIrp.SystemBuffer;
RtlZeroMemory(Buffer, Length);
switch (FileInformationClass)
{
case FileBasicInformation:
{
PFILE_BASIC_INFORMATION FileBasicInformation;
if (Length < sizeof(FILE_BASIC_INFORMATION))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
_SEH2_LEAVE;
}
FileBasicInformation = (PFILE_BASIC_INFORMATION)Buffer;
if (FS_VERSION == 1)
{
FileBasicInformation->CreationTime = FFSSysTime(Fcb->dinode1->di_ctime);
FileBasicInformation->LastAccessTime = FFSSysTime(Fcb->dinode1->di_atime);
FileBasicInformation->LastWriteTime = FFSSysTime(Fcb->dinode1->di_mtime);
FileBasicInformation->ChangeTime = FFSSysTime(Fcb->dinode1->di_mtime);
}
else
{
FileBasicInformation->CreationTime = FFSSysTime((ULONG)Fcb->dinode2->di_ctime);
FileBasicInformation->LastAccessTime = FFSSysTime((ULONG)Fcb->dinode2->di_atime);
FileBasicInformation->LastWriteTime = FFSSysTime((ULONG)Fcb->dinode2->di_mtime);
FileBasicInformation->ChangeTime = FFSSysTime((ULONG)Fcb->dinode2->di_mtime);
}
FileBasicInformation->FileAttributes = Fcb->FFSMcb->FileAttr;
Irp->IoStatus.Information = sizeof(FILE_BASIC_INFORMATION);
Status = STATUS_SUCCESS;
_SEH2_LEAVE;
}
#if (_WIN32_WINNT >= 0x0500)
case FileAttributeTagInformation:
{
PFILE_ATTRIBUTE_TAG_INFORMATION FATI;
if (Length < sizeof(FILE_ATTRIBUTE_TAG_INFORMATION))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
_SEH2_LEAVE;
}
FATI = (PFILE_ATTRIBUTE_TAG_INFORMATION) Buffer;
FATI->FileAttributes = Fcb->FFSMcb->FileAttr;
FATI->ReparseTag = 0;
Irp->IoStatus.Information = sizeof(FILE_ATTRIBUTE_TAG_INFORMATION);
Status = STATUS_SUCCESS;
_SEH2_LEAVE;
}
#endif // (_WIN32_WINNT >= 0x0500)
case FileStandardInformation:
{
PFILE_STANDARD_INFORMATION FileStandardInformation;
if (Length < sizeof(FILE_STANDARD_INFORMATION))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
_SEH2_LEAVE;
}
FileStandardInformation = (PFILE_STANDARD_INFORMATION)Buffer;
if (FS_VERSION == 1)
{
FileStandardInformation->AllocationSize.QuadPart =
(LONGLONG)(Fcb->dinode1->di_size);
FileStandardInformation->EndOfFile.QuadPart =
(LONGLONG)(Fcb->dinode1->di_size);
FileStandardInformation->NumberOfLinks = Fcb->dinode1->di_nlink;
}
else
{
FileStandardInformation->AllocationSize.QuadPart =
(LONGLONG)(Fcb->dinode2->di_size);
FileStandardInformation->EndOfFile.QuadPart =
(LONGLONG)(Fcb->dinode2->di_size);
FileStandardInformation->NumberOfLinks = Fcb->dinode2->di_nlink;
}
if (IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY))
FileStandardInformation->DeletePending = FALSE;
else
FileStandardInformation->DeletePending = IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING);
if (Fcb->FFSMcb->FileAttr & FILE_ATTRIBUTE_DIRECTORY)
{
FileStandardInformation->Directory = TRUE;
}
else
{
FileStandardInformation->Directory = FALSE;
}
Irp->IoStatus.Information = sizeof(FILE_STANDARD_INFORMATION);
Status = STATUS_SUCCESS;
_SEH2_LEAVE;
}
case FileInternalInformation:
{
PFILE_INTERNAL_INFORMATION FileInternalInformation;
if (Length < sizeof(FILE_INTERNAL_INFORMATION))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
_SEH2_LEAVE;
}
FileInternalInformation = (PFILE_INTERNAL_INFORMATION)Buffer;
// The "inode number"
FileInternalInformation->IndexNumber.QuadPart = (LONGLONG)Fcb->FFSMcb->Inode;
Irp->IoStatus.Information = sizeof(FILE_INTERNAL_INFORMATION);
Status = STATUS_SUCCESS;
_SEH2_LEAVE;
}
case FileEaInformation:
{
PFILE_EA_INFORMATION FileEaInformation;
if (Length < sizeof(FILE_EA_INFORMATION))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
_SEH2_LEAVE;
}
FileEaInformation = (PFILE_EA_INFORMATION)Buffer;
// Romfs doesn't have any extended attributes
FileEaInformation->EaSize = 0;
Irp->IoStatus.Information = sizeof(FILE_EA_INFORMATION);
Status = STATUS_SUCCESS;
_SEH2_LEAVE;
}
case FileNameInformation:
{
PFILE_NAME_INFORMATION FileNameInformation;
if (Length < sizeof(FILE_NAME_INFORMATION) +
Fcb->FFSMcb->ShortName.Length - sizeof(WCHAR))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
_SEH2_LEAVE;
}
FileNameInformation = (PFILE_NAME_INFORMATION)Buffer;
FileNameInformation->FileNameLength = Fcb->FFSMcb->ShortName.Length;
RtlCopyMemory(
FileNameInformation->FileName,
Fcb->FFSMcb->ShortName.Buffer,
Fcb->FFSMcb->ShortName.Length);
Irp->IoStatus.Information = sizeof(FILE_NAME_INFORMATION) +
Fcb->FFSMcb->ShortName.Length - sizeof(WCHAR);
Status = STATUS_SUCCESS;
_SEH2_LEAVE;
}
case FilePositionInformation:
{
PFILE_POSITION_INFORMATION FilePositionInformation;
if (Length < sizeof(FILE_POSITION_INFORMATION))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
_SEH2_LEAVE;
}
FilePositionInformation = (PFILE_POSITION_INFORMATION)Buffer;
FilePositionInformation->CurrentByteOffset =
FileObject->CurrentByteOffset;
Irp->IoStatus.Information = sizeof(FILE_POSITION_INFORMATION);
Status = STATUS_SUCCESS;
_SEH2_LEAVE;
}
case FileAllInformation:
{
PFILE_ALL_INFORMATION FileAllInformation;
PFILE_BASIC_INFORMATION FileBasicInformation;
PFILE_STANDARD_INFORMATION FileStandardInformation;
PFILE_INTERNAL_INFORMATION FileInternalInformation;
PFILE_EA_INFORMATION FileEaInformation;
PFILE_POSITION_INFORMATION FilePositionInformation;
PFILE_NAME_INFORMATION FileNameInformation;
if (Length < sizeof(FILE_ALL_INFORMATION))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
_SEH2_LEAVE;
}
FileAllInformation = (PFILE_ALL_INFORMATION)Buffer;
FileBasicInformation =
&FileAllInformation->BasicInformation;
FileStandardInformation =
&FileAllInformation->StandardInformation;
FileInternalInformation =
&FileAllInformation->InternalInformation;
FileEaInformation =
&FileAllInformation->EaInformation;
FilePositionInformation =
&FileAllInformation->PositionInformation;
FileNameInformation =
&FileAllInformation->NameInformation;
if (FS_VERSION == 1)
{
FileBasicInformation->CreationTime = FFSSysTime(Fcb->dinode1->di_ctime);
FileBasicInformation->LastAccessTime = FFSSysTime(Fcb->dinode1->di_atime);
FileBasicInformation->LastWriteTime = FFSSysTime(Fcb->dinode1->di_mtime);
FileBasicInformation->ChangeTime = FFSSysTime(Fcb->dinode1->di_mtime);
FileBasicInformation->FileAttributes = Fcb->FFSMcb->FileAttr;
FileStandardInformation->AllocationSize.QuadPart =
(LONGLONG)(Fcb->dinode1->di_size);
FileStandardInformation->EndOfFile.QuadPart =
(LONGLONG)(Fcb->dinode1->di_size);
FileStandardInformation->NumberOfLinks = Fcb->dinode1->di_nlink;
}
else
{
FileBasicInformation->CreationTime = FFSSysTime((ULONG)Fcb->dinode2->di_ctime);
FileBasicInformation->LastAccessTime = FFSSysTime((ULONG)Fcb->dinode2->di_atime);
FileBasicInformation->LastWriteTime = FFSSysTime((ULONG)Fcb->dinode2->di_mtime);
FileBasicInformation->ChangeTime = FFSSysTime((ULONG)Fcb->dinode2->di_mtime);
FileBasicInformation->FileAttributes = Fcb->FFSMcb->FileAttr;
FileStandardInformation->AllocationSize.QuadPart =
(LONGLONG)(Fcb->dinode2->di_size);
FileStandardInformation->EndOfFile.QuadPart =
(LONGLONG)(Fcb->dinode2->di_size);
FileStandardInformation->NumberOfLinks = Fcb->dinode2->di_nlink;
}
if (IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY))
FileStandardInformation->DeletePending = FALSE;
else
FileStandardInformation->DeletePending = IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING);
if (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
{
FileStandardInformation->Directory = TRUE;
}
else
{
FileStandardInformation->Directory = FALSE;
}
// The "inode number"
FileInternalInformation->IndexNumber.QuadPart = (LONGLONG)Fcb->FFSMcb->Inode;
// Romfs doesn't have any extended attributes
FileEaInformation->EaSize = 0;
FilePositionInformation->CurrentByteOffset =
FileObject->CurrentByteOffset;
if (Length < sizeof(FILE_ALL_INFORMATION) +
Fcb->FFSMcb->ShortName.Length - sizeof(WCHAR))
{
Irp->IoStatus.Information = sizeof(FILE_ALL_INFORMATION);
Status = STATUS_BUFFER_OVERFLOW;
_SEH2_LEAVE;
}
FileNameInformation->FileNameLength = Fcb->FFSMcb->ShortName.Length;
RtlCopyMemory(
FileNameInformation->FileName,
Fcb->FFSMcb->ShortName.Buffer,
Fcb->FFSMcb->ShortName.Length);
Irp->IoStatus.Information = sizeof(FILE_ALL_INFORMATION) +
Fcb->FFSMcb->ShortName.Length - sizeof(WCHAR);
Status = STATUS_SUCCESS;
_SEH2_LEAVE;
}
/*
case FileAlternateNameInformation:
{
// TODO: Handle FileAlternateNameInformation
// Here we would like to use RtlGenerate8dot3Name but I don't
// know how to use the argument PGENERATE_NAME_CONTEXT
}
*/
case FileNetworkOpenInformation:
{
PFILE_NETWORK_OPEN_INFORMATION FileNetworkOpenInformation;
if (Length < sizeof(FILE_NETWORK_OPEN_INFORMATION))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
_SEH2_LEAVE;
}
FileNetworkOpenInformation =
(PFILE_NETWORK_OPEN_INFORMATION)Buffer;
if (FS_VERSION == 1)
{
FileNetworkOpenInformation->CreationTime = FFSSysTime(Fcb->dinode1->di_ctime);
FileNetworkOpenInformation->LastAccessTime = FFSSysTime(Fcb->dinode1->di_atime);
FileNetworkOpenInformation->LastWriteTime = FFSSysTime(Fcb->dinode1->di_mtime);
FileNetworkOpenInformation->ChangeTime = FFSSysTime(Fcb->dinode1->di_mtime);
FileNetworkOpenInformation->AllocationSize.QuadPart =
(LONGLONG)(Fcb->dinode1->di_size);
FileNetworkOpenInformation->EndOfFile.QuadPart =
(LONGLONG)(Fcb->dinode1->di_size);
}
else
{
FileNetworkOpenInformation->CreationTime = FFSSysTime((ULONG)Fcb->dinode2->di_ctime);
FileNetworkOpenInformation->LastAccessTime = FFSSysTime((ULONG)Fcb->dinode2->di_atime);
FileNetworkOpenInformation->LastWriteTime = FFSSysTime((ULONG)Fcb->dinode2->di_mtime);
FileNetworkOpenInformation->ChangeTime = FFSSysTime((ULONG)Fcb->dinode2->di_mtime);
FileNetworkOpenInformation->AllocationSize.QuadPart =
(LONGLONG)(Fcb->dinode2->di_size);
FileNetworkOpenInformation->EndOfFile.QuadPart =
(LONGLONG)(Fcb->dinode2->di_size);
}
FileNetworkOpenInformation->FileAttributes =
Fcb->FFSMcb->FileAttr;
Irp->IoStatus.Information =
sizeof(FILE_NETWORK_OPEN_INFORMATION);
Status = STATUS_SUCCESS;
_SEH2_LEAVE;
}
default:
Status = STATUS_INVALID_INFO_CLASS;
}
}
_SEH2_FINALLY
{
if (FcbResourceAcquired)
{
ExReleaseResourceForThreadLite(
&Fcb->MainResource,
ExGetCurrentResourceThread());
}
if (!IrpContext->ExceptionInProgress)
{
if (Status == STATUS_PENDING)
{
FFSQueueRequest(IrpContext);
}
else
{
FFSCompleteIrpContext(IrpContext, Status);
}
}
} _SEH2_END;
return Status;
}
__drv_mustHoldCriticalRegion
NTSTATUS
FFSSetInformation(
IN PFFS_IRP_CONTEXT IrpContext)
{
PDEVICE_OBJECT DeviceObject;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PFFS_VCB Vcb = 0;
PFILE_OBJECT FileObject;
PFFS_FCB Fcb = 0;
PFFS_CCB Ccb;
PIRP Irp;
PIO_STACK_LOCATION IoStackLocation;
FILE_INFORMATION_CLASS FileInformationClass;
ULONG NotifyFilter = 0;
ULONG Length;
PVOID Buffer;
BOOLEAN FcbMainResourceAcquired = FALSE;
BOOLEAN VcbResourceAcquired = FALSE;
BOOLEAN FcbPagingIoResourceAcquired = FALSE;
PAGED_CODE();
_SEH2_TRY
{
ASSERT(IrpContext != NULL);
ASSERT((IrpContext->Identifier.Type == FFSICX) &&
(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject;
//
// This request is not allowed on the main device object
//
if (DeviceObject == FFSGlobal->DeviceObject)
{
Status = STATUS_INVALID_DEVICE_REQUEST;
_SEH2_LEAVE;
}
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;
_SEH2_LEAVE;
}
ASSERT((Fcb->Identifier.Type == FFSFCB) &&
(Fcb->Identifier.Size == sizeof(FFS_FCB)));
if (IsFlagOn(Fcb->Flags, FCB_FILE_DELETED))
{
Status = STATUS_FILE_DELETED;
_SEH2_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)
{
#ifdef _MSC_VER
#pragma prefast( suppress: 28137, "by design" )
#endif
if (!ExAcquireResourceExclusiveLite(
&Vcb->MainResource,
IrpContext->IsSynchronous))
{
Status = STATUS_PENDING;
_SEH2_LEAVE;
}
VcbResourceAcquired = TRUE;
}
}
else if (!FlagOn(Fcb->Flags, FCB_PAGE_FILE))
{
#ifdef _MSC_VER
#pragma prefast( suppress: 28137, "by design" )
#endif
if (!ExAcquireResourceExclusiveLite(
&Fcb->MainResource,
IrpContext->IsSynchronous))
{
Status = STATUS_PENDING;
_SEH2_LEAVE;
}
FcbMainResourceAcquired = TRUE;
}
if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY))
{
if (FileInformationClass != FilePositionInformation)
{
Status = STATUS_MEDIA_WRITE_PROTECTED;
_SEH2_LEAVE;
}
}
if (FileInformationClass == FileDispositionInformation ||
FileInformationClass == FileRenameInformation ||
FileInformationClass == FileLinkInformation ||
FileInformationClass == FileAllocationInformation ||
FileInformationClass == FileEndOfFileInformation)
{
#ifdef _MSC_VER
#pragma prefast( suppress: 28137, "by design" )
#endif
if (!ExAcquireResourceExclusiveLite(
&Fcb->PagingIoResource,
IrpContext->IsSynchronous))
{
Status = STATUS_PENDING;
_SEH2_LEAVE;
}
FcbPagingIoResourceAcquired = TRUE;
}
/*
if (FileInformationClass != FileDispositionInformation
&& FlagOn(Fcb->Flags, FCB_DELETE_PENDING))
{
Status = STATUS_DELETE_PENDING;
_SEH2_LEAVE;
}
*/
switch (FileInformationClass)
{
#if !FFS_READ_ONLY
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;
_SEH2_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;
_SEH2_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;
_SEH2_LEAVE;
}
if (FEOFI->EndOfFile.HighPart != 0)
{
Status = STATUS_INVALID_PARAMETER;
_SEH2_LEAVE;
}
if (IoStackLocation->Parameters.SetFile.AdvanceOnly)
{
Status = STATUS_SUCCESS;
_SEH2_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;
_SEH2_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;
#endif // !FFS_READ_ONLY
//
// 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;
_SEH2_LEAVE;
}
FilePositionInformation = (PFILE_POSITION_INFORMATION) Buffer;
if ((FlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING)) &&
(FilePositionInformation->CurrentByteOffset.LowPart &
DeviceObject->AlignmentRequirement))
{
Status = STATUS_INVALID_PARAMETER;
_SEH2_LEAVE;
}
FileObject->CurrentByteOffset =
FilePositionInformation->CurrentByteOffset;
Status = STATUS_SUCCESS;
_SEH2_LEAVE;
}
break;
default:
Status = STATUS_INVALID_INFO_CLASS;
}
}
_SEH2_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);
}
}
} _SEH2_END;
return Status;
}
#if !FFS_READ_ONLY
BOOLEAN
FFSExpandFile(
PFFS_IRP_CONTEXT IrpContext,
PFFS_VCB Vcb,
PFFS_FCB Fcb,
PLARGE_INTEGER AllocationSize)
{
ULONG dwRet = 0;
BOOLEAN bRet = TRUE;
PAGED_CODE();
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)
{
BOOLEAN bRet = TRUE;
PAGED_CODE();
while (bRet && (AllocationSize->QuadPart <
Fcb->Header.AllocationSize.QuadPart))
{
bRet = FFSTruncateInode(IrpContext, Vcb, Fcb);
}
return bRet;
}
NTSTATUS
FFSSetDispositionInfo(
PFFS_IRP_CONTEXT IrpContext,
PFFS_VCB Vcb,
PFFS_FCB Fcb,
BOOLEAN bDelete)
{
PIRP Irp = IrpContext->Irp;
PIO_STACK_LOCATION IrpSp;
PAGED_CODE();
IrpSp = IoGetCurrentIrpStackLocation(Irp);
FFSPrint((DBG_INFO, "FFSSetDispositionInfo: bDelete=%x\n", bDelete));
if (bDelete)
{
FFSPrint((DBG_INFO, "FFSSetDispositionInformation: MmFlushImageSection on %s.\n",
Fcb->AnsiFileName.Buffer));
if (!MmFlushImageSection(&Fcb->SectionObject,
MmFlushForDelete))
{
return STATUS_CANNOT_DELETE;
}
if (Fcb->FFSMcb->Inode == FFS_ROOT_INO)
{
return STATUS_CANNOT_DELETE;
}
if (IsDirectory(Fcb))
{
if (!FFSIsDirectoryEmpty(Vcb, Fcb))
{
return STATUS_DIRECTORY_NOT_EMPTY;
}
}
SetFlag(Fcb->Flags, FCB_DELETE_PENDING);
IrpSp->FileObject->DeletePending = TRUE;
if (IsDirectory(Fcb))
{
FsRtlNotifyFullChangeDirectory(Vcb->NotifySync,
&Vcb->NotifyList,
Fcb,
NULL,
FALSE,
FALSE,
0,
NULL,
NULL,
NULL);
}
}
else
{
ClearFlag(Fcb->Flags, FCB_DELETE_PENDING);
IrpSp->FileObject->DeletePending = FALSE;
}
return STATUS_SUCCESS;
}
__drv_mustHoldCriticalRegion
NTSTATUS
FFSSetRenameInfo(
PFFS_IRP_CONTEXT IrpContext,
PFFS_VCB Vcb,
PFFS_FCB Fcb)
{
PFFS_FCB TargetDcb;
PFFS_MCB TargetMcb;
PFFS_MCB Mcb;
FFSv1_INODE dinode1;
UNICODE_STRING FileName;
NTSTATUS Status;
PIRP Irp;
PIO_STACK_LOCATION IrpSp;
PFILE_OBJECT FileObject;
PFILE_OBJECT TargetObject;
BOOLEAN ReplaceIfExists;
BOOLEAN bMove = FALSE;
PFILE_RENAME_INFORMATION FRI;
PAGED_CODE();
if (Fcb->FFSMcb->Inode == FFS_ROOT_INO)
{
Status = STATUS_INVALID_PARAMETER;
goto errorout;
}
Irp = IrpContext->Irp;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
FileObject = IrpSp->FileObject;
TargetObject = IrpSp->Parameters.SetFile.FileObject;
ReplaceIfExists = IrpSp->Parameters.SetFile.ReplaceIfExists;
FRI = (PFILE_RENAME_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
if (TargetObject == NULL)
{
UNICODE_STRING NewName;
NewName.Buffer = FRI->FileName;
NewName.MaximumLength = NewName.Length = (USHORT)FRI->FileNameLength;
while (NewName.Length > 0 && NewName.Buffer[NewName.Length / 2 - 1] == L'\\')
{
NewName.Buffer[NewName.Length / 2 - 1] = 0;
NewName.Length -= 2;
}
while (NewName.Length > 0 && NewName.Buffer[NewName.Length / 2 - 1] != L'\\')
{
NewName.Length -= 2;
}
NewName.Buffer = (USHORT *)((UCHAR *)NewName.Buffer + NewName.Length);
NewName.Length = (USHORT)(FRI->FileNameLength - NewName.Length);
FileName = NewName;
TargetDcb = NULL;
TargetMcb = Fcb->FFSMcb->Parent;
if (FileName.Length >= FFS_NAME_LEN*sizeof(USHORT))
{
Status = STATUS_OBJECT_NAME_INVALID;
goto errorout;
}
}
else
{
TargetDcb = (PFFS_FCB)(TargetObject->FsContext);
if (!TargetDcb || TargetDcb->Vcb != Vcb)
{
FFSBreakPoint();
Status = STATUS_INVALID_PARAMETER;
goto errorout;
}
TargetMcb = TargetDcb->FFSMcb;
FileName = TargetObject->FileName;
}
if (FsRtlDoesNameContainWildCards(&FileName))
{
Status = STATUS_OBJECT_NAME_INVALID;
goto errorout;
}
if (TargetMcb->Inode == Fcb->FFSMcb->Parent->Inode)
{
if (FsRtlAreNamesEqual(&FileName,
&(Fcb->FFSMcb->ShortName),
FALSE,
NULL))
{
Status = STATUS_SUCCESS;
goto errorout;
}
}
else
{
bMove = TRUE;
}
TargetDcb = TargetMcb->FFSFcb;
if (!TargetDcb)
TargetDcb = FFSCreateFcbFromMcb(Vcb, TargetMcb);
if ((TargetMcb->Inode != Fcb->FFSMcb->Parent->Inode) &&
(Fcb->FFSMcb->Parent->FFSFcb == NULL))
{
FFSCreateFcbFromMcb(Vcb, Fcb->FFSMcb->Parent);
}
if (!TargetDcb || !(Fcb->FFSMcb->Parent->FFSFcb))
{
Status = STATUS_UNSUCCESSFUL;
goto errorout;
}
Mcb = NULL;
Status = FFSv1LookupFileName(
Vcb,
&FileName,
TargetMcb,
&Mcb,
&dinode1);
if (NT_SUCCESS(Status))
{
if ((!ReplaceIfExists) ||
(IsFlagOn(Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) ||
(IsFlagOn(Mcb->FileAttr, FILE_ATTRIBUTE_READONLY)))
{
Status = STATUS_OBJECT_NAME_COLLISION;
goto errorout;
}
if (ReplaceIfExists)
{
Status = STATUS_NOT_IMPLEMENTED;
goto errorout;
}
}
if (IsDirectory(Fcb))
{
Status = FFSRemoveEntry(IrpContext, Vcb,
Fcb->FFSMcb->Parent->FFSFcb,
DT_DIR,
Fcb->FFSMcb->Inode);
if (!NT_SUCCESS(Status))
{
FFSBreakPoint();
goto errorout;
}
Status = FFSAddEntry(IrpContext, Vcb,
TargetDcb,
DT_DIR,
Fcb->FFSMcb->Inode,
&FileName);
if (!NT_SUCCESS(Status))
{
FFSBreakPoint();
FFSAddEntry(IrpContext, Vcb,
Fcb->FFSMcb->Parent->FFSFcb,
DT_DIR,
Fcb->FFSMcb->Inode,
&Fcb->FFSMcb->ShortName);
goto errorout;
}
if(!FFSv1SaveInode(IrpContext,
Vcb,
TargetMcb->Inode,
TargetDcb->dinode1))
{
Status = STATUS_UNSUCCESSFUL;
FFSBreakPoint();
goto errorout;
}
if(!FFSv1SaveInode(IrpContext,
Vcb,
Fcb->FFSMcb->Parent->Inode,
Fcb->FFSMcb->Parent->FFSFcb->dinode1))
{
Status = STATUS_UNSUCCESSFUL;
FFSBreakPoint();
goto errorout;
}
Status = FFSSetParentEntry(IrpContext, Vcb, Fcb,
Fcb->FFSMcb->Parent->Inode,
TargetDcb->FFSMcb->Inode);
if (!NT_SUCCESS(Status))
{
FFSBreakPoint();
goto errorout;
}
}
else
{
Status = FFSRemoveEntry(IrpContext, Vcb,
Fcb->FFSMcb->Parent->FFSFcb,
DT_REG,
Fcb->FFSMcb->Inode);
if (!NT_SUCCESS(Status))
{
FFSBreakPoint();
goto errorout;
}
Status = FFSAddEntry(IrpContext,
Vcb, TargetDcb,
DT_REG,
Fcb->FFSMcb->Inode,
&FileName);
if (!NT_SUCCESS(Status))
{
FFSBreakPoint();
FFSAddEntry(IrpContext, Vcb,
Fcb->FFSMcb->Parent->FFSFcb,
DT_REG,
Fcb->FFSMcb->Inode,
&Fcb->FFSMcb->ShortName);
goto errorout;
}
}
if (NT_SUCCESS(Status))
{
if (Fcb->FFSMcb->ShortName.MaximumLength < (FileName.Length + 2))
{
ExFreePool(Fcb->FFSMcb->ShortName.Buffer);
Fcb->FFSMcb->ShortName.Buffer =
ExAllocatePoolWithTag(PagedPool, FileName.Length + 2, FFS_POOL_TAG);
if (!Fcb->FFSMcb->ShortName.Buffer)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto errorout;
}
Fcb->FFSMcb->ShortName.MaximumLength = FileName.Length + 2;
}
{
RtlZeroMemory(Fcb->FFSMcb->ShortName.Buffer,
Fcb->FFSMcb->ShortName.MaximumLength);
RtlCopyMemory(Fcb->FFSMcb->ShortName.Buffer,
FileName.Buffer, FileName.Length);
Fcb->FFSMcb->ShortName.Length = FileName.Length;
}
#if DBG
Fcb->AnsiFileName.Length = (USHORT)
RtlxUnicodeStringToOemSize(&FileName);
if (Fcb->AnsiFileName.MaximumLength < FileName.Length)
{
ExFreePool(Fcb->AnsiFileName.Buffer);
Fcb->AnsiFileName.Buffer =
ExAllocatePoolWithTag(PagedPool, Fcb->AnsiFileName.Length + 1, FFS_POOL_TAG);
if (!Fcb->AnsiFileName.Buffer)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto errorout;
}
RtlZeroMemory(Fcb->AnsiFileName.Buffer,
Fcb->AnsiFileName.Length + 1);
Fcb->AnsiFileName.MaximumLength =
Fcb->AnsiFileName.Length + 1;
}
FFSUnicodeToOEM(&(Fcb->AnsiFileName),
&FileName);
#endif
if (bMove)
{
FFSNotifyReportChange(
IrpContext,
Vcb,
Fcb,
(IsDirectory(Fcb) ?
FILE_NOTIFY_CHANGE_DIR_NAME :
FILE_NOTIFY_CHANGE_FILE_NAME),
FILE_ACTION_REMOVED);
}
else
{
FFSNotifyReportChange(
IrpContext,
Vcb,
Fcb,
(IsDirectory(Fcb) ?
FILE_NOTIFY_CHANGE_DIR_NAME :
FILE_NOTIFY_CHANGE_FILE_NAME),
FILE_ACTION_RENAMED_OLD_NAME);
}
FFSDeleteMcbNode(Vcb, Fcb->FFSMcb->Parent, Fcb->FFSMcb);
FFSAddMcbNode(Vcb, TargetMcb, Fcb->FFSMcb);
if (bMove)
{
FFSNotifyReportChange(
IrpContext,
Vcb,
Fcb,
(IsDirectory(Fcb) ?
FILE_NOTIFY_CHANGE_DIR_NAME :
FILE_NOTIFY_CHANGE_FILE_NAME),
FILE_ACTION_ADDED);
}
else
{
FFSNotifyReportChange(
IrpContext,
Vcb,
Fcb,
(IsDirectory(Fcb) ?
FILE_NOTIFY_CHANGE_DIR_NAME :
FILE_NOTIFY_CHANGE_FILE_NAME),
FILE_ACTION_RENAMED_NEW_NAME);
}
}
errorout:
return Status;
}
__drv_mustHoldCriticalRegion
BOOLEAN
FFSDeleteFile(
PFFS_IRP_CONTEXT IrpContext,
PFFS_VCB Vcb,
PFFS_FCB Fcb)
{
BOOLEAN bRet = FALSE;
LARGE_INTEGER AllocationSize;
PFFS_FCB Dcb = NULL;
NTSTATUS Status;
PAGED_CODE();
FFSPrint((DBG_INFO, "FFSDeleteFile: File %S (%xh) will be deleted!\n",
Fcb->FFSMcb->ShortName.Buffer, Fcb->FFSMcb->Inode));
if (IsFlagOn(Fcb->Flags, FCB_FILE_DELETED))
{
return TRUE;
}
if (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
{
if (!FFSIsDirectoryEmpty(Vcb, Fcb))
{
ClearFlag(Fcb->Flags, FCB_DELETE_PENDING);
return FALSE;
}
}
FFSPrint((DBG_INFO, "FFSDeleteFile: FFSSB->S_FREE_BLOCKS = %xh .\n",
Vcb->ffs_super_block->fs_size - Vcb->ffs_super_block->fs_dsize));
Status = STATUS_UNSUCCESSFUL;
{
if (Fcb->FFSMcb->Parent->FFSFcb)
{
Status = FFSRemoveEntry(
IrpContext, Vcb,
Fcb->FFSMcb->Parent->FFSFcb,
(FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY) ?
DT_DIR : DT_REG),
Fcb->FFSMcb->Inode);
}
else
{
Dcb = FFSCreateFcbFromMcb(Vcb, Fcb->FFSMcb->Parent);
if (Dcb)
{
Status = FFSRemoveEntry(
IrpContext, Vcb, Dcb,
(FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY) ?
DT_DIR : DT_REG),
Fcb->FFSMcb->Inode);
}
}
}
if (NT_SUCCESS(Status))
{
Fcb->dinode1->di_nlink--;
if (IsDirectory(Fcb))
{
if (Fcb->dinode1->di_nlink < 2)
{
bRet = TRUE;
}
}
else
{
if (Fcb->dinode1->di_nlink == 0)
{
bRet = TRUE;
}
}
}
if (bRet)
{
AllocationSize.QuadPart = (LONGLONG)0;
bRet = FFSTruncateFile(IrpContext, Vcb, Fcb, &AllocationSize);
//
// Update the inode's data length . It should be ZERO if succeeds.
//
if (Fcb->dinode1->di_size > Fcb->Header.AllocationSize.LowPart)
{
Fcb->dinode1->di_size = Fcb->Header.AllocationSize.LowPart;
}
Fcb->Header.FileSize.QuadPart = (LONGLONG) Fcb->dinode1->di_size;
if (bRet)
{
{
LARGE_INTEGER SysTime;
KeQuerySystemTime(&SysTime);
/*Fcb->dinode->di_dtime = FFSInodeTime(SysTime); XXX */
FFSv1SaveInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, Fcb->dinode1);
}
if (IsDirectory(Fcb))
{
bRet = FFSFreeInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, DT_DIR);
}
else
{
bRet = FFSFreeInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, DT_REG);
}
SetFlag(Fcb->Flags, FCB_FILE_DELETED);
FFSDeleteMcbNode(Vcb, Fcb->FFSMcb->Parent, Fcb->FFSMcb);
}
else
{
FFSv1SaveInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, Fcb->dinode1);
}
}
else
{
FFSv1SaveInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, Fcb->dinode1);
}
FFSPrint((DBG_INFO, "FFSDeleteFile: Succeed... FFSSB->S_FREE_BLOCKS = %xh .\n",
Vcb->ffs_super_block->fs_size - Vcb->ffs_super_block->fs_dsize));
return bRet;
}
#endif // !FFS_READ_ONLY