--- /dev/null
+/*
+ * COPYRIGHT: GNU GENERAL PUBLIC LICENSE VERSION 2
+ * PROJECT: ReiserFs file system driver for Windows NT/2000/XP/Vista.
+ * FILE: fileinfo.c
+ * PURPOSE:
+ * PROGRAMMER: Mark Piper, Matt Wu, Bo Brantén.
+ * HOMEPAGE:
+ * UPDATE HISTORY:
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include "rfsd.h"
+
+/* GLOBALS ***************************************************************/
+
+extern PRFSD_GLOBAL RfsdGlobal;
+
+/* DEFINITIONS *************************************************************/
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, RfsdQueryInformation)
+#pragma alloc_text(PAGE, RfsdSetInformation)
+#if !RFSD_READ_ONLY
+#pragma alloc_text(PAGE, RfsdExpandFile)
+#pragma alloc_text(PAGE, RfsdTruncateFile)
+#pragma alloc_text(PAGE, RfsdSetDispositionInfo)
+#pragma alloc_text(PAGE, RfsdSetRenameInfo)
+#pragma alloc_text(PAGE, RfsdDeleteFile)
+#endif // !RFSD_READ_ONLY
+#endif
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+RfsdQueryInformation (IN PRFSD_IRP_CONTEXT IrpContext)
+{
+ PDEVICE_OBJECT DeviceObject;
+ NTSTATUS Status = STATUS_UNSUCCESSFUL;
+ PFILE_OBJECT FileObject;
+ PRFSD_VCB Vcb;
+ PRFSD_FCB Fcb = 0;
+ PRFSD_CCB Ccb;
+ PIRP Irp;
+ PIO_STACK_LOCATION IoStackLocation;
+ FILE_INFORMATION_CLASS FileInformationClass;
+ ULONG Length;
+ PVOID Buffer;
+ BOOLEAN FcbResourceAcquired = FALSE;
+ LONGLONG FileSize;
+ LONGLONG AllocationSize;
+
+ PAGED_CODE();
+
+ _SEH2_TRY {
+
+ ASSERT(IrpContext != NULL);
+
+ ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
+ (IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));
+
+ DeviceObject = IrpContext->DeviceObject;
+
+ //
+ // This request is not allowed on the main device object
+ //
+ if (DeviceObject == RfsdGlobal->DeviceObject) {
+ Status = STATUS_INVALID_DEVICE_REQUEST;
+ _SEH2_LEAVE;
+ }
+
+ FileObject = IrpContext->FileObject;
+
+ Fcb = (PRFSD_FCB) FileObject->FsContext;
+
+ ASSERT(Fcb != NULL);
+
+ //
+ // This request is not allowed on volumes
+ //
+ if (Fcb->Identifier.Type == RFSDVCB) {
+ Status = STATUS_INVALID_PARAMETER;
+ _SEH2_LEAVE;
+ }
+
+ ASSERT((Fcb->Identifier.Type == RFSDFCB) &&
+ (Fcb->Identifier.Size == sizeof(RFSD_FCB)));
+
+ Vcb = Fcb->Vcb;
+
+/*
+ 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 = (PRFSD_CCB) FileObject->FsContext2;
+
+ ASSERT(Ccb != NULL);
+
+ ASSERT((Ccb->Identifier.Type == RFSDCCB) &&
+ (Ccb->Identifier.Size == sizeof(RFSD_CCB)));
+
+ Irp = IrpContext->Irp;
+
+ IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+ FileInformationClass =
+ IoStackLocation->Parameters.QueryFile.FileInformationClass;
+
+ Length = IoStackLocation->Parameters.QueryFile.Length;
+
+ Buffer = Irp->AssociatedIrp.SystemBuffer;
+
+ RtlZeroMemory(Buffer, Length);
+
+ FileSize = (LONGLONG) Fcb->Inode->i_size;
+
+ AllocationSize = CEILING_ALIGNED(FileSize, (ULONGLONG)Vcb->BlockSize);
+
+ 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;
+
+ FileBasicInformation->CreationTime = RfsdSysTime(Fcb->Inode->i_ctime);
+
+ FileBasicInformation->LastAccessTime = RfsdSysTime(Fcb->Inode->i_atime);
+
+ FileBasicInformation->LastWriteTime = RfsdSysTime(Fcb->Inode->i_mtime);
+
+ FileBasicInformation->ChangeTime = RfsdSysTime(Fcb->Inode->i_mtime);
+
+ FileBasicInformation->FileAttributes = Fcb->RfsdMcb->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->RfsdMcb->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;
+
+ FileStandardInformation->AllocationSize.QuadPart = AllocationSize;
+ FileStandardInformation->EndOfFile.QuadPart = FileSize;
+
+ FileStandardInformation->NumberOfLinks = Fcb->Inode->i_links_count;
+
+ if (IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY))
+ FileStandardInformation->DeletePending = FALSE;
+ else
+ FileStandardInformation->DeletePending = IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING);
+
+ if (Fcb->RfsdMcb->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.LowPart = Fcb->RfsdMcb->Key.k_dir_id;
+ FileInternalInformation->IndexNumber.HighPart = Fcb->RfsdMcb->Key.k_objectid;
+
+ 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->RfsdMcb->ShortName.Length - sizeof(WCHAR)) {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ _SEH2_LEAVE;
+ }
+
+ FileNameInformation = (PFILE_NAME_INFORMATION) Buffer;
+
+ FileNameInformation->FileNameLength = Fcb->RfsdMcb->ShortName.Length;
+
+ RtlCopyMemory(
+ FileNameInformation->FileName,
+ Fcb->RfsdMcb->ShortName.Buffer,
+ Fcb->RfsdMcb->ShortName.Length );
+
+ Irp->IoStatus.Information = sizeof(FILE_NAME_INFORMATION) +
+ Fcb->RfsdMcb->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;
+
+ FileBasicInformation->CreationTime = RfsdSysTime(Fcb->Inode->i_ctime);
+
+ FileBasicInformation->LastAccessTime = RfsdSysTime(Fcb->Inode->i_atime);
+
+ FileBasicInformation->LastWriteTime = RfsdSysTime(Fcb->Inode->i_mtime);
+
+ FileBasicInformation->ChangeTime = RfsdSysTime(Fcb->Inode->i_mtime);
+
+ FileBasicInformation->FileAttributes = Fcb->RfsdMcb->FileAttr;
+
+ FileStandardInformation->AllocationSize.QuadPart = AllocationSize;
+
+ FileStandardInformation->EndOfFile.QuadPart = FileSize;
+
+ FileStandardInformation->NumberOfLinks = Fcb->Inode->i_links_count;
+
+ if (IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY))
+ FileStandardInformation->DeletePending = FALSE;
+ else
+ FileStandardInformation->DeletePending = IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING);
+
+ if (FlagOn(Fcb->RfsdMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) {
+ FileStandardInformation->Directory = TRUE;
+ } else {
+ FileStandardInformation->Directory = FALSE;
+ }
+
+ // The "inode number"
+ FileInternalInformation->IndexNumber.LowPart = Fcb->RfsdMcb->Key.k_dir_id;
+ FileInternalInformation->IndexNumber.HighPart = Fcb->RfsdMcb->Key.k_objectid;
+
+ // Romfs doesn't have any extended attributes
+ FileEaInformation->EaSize = 0;
+
+ FilePositionInformation->CurrentByteOffset =
+ FileObject->CurrentByteOffset;
+
+ if (Length < sizeof(FILE_ALL_INFORMATION) +
+ Fcb->RfsdMcb->ShortName.Length - sizeof(WCHAR)) {
+ Irp->IoStatus.Information = sizeof(FILE_ALL_INFORMATION);
+ Status = STATUS_BUFFER_OVERFLOW;
+ _SEH2_LEAVE;
+ }
+
+ FileNameInformation->FileNameLength = Fcb->RfsdMcb->ShortName.Length;
+
+ RtlCopyMemory(
+ FileNameInformation->FileName,
+ Fcb->RfsdMcb->ShortName.Buffer,
+ Fcb->RfsdMcb->ShortName.Length
+ );
+
+ Irp->IoStatus.Information = sizeof(FILE_ALL_INFORMATION) +
+ Fcb->RfsdMcb->ShortName.Length - sizeof(WCHAR);
+ Status = STATUS_SUCCESS;
+ _SEH2_LEAVE;
+ }
+
+ /*
+ case FileAlternateNameInformation:
+ {
+ // TODO: [ext2fsd] 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;
+
+ FileNetworkOpenInformation->CreationTime = RfsdSysTime(Fcb->Inode->i_ctime);
+
+ FileNetworkOpenInformation->LastAccessTime = RfsdSysTime(Fcb->Inode->i_atime);
+
+ FileNetworkOpenInformation->LastWriteTime = RfsdSysTime(Fcb->Inode->i_mtime);
+
+ FileNetworkOpenInformation->ChangeTime = RfsdSysTime(Fcb->Inode->i_mtime);
+
+ FileNetworkOpenInformation->AllocationSize.QuadPart = AllocationSize;
+
+ FileNetworkOpenInformation->EndOfFile.QuadPart = FileSize;
+
+ FileNetworkOpenInformation->FileAttributes = Fcb->RfsdMcb->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) {
+ RfsdQueueRequest(IrpContext);
+ } else {
+ RfsdCompleteIrpContext(IrpContext, Status);
+ }
+ }
+ } _SEH2_END;
+
+ return Status;
+}
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+RfsdSetInformation (IN PRFSD_IRP_CONTEXT IrpContext)
+{
+ PDEVICE_OBJECT DeviceObject;
+ NTSTATUS Status = STATUS_UNSUCCESSFUL;
+ PRFSD_VCB Vcb = 0;
+ PFILE_OBJECT FileObject;
+ PRFSD_FCB Fcb = 0;
+ PRFSD_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 == RFSDICX) &&
+ (IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));
+
+ DeviceObject = IrpContext->DeviceObject;
+
+ //
+ // This request is not allowed on the main device object
+ //
+ if (DeviceObject == RfsdGlobal->DeviceObject) {
+ Status = STATUS_INVALID_DEVICE_REQUEST;
+ _SEH2_LEAVE;
+ }
+
+ Vcb = (PRFSD_VCB) DeviceObject->DeviceExtension;
+
+ ASSERT(Vcb != NULL);
+
+ ASSERT((Vcb->Identifier.Type == RFSDVCB) &&
+ (Vcb->Identifier.Size == sizeof(RFSD_VCB)));
+
+ ASSERT(IsMounted(Vcb));
+
+ FileObject = IrpContext->FileObject;
+
+ Fcb = (PRFSD_FCB) FileObject->FsContext;
+
+ ASSERT(Fcb != NULL);
+
+ //
+ // This request is not allowed on volumes
+ //
+ if (Fcb->Identifier.Type == RFSDVCB) {
+ DbgBreak();
+
+ Status = STATUS_INVALID_PARAMETER;
+ _SEH2_LEAVE;
+ }
+
+ ASSERT((Fcb->Identifier.Type == RFSDFCB) &&
+ (Fcb->Identifier.Size == sizeof(RFSD_FCB)));
+
+ if (IsFlagOn(Fcb->Flags, FCB_FILE_DELETED)) {
+ Status = STATUS_FILE_DELETED;
+ _SEH2_LEAVE;
+ }
+
+ Ccb = (PRFSD_CCB) FileObject->FsContext2;
+
+ ASSERT(Ccb != NULL);
+
+ ASSERT((Ccb->Identifier.Type == RFSDCCB) &&
+ (Ccb->Identifier.Size == sizeof(RFSD_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 !RFSD_READ_ONLY
+#if 0
+ case FileBasicInformation:
+ {
+ PFILE_BASIC_INFORMATION FBI = (PFILE_BASIC_INFORMATION) Buffer;
+ PRFSD_INODE RfsdInode = Fcb->Inode;
+
+ if (FBI->CreationTime.QuadPart) {
+ RfsdInode->i_ctime = (ULONG)(RfsdInodeTime(FBI->CreationTime));
+ }
+
+ if (FBI->LastAccessTime.QuadPart) {
+ RfsdInode->i_atime = (ULONG)(RfsdInodeTime(FBI->LastAccessTime));
+ }
+
+ if (FBI->LastWriteTime.QuadPart) {
+ RfsdInode->i_mtime = (ULONG)(RfsdInodeTime(FBI->LastWriteTime));
+ }
+
+ if (IsFlagOn(FBI->FileAttributes, FILE_ATTRIBUTE_READONLY)) {
+ RfsdSetReadOnly(Fcb->Inode->i_mode);
+ SetFlag(Fcb->RfsdMcb->FileAttr, FILE_ATTRIBUTE_READONLY);
+ } else {
+ RfsdSetWritable(Fcb->Inode->i_mode);
+ ClearFlag(Fcb->RfsdMcb->FileAttr, FILE_ATTRIBUTE_READONLY);
+ }
+
+ if(RfsdSaveInode(IrpContext, Vcb, Fcb->RfsdMcb->Inode, RfsdInode)) {
+ 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->RfsdMcb->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 ) {
+
+ Status = RfsdExpandFile(
+ IrpContext,
+ Vcb, Fcb,
+ &(FAI->AllocationSize));
+
+ if (NT_SUCCESS(Status)) {
+
+ RfsdSaveInode( IrpContext,
+ Vcb,
+ Fcb->RfsdMcb->Inode,
+ Fcb->Inode );
+ }
+
+ } else {
+
+ if (MmCanFileBeTruncated(&(Fcb->SectionObject), &(FAI->AllocationSize))) {
+
+ LARGE_INTEGER EndOfFile;
+
+ EndOfFile.QuadPart = FAI->AllocationSize.QuadPart +
+ (LONGLONG)(Vcb->BlockSize - 1);
+
+ Status = RfsdTruncateFile(IrpContext, Vcb, Fcb, &(EndOfFile));
+
+ if (NT_SUCCESS(Status)) {
+
+ if ( FAI->AllocationSize.QuadPart <
+ Fcb->Header.FileSize.QuadPart) {
+ Fcb->Header.FileSize.QuadPart =
+ FAI->AllocationSize.QuadPart;
+ }
+
+ RfsdSaveInode( IrpContext,
+ Vcb,
+ Fcb->RfsdMcb->Inode,
+ Fcb->Inode);
+ }
+
+ } 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,
+ &(RfsdGlobal->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;
+
+ Status = RfsdExpandFile(IrpContext, Vcb, Fcb, &(FEOFI->EndOfFile));
+
+ if (NT_SUCCESS(Status)) {
+
+ Fcb->Header.FileSize.QuadPart = FEOFI->EndOfFile.QuadPart;
+
+ Fcb->Inode->i_size = FEOFI->EndOfFile.QuadPart;
+
+ Fcb->Header.ValidDataLength.QuadPart =
+ (LONGLONG)(0x7fffffffffffffff);
+
+ RfsdSaveInode( IrpContext,
+ Vcb,
+ Fcb->RfsdMcb->Inode,
+ Fcb->Inode);
+
+
+ CcSetFileSizes(FileObject,
+ (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
+
+ SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
+
+ RfsdZeroHoles( 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);
+
+ Status = RfsdTruncateFile(IrpContext, Vcb, Fcb, &(EndOfFile));
+
+ if (NT_SUCCESS(Status)) {
+
+ Fcb->Header.FileSize.QuadPart = FEOFI->EndOfFile.QuadPart;
+ Fcb->Inode->i_size = FEOFI->EndOfFile.QuadPart;
+
+ RfsdSaveInode( IrpContext,
+ Vcb,
+ Fcb->RfsdMcb->Inode,
+ Fcb->Inode);
+
+ CcSetFileSizes(FileObject,
+ (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
+
+ SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
+
+ NotifyFilter = FILE_NOTIFY_CHANGE_SIZE |
+ FILE_NOTIFY_CHANGE_LAST_WRITE ;
+ }
+
+ } else {
+
+ Status = STATUS_USER_MAPPED_FILE;
+ _SEH2_LEAVE;
+ }
+ }
+ }
+
+ break;
+
+ case FileDispositionInformation:
+ {
+ PFILE_DISPOSITION_INFORMATION FDI = (PFILE_DISPOSITION_INFORMATION)Buffer;
+
+ Status = RfsdSetDispositionInfo(IrpContext, Vcb, Fcb, FDI->DeleteFile);
+ }
+
+ break;
+
+ case FileRenameInformation:
+ {
+ Status = RfsdSetRenameInfo(IrpContext, Vcb, Fcb);
+ }
+
+ break;
+#endif // 0
+#endif // !RFSD_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)) {
+ RfsdNotifyReportChange(
+ 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) {
+ RfsdQueueRequest(IrpContext);
+ } else {
+ RfsdCompleteIrpContext(IrpContext, Status);
+ }
+ }
+ } _SEH2_END;
+
+ return Status;
+}
+
+#if !RFSD_READ_ONLY
+
+NTSTATUS
+RfsdExpandFile( PRFSD_IRP_CONTEXT IrpContext,
+ PRFSD_VCB Vcb, PRFSD_FCB Fcb,
+ PLARGE_INTEGER AllocationSize)
+{
+ ULONG dwRet = 0;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ PAGED_CODE();
+
+ if (AllocationSize->QuadPart <= Fcb->Header.AllocationSize.QuadPart) {
+ return Status;
+ }
+
+ if (((LONGLONG)SUPER_BLOCK->s_free_blocks_count) * Vcb->BlockSize <=
+ (AllocationSize->QuadPart - Fcb->Header.AllocationSize.QuadPart) ) {
+ RfsdPrint((DBG_ERROR, "RfsdExpandFile: There is no enough disk space available.\n"));
+ return STATUS_DISK_FULL;
+ }
+
+ while (NT_SUCCESS(Status) && (AllocationSize->QuadPart > Fcb->Header.AllocationSize.QuadPart)) {
+ Status = RfsdExpandInode(IrpContext, Vcb, Fcb, &dwRet);
+ }
+
+ return Status;
+}
+
+NTSTATUS
+RfsdTruncateFile( PRFSD_IRP_CONTEXT IrpContext,
+ PRFSD_VCB Vcb, PRFSD_FCB Fcb,
+ PLARGE_INTEGER AllocationSize)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ PAGED_CODE();
+
+ while (NT_SUCCESS(Status) && (AllocationSize->QuadPart <
+ Fcb->Header.AllocationSize.QuadPart)) {
+ Status= RfsdTruncateInode(IrpContext, Vcb, Fcb);
+ }
+
+ return Status;
+}
+
+NTSTATUS
+RfsdSetDispositionInfo(
+ PRFSD_IRP_CONTEXT IrpContext,
+ PRFSD_VCB Vcb,
+ PRFSD_FCB Fcb,
+ BOOLEAN bDelete)
+{
+ PIRP Irp = IrpContext->Irp;
+ PIO_STACK_LOCATION IrpSp;
+
+ PAGED_CODE();
+
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+ RfsdPrint((DBG_INFO, "RfsdSetDispositionInfo: bDelete=%x\n", bDelete));
+
+ if (bDelete) {
+
+ RfsdPrint((DBG_INFO, "RfsdSetDispositionInformation: MmFlushImageSection on %s.\n",
+ Fcb->AnsiFileName.Buffer));
+
+ if (!MmFlushImageSection( &Fcb->SectionObject,
+ MmFlushForDelete )) {
+ return STATUS_CANNOT_DELETE;
+ }
+
+ if (RFSD_IS_ROOT_KEY(Fcb->RfsdMcb->Key)) {
+ return STATUS_CANNOT_DELETE;
+ }
+
+ if (IsDirectory(Fcb)) {
+ if (!RfsdIsDirectoryEmpty(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;
+}
+
+NTSTATUS
+RfsdSetRenameInfo(
+ PRFSD_IRP_CONTEXT IrpContext,
+ PRFSD_VCB Vcb,
+ PRFSD_FCB Fcb )
+{
+ PRFSD_FCB TargetDcb;
+ PRFSD_MCB TargetMcb;
+
+ PRFSD_MCB Mcb;
+ RFSD_INODE Inode;
+
+ 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 0
+ if (Fcb->RfsdMcb->Inode == RFSD_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->RfsdMcb->Parent;
+
+ if (FileName.Length >= RFSD_NAME_LEN*sizeof(USHORT)) {
+ Status = STATUS_OBJECT_NAME_INVALID;
+ goto errorout;
+ }
+
+ } else {
+
+ TargetDcb = (PRFSD_FCB)(TargetObject->FsContext);
+
+ if (!TargetDcb || TargetDcb->Vcb != Vcb) {
+
+ DbgBreak();
+
+ Status = STATUS_INVALID_PARAMETER;
+ goto errorout;
+ }
+
+ TargetMcb = TargetDcb->RfsdMcb;
+
+ FileName = TargetObject->FileName;
+ }
+
+ if (FsRtlDoesNameContainWildCards(&FileName)) {
+ Status = STATUS_OBJECT_NAME_INVALID;
+ goto errorout;
+ }
+
+ if (TargetMcb->Inode == Fcb->RfsdMcb->Parent->Inode) {
+ if (FsRtlAreNamesEqual( &FileName,
+ &(Fcb->RfsdMcb->ShortName),
+ FALSE,
+ NULL )) {
+ Status = STATUS_SUCCESS;
+ goto errorout;
+ }
+ } else {
+ bMove = TRUE;
+ }
+
+ TargetDcb = TargetMcb->RfsdFcb;
+
+ if (!TargetDcb)
+ TargetDcb = RfsdCreateFcbFromMcb(Vcb, TargetMcb);
+
+ if ((TargetMcb->Inode != Fcb->RfsdMcb->Parent->Inode) &&
+ (Fcb->RfsdMcb->Parent->RfsdFcb == NULL) ) {
+ RfsdCreateFcbFromMcb(Vcb, Fcb->RfsdMcb->Parent);
+ }
+
+ if (!TargetDcb || !(Fcb->RfsdMcb->Parent->RfsdFcb)) {
+ Status = STATUS_UNSUCCESSFUL;
+
+ goto errorout;
+ }
+
+ Mcb = NULL;
+ Status = RfsdLookupFileName(
+ Vcb,
+ &FileName,
+ TargetMcb,
+ &Mcb,
+ &Inode );
+
+ 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 = RfsdRemoveEntry( IrpContext, Vcb,
+ Fcb->RfsdMcb->Parent->RfsdFcb,
+ RFSD_FT_DIR,
+ Fcb->RfsdMcb->Inode );
+
+ if (!NT_SUCCESS(Status)) {
+ DbgBreak();
+
+ goto errorout;
+ }
+
+ Status = RfsdAddEntry( IrpContext, Vcb,
+ TargetDcb,
+ RFSD_FT_DIR,
+ Fcb->RfsdMcb->Inode,
+ &FileName );
+
+ if (!NT_SUCCESS(Status)) {
+
+ DbgBreak();
+
+ RfsdAddEntry( IrpContext, Vcb,
+ Fcb->RfsdMcb->Parent->RfsdFcb,
+ RFSD_FT_DIR,
+ Fcb->RfsdMcb->Inode,
+ &Fcb->RfsdMcb->ShortName );
+
+ goto errorout;
+ }
+
+ if( !RfsdSaveInode( IrpContext,
+ Vcb,
+ TargetMcb->Inode,
+ TargetDcb->Inode)) {
+ Status = STATUS_UNSUCCESSFUL;
+
+ DbgBreak();
+
+ goto errorout;
+ }
+
+ if( !RfsdSaveInode( IrpContext,
+ Vcb,
+ Fcb->RfsdMcb->Parent->Inode,
+ Fcb->RfsdMcb->Parent->RfsdFcb->Inode)) {
+
+ Status = STATUS_UNSUCCESSFUL;
+
+ DbgBreak();
+
+ goto errorout;
+ }
+
+ Status = RfsdSetParentEntry( IrpContext, Vcb, Fcb,
+ Fcb->RfsdMcb->Parent->Inode,
+ TargetDcb->RfsdMcb->Inode );
+
+
+ if (!NT_SUCCESS(Status)) {
+ DbgBreak();
+ goto errorout;
+ }
+
+ } else {
+
+ Status = RfsdRemoveEntry( IrpContext, Vcb,
+ Fcb->RfsdMcb->Parent->RfsdFcb,
+ RFSD_FT_REG_FILE,
+ Fcb->RfsdMcb->Inode );
+ if (!NT_SUCCESS(Status)) {
+ DbgBreak();
+ goto errorout;
+ }
+
+ Status = RfsdAddEntry( IrpContext,
+ Vcb, TargetDcb,
+ RFSD_FT_REG_FILE,
+ Fcb->RfsdMcb->Inode,
+ &FileName );
+
+ if (!NT_SUCCESS(Status)) {
+
+ DbgBreak();
+
+ RfsdAddEntry( IrpContext, Vcb,
+ Fcb->RfsdMcb->Parent->RfsdFcb,
+ RFSD_FT_REG_FILE,
+ Fcb->RfsdMcb->Inode,
+ &Fcb->RfsdMcb->ShortName );
+
+ goto errorout;
+ }
+ }
+
+ if (NT_SUCCESS(Status)) {
+
+ if (Fcb->RfsdMcb->ShortName.MaximumLength < (FileName.Length + 2)) {
+
+ ExFreePool(Fcb->RfsdMcb->ShortName.Buffer);
+ Fcb->RfsdMcb->ShortName.Buffer =
+ ExAllocatePoolWithTag(PagedPool, FileName.Length + 2, RFSD_POOL_TAG);
+
+ if (!Fcb->RfsdMcb->ShortName.Buffer) {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto errorout;
+ }
+
+ Fcb->RfsdMcb->ShortName.MaximumLength = FileName.Length + 2;
+ }
+
+ {
+ RtlZeroMemory( Fcb->RfsdMcb->ShortName.Buffer,
+ Fcb->RfsdMcb->ShortName.MaximumLength);
+
+ RtlCopyMemory( Fcb->RfsdMcb->ShortName.Buffer,
+ FileName.Buffer, FileName.Length);
+
+ Fcb->RfsdMcb->ShortName.Length = FileName.Length;
+ }
+
+#if DBG
+
+ Fcb->AnsiFileName.Length = (USHORT)
+ RfsdUnicodeToOEMSize(&FileName) + 1;
+
+ if (Fcb->AnsiFileName.MaximumLength < FileName.Length) {
+ ExFreePool(Fcb->AnsiFileName.Buffer);
+
+ Fcb->AnsiFileName.Buffer =
+ ExAllocatePoolWithTag(PagedPool, Fcb->AnsiFileName.Length + 1, RFSD_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;
+ }
+
+ RfsdUnicodeToOEM( &(Fcb->AnsiFileName),
+ &FileName );
+
+#endif
+
+ if (bMove) {
+
+ RfsdNotifyReportChange(
+ IrpContext,
+ Vcb,
+ Fcb,
+ (IsDirectory(Fcb) ?
+ FILE_NOTIFY_CHANGE_DIR_NAME :
+ FILE_NOTIFY_CHANGE_FILE_NAME ),
+ FILE_ACTION_REMOVED);
+
+ } else {
+
+ RfsdNotifyReportChange(
+ IrpContext,
+ Vcb,
+ Fcb,
+ (IsDirectory(Fcb) ?
+ FILE_NOTIFY_CHANGE_DIR_NAME :
+ FILE_NOTIFY_CHANGE_FILE_NAME ),
+ FILE_ACTION_RENAMED_OLD_NAME);
+
+ }
+
+ RfsdDeleteMcbNode(Vcb, Fcb->RfsdMcb->Parent, Fcb->RfsdMcb);
+ RfsdAddMcbNode(Vcb, TargetMcb, Fcb->RfsdMcb);
+
+ if (bMove) {
+
+ RfsdNotifyReportChange(
+ IrpContext,
+ Vcb,
+ Fcb,
+ (IsDirectory(Fcb) ?
+ FILE_NOTIFY_CHANGE_DIR_NAME :
+ FILE_NOTIFY_CHANGE_FILE_NAME ),
+ FILE_ACTION_ADDED);
+ } else {
+
+ RfsdNotifyReportChange(
+ IrpContext,
+ Vcb,
+ Fcb,
+ (IsDirectory(Fcb) ?
+ FILE_NOTIFY_CHANGE_DIR_NAME :
+ FILE_NOTIFY_CHANGE_FILE_NAME ),
+ FILE_ACTION_RENAMED_NEW_NAME );
+
+ }
+ }
+
+errorout:
+#endif // 0
+ return 0;//Status;
+}
+
+NTSTATUS
+RfsdDeleteFile(
+ PRFSD_IRP_CONTEXT IrpContext,
+ PRFSD_VCB Vcb,
+ PRFSD_FCB Fcb )
+{
+ BOOLEAN bRet = FALSE;
+ LARGE_INTEGER AllocationSize;
+ PRFSD_FCB Dcb = NULL;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ PAGED_CODE();
+#if 0
+ RfsdPrint((DBG_INFO, "RfsdDeleteFile: File %S (%xh) will be deleted!\n",
+ Fcb->RfsdMcb->ShortName.Buffer, Fcb->RfsdMcb->Inode));
+
+ if (IsFlagOn(Fcb->Flags, FCB_FILE_DELETED)) {
+ return Status;
+ }
+
+ if (FlagOn(Fcb->RfsdMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) {
+ if (!RfsdIsDirectoryEmpty(Vcb, Fcb)) {
+ ClearFlag(Fcb->Flags, FCB_DELETE_PENDING);
+
+ return STATUS_DIRECTORY_NOT_EMPTY;
+ }
+ }
+
+ RfsdPrint((DBG_INFO, "RfsdDeleteFile: RFSDSB->S_FREE_BLOCKS = %xh .\n",
+ Vcb->SuperBlock->s_free_blocks_count));
+
+ if (IsDirectory(Fcb)) {
+ if (Fcb->Inode->i_links_count <= 2) {
+ } else {
+ Status = STATUS_CANNOT_DELETE;
+ }
+ } else {
+ if (Fcb->Inode->i_links_count <= 1) {
+ } else {
+ Status = STATUS_CANNOT_DELETE;
+ }
+ }
+
+ if (!NT_SUCCESS(Status)) {
+ DbgBreak();
+ return Status;
+ }
+
+ if (Fcb->RfsdMcb->Parent->RfsdFcb) {
+
+ Status = RfsdRemoveEntry(
+ IrpContext, Vcb,
+ Fcb->RfsdMcb->Parent->RfsdFcb,
+ (FlagOn(Fcb->RfsdMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY) ?
+ RFSD_FT_DIR : RFSD_FT_REG_FILE),
+ Fcb->RfsdMcb->Inode);
+ } else {
+
+ Dcb = RfsdCreateFcbFromMcb(Vcb, Fcb->RfsdMcb->Parent);
+ if (Dcb) {
+ Status = RfsdRemoveEntry(
+ IrpContext, Vcb, Dcb,
+ (FlagOn(Fcb->RfsdMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY) ?
+ RFSD_FT_DIR : RFSD_FT_REG_FILE),
+ Fcb->RfsdMcb->Inode);
+ }
+ }
+
+ if (NT_SUCCESS(Status)) {
+
+ LARGE_INTEGER SysTime;
+ KeQuerySystemTime(&SysTime);
+
+ AllocationSize.QuadPart = (LONGLONG)0;
+
+ Status = RfsdTruncateFile(IrpContext, Vcb, Fcb, &AllocationSize);
+
+ //
+ // Update the inode's data length . It should be ZERO if succeeds.
+ //
+
+ if (Fcb->Header.FileSize.QuadPart > Fcb->Header.AllocationSize.QuadPart) {
+
+ Fcb->Header.FileSize.QuadPart = Fcb->Header.AllocationSize.QuadPart;
+ Fcb->Inode->i_size = Fcb->Header.AllocationSize.QuadPart;
+ }
+
+ Fcb->Inode->i_links_count = 0;
+
+ RfsdSaveInode(IrpContext, Vcb, Fcb->RfsdMcb->Inode, Fcb->Inode);
+
+ if (IsDirectory(Fcb)) {
+ bRet = RfsdFreeInode(IrpContext, Vcb, Fcb->RfsdMcb->Inode, RFSD_FT_DIR);
+ } else {
+ bRet = RfsdFreeInode(IrpContext, Vcb, Fcb->RfsdMcb->Inode, RFSD_FT_REG_FILE);
+ }
+
+ SetFlag(Fcb->Flags, FCB_FILE_DELETED);
+ RfsdDeleteMcbNode(Vcb, Fcb->RfsdMcb->Parent, Fcb->RfsdMcb);
+
+ } else {
+ DbgBreak();
+ RfsdSaveInode(IrpContext, Vcb, Fcb->RfsdMcb->Inode, Fcb->Inode);
+ }
+
+ RfsdPrint((DBG_INFO, "RfsdDeleteFile: Succeed... RFSDSB->S_FREE_BLOCKS = %xh .\n",
+ Vcb->SuperBlock->s_free_blocks_count));
+#endif // 0
+ return Status;
+}
+
+#endif // !RFSD_READ_ONLY