Author: fireball
Date: Sun Aug  8 10:43:28 2010
New Revision: 48487

URL: http://svn.reactos.org/svn/reactos?rev=48487&view=rev
Log:
[FASTFAT_NEW]
- Implement close and cleanup infrastructure.
- Add necessary FCB and VCB counters.
- Add missing op and file locks initialization.
- A lot of small cleanups, improvements, and other things, bringing fastfat_new 
much closer to a minimally working state.

Modified:
    trunk/reactos/drivers/filesystems/fastfat_new/cleanup.c
    trunk/reactos/drivers/filesystems/fastfat_new/close.c
    trunk/reactos/drivers/filesystems/fastfat_new/create.c
    trunk/reactos/drivers/filesystems/fastfat_new/dir.c
    trunk/reactos/drivers/filesystems/fastfat_new/fastfat.c
    trunk/reactos/drivers/filesystems/fastfat_new/fastfat.h
    trunk/reactos/drivers/filesystems/fastfat_new/fat.c
    trunk/reactos/drivers/filesystems/fastfat_new/fatstruc.h
    trunk/reactos/drivers/filesystems/fastfat_new/fcb.c
    trunk/reactos/drivers/filesystems/fastfat_new/volume.c

Modified: trunk/reactos/drivers/filesystems/fastfat_new/cleanup.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/fastfat_new/cleanup.c?rev=48487&r1=48486&r2=48487&view=diff
==============================================================================
--- trunk/reactos/drivers/filesystems/fastfat_new/cleanup.c [iso-8859-1] 
(original)
+++ trunk/reactos/drivers/filesystems/fastfat_new/cleanup.c [iso-8859-1] Sun 
Aug  8 10:43:28 2010
@@ -13,13 +13,431 @@
 
 /* FUNCTIONS ****************************************************************/
 
+/* Last handle to a file object is closed */
+NTSTATUS
+NTAPI
+FatiCleanup(PFAT_IRP_CONTEXT IrpContext, PIRP Irp)
+{
+    PIO_STACK_LOCATION IrpSp;
+    PFILE_OBJECT FileObject;
+    TYPE_OF_OPEN TypeOfOpen;
+    PSHARE_ACCESS ShareAccess;
+    BOOLEAN SendUnlockNotification = FALSE;
+    PLARGE_INTEGER TruncateSize = NULL;
+    //LARGE_INTEGER LocalTruncateSize;
+    BOOLEAN AcquiredVcb = FALSE, AcquiredFcb = FALSE;
+    NTSTATUS Status;
+    PVCB Vcb;
+    PFCB Fcb;
+    PCCB Ccb;
+
+    IrpSp = IoGetCurrentIrpStackLocation( Irp );
+
+    DPRINT("FatiCleanup\n");
+    DPRINT("\tIrp           = %p\n", Irp);
+    DPRINT("\t->FileObject  = %p\n", IrpSp->FileObject);
+
+    FileObject = IrpSp->FileObject;
+    TypeOfOpen = FatDecodeFileObject(FileObject, &Vcb, &Fcb, &Ccb);
+
+    if (TypeOfOpen == UnopenedFileObject)
+    {
+        DPRINT1("Unopened File Object\n");
+
+        FatCompleteRequest(IrpContext, Irp, STATUS_SUCCESS);
+        return STATUS_SUCCESS;
+    }
+
+    if (FlagOn( FileObject->Flags, FO_CLEANUP_COMPLETE ))
+    {
+        /* Just flush the file */
+
+        if (FlagOn(Vcb->State, VCB_STATE_FLAG_DEFERRED_FLUSH) &&
+            FlagOn(FileObject->Flags, FO_FILE_MODIFIED) &&
+            !FlagOn(Vcb->State, VCB_STATE_FLAG_WRITE_PROTECTED) &&
+            (TypeOfOpen == UserFileOpen))
+        {
+            //Status = FatFlushFile(IrpContext, Fcb, Flush);
+            //if (!NT_SUCCESS(Status)) FatNormalizeAndRaiseStatus(IrpContext, 
Status);
+            UNIMPLEMENTED;
+        }
+
+        FatCompleteRequest(IrpContext, Irp, STATUS_SUCCESS);
+        return STATUS_SUCCESS;
+    }
+
+    if (TypeOfOpen == UserFileOpen ||
+        TypeOfOpen == UserDirectoryOpen)
+    {
+        ASSERT(Fcb != NULL);
+
+        (VOID)FatAcquireExclusiveFcb(IrpContext, Fcb);
+
+        AcquiredFcb = TRUE;
+
+        /* Set FCB flags according to DELETE_ON_CLOSE */
+        if (FlagOn(Ccb->Flags, CCB_DELETE_ON_CLOSE))
+        {
+            ASSERT(FatNodeType(Fcb) != FAT_NTC_ROOT_DCB);
+
+            SetFlag(Fcb->State, FCB_STATE_DELETE_ON_CLOSE);
+
+            /* Issue a notification */
+            if (TypeOfOpen == UserDirectoryOpen)
+            {
+                FsRtlNotifyFullChangeDirectory(Vcb->NotifySync,
+                                               &Vcb->NotifyList,
+                                               FileObject->FsContext,
+                                               NULL,
+                                               FALSE,
+                                               FALSE,
+                                               0,
+                                               NULL,
+                                               NULL,
+                                               NULL);
+            }
+        }
+
+        /* If file should be deleted, acquire locks */
+        if ((Fcb->UncleanCount == 1) &&
+            FlagOn(Fcb->State, FCB_STATE_DELETE_ON_CLOSE) &&
+            (Fcb->Condition != FcbBad) &&
+            !FlagOn(Vcb->State, VCB_STATE_FLAG_WRITE_PROTECTED))
+        {
+            FatReleaseFcb(IrpContext, Fcb);
+            AcquiredFcb = FALSE;
+
+            (VOID)FatAcquireExclusiveVcb(IrpContext, Vcb);
+            AcquiredVcb = TRUE;
+
+            (VOID)FatAcquireExclusiveFcb(IrpContext, Fcb);
+            AcquiredFcb = TRUE;
+        }
+    }
+
+    /* Acquire VCB lock if it was a volume open */
+    if (TypeOfOpen == UserVolumeOpen)
+    {
+        (VOID)FatAcquireExclusiveVcb(IrpContext, Vcb);
+        AcquiredVcb = TRUE;
+    }
+
+    /* Cleanup all notifications */
+    if (TypeOfOpen == UserDirectoryOpen)
+    {
+        FsRtlNotifyCleanup(Vcb->NotifySync,
+                           &Vcb->NotifyList,
+                           Ccb);
+    }
+
+    if (Fcb)
+    {
+        //TODO: FatVerifyFcb
+    }
+
+    switch (TypeOfOpen)
+    {
+    case DirectoryFile:
+    case VirtualVolumeFile:
+        DPRINT1("Cleanup VirtualVolumeFile/DirectoryFile\n");
+        ShareAccess = NULL;
+        break;
+
+    case UserVolumeOpen:
+        DPRINT("Cleanup UserVolumeOpen\n");
+
+        if (FlagOn(Ccb->Flags, CCB_COMPLETE_DISMOUNT))
+        {
+            FatCheckForDismount( IrpContext, Vcb, TRUE );
+        } else if (FileObject->WriteAccess &&
+            FlagOn(FileObject->Flags, FO_FILE_MODIFIED))
+        {
+            UNIMPLEMENTED;
+        }
+
+        /* Release the volume and send notification */
+        if (FlagOn(Vcb->State, VCB_STATE_FLAG_LOCKED) &&
+            (Vcb->FileObjectWithVcbLocked == FileObject))
+        {
+            UNIMPLEMENTED;
+            SendUnlockNotification = TRUE;
+        }
+
+        ShareAccess = &Vcb->ShareAccess;
+        break;
+
+    case EaFile:
+        DPRINT1("Cleanup EaFileObject\n");
+        ShareAccess = NULL;
+        break;
+
+    case UserDirectoryOpen:
+        DPRINT("Cleanup UserDirectoryOpen\n");
+
+        ShareAccess = &Fcb->ShareAccess;
+
+        /* Should it be a delayed close? */
+        if ((Fcb->UncleanCount == 1) &&
+            (Fcb->OpenCount == 1) &&
+            (Fcb->Dcb.DirectoryFileOpenCount == 0) &&
+            !FlagOn(Fcb->State, FCB_STATE_DELETE_ON_CLOSE) &&
+            Fcb->Condition == FcbGood)
+        {
+            /* Yes, a delayed one */
+            SetFlag(Fcb->State, FCB_STATE_DELAY_CLOSE);
+        }
+
+        if (VcbGood == Vcb->Condition)
+        {
+            //FatUpdateDirentFromFcb( IrpContext, FileObject, Fcb, Ccb );
+            //TODO: Actually update dirent
+        }
+
+        if ((Fcb->UncleanCount == 1) &&
+            (FatNodeType(Fcb) == FAT_NTC_DCB) &&
+            (FlagOn(Fcb->State, FCB_STATE_DELETE_ON_CLOSE)) &&
+            (Fcb->Condition != FcbBad) &&
+            !FlagOn(Vcb->State, VCB_STATE_FLAG_WRITE_PROTECTED))
+        {
+            UNIMPLEMENTED;
+        }
+
+        /*  Decrement unclean counter */
+        ASSERT(Fcb->UncleanCount != 0);
+        Fcb->UncleanCount--;
+        break;
+
+    case UserFileOpen:
+        DPRINT("Cleanup UserFileOpen\n");
+
+        ShareAccess = &Fcb->ShareAccess;
+
+        /* Should it be a delayed close? */
+        if ((FileObject->SectionObjectPointer->DataSectionObject == NULL) &&
+            (FileObject->SectionObjectPointer->ImageSectionObject == NULL) &&
+            (Fcb->UncleanCount == 1) &&
+            (Fcb->OpenCount == 1) &&
+            !FlagOn(Fcb->State, FCB_STATE_DELETE_ON_CLOSE) &&
+            Fcb->Condition == FcbGood)
+        {
+            /* Yes, a delayed one */
+            SetFlag(Fcb->State, FCB_STATE_DELAY_CLOSE);
+        }
+
+        /* Unlock all file locks */
+        FsRtlFastUnlockAll(&Fcb->Fcb.Lock,
+                           FileObject,
+                           IoGetRequestorProcess(Irp),
+                           NULL);
+
+        if (Vcb->Condition == VcbGood)
+        {
+            if (Fcb->Condition != FcbBad)
+            {
+                //FatUpdateDirentFromFcb( IrpContext, FileObject, Fcb, Ccb );
+                // TODO: Update on-disk structures
+            }
+
+            if (Fcb->UncleanCount == 1 &&
+                Fcb->Condition != FcbBad)
+            {
+                //DELETE_CONTEXT DeleteContext;
+
+                /* Should this file be deleted on close? */
+                if (FlagOn(Fcb->State, FCB_STATE_DELETE_ON_CLOSE) &&
+                    !FlagOn(Vcb->State, VCB_STATE_FLAG_WRITE_PROTECTED))
+                {
+                    UNIMPLEMENTED;
+                }
+                else
+                {
+                    if (!FlagOn(Fcb->State, FCB_STATE_PAGEFILE) &&
+                        (Fcb->Header.ValidDataLength.LowPart < 
Fcb->Header.FileSize.LowPart))
+                    {
+#if 0
+                        ULONG ValidDataLength;
+
+                        ValidDataLength = Fcb->Header.ValidDataLength.LowPart;
+
+                        if (ValidDataLength < Fcb->ValidDataToDisk) {
+                            ValidDataLength = Fcb->ValidDataToDisk;
+                        }
+
+                        if (ValidDataLength < Fcb->Header.FileSize.LowPart)
+                        {
+                            FatZeroData( IrpContext,
+                                Vcb,
+                                FileObject,
+                                ValidDataLength,
+                                Fcb->Header.FileSize.LowPart -
+                                ValidDataLength );
+
+                            Fcb->ValidDataToDisk =
+                                Fcb->Header.ValidDataLength.LowPart =
+                                Fcb->Header.FileSize.LowPart;
+
+                            if (CcIsFileCached(FileObject))
+                            {
+                                CcSetFileSizes(FileObject, 
(PCC_FILE_SIZES)&Fcb->Header.AllocationSize);
+                            }
+                        }
+#endif
+                        DPRINT1("Zeroing out data is not implemented\n");
+                    }
+                }
+
+                /* Should the file be truncated on close? */
+                if (FlagOn(Fcb->State, FCB_STATE_TRUNCATE_ON_CLOSE))
+                {
+                    if (Vcb->Condition == VcbGood)
+                    {
+                        // TODO: Actually truncate the file allocation
+                        UNIMPLEMENTED;
+                    }
+
+                    /* Remove truncation flag */
+                    Fcb->State &= ~FCB_STATE_TRUNCATE_ON_CLOSE;
+                }
+
+                /* Check again if it should be deleted */
+                if (FlagOn(Fcb->State, FCB_STATE_DELETE_ON_CLOSE) &&
+                    Fcb->Header.AllocationSize.LowPart == 0)
+                {
+                    UNIMPLEMENTED;
+                    /*FatNotifyReportChange(IrpContext,
+                                          Vcb,
+                                          Fcb,
+                                          FILE_NOTIFY_CHANGE_FILE_NAME,
+                                          FILE_ACTION_REMOVED );*/
+                }
+
+                /* Remove the entry from the splay table if the file was 
deleted */
+                if (FlagOn(Fcb->State, FCB_STATE_DELETE_ON_CLOSE))
+                {
+                    FatRemoveNames(IrpContext, Fcb);
+                }
+            }
+        }
+
+        ASSERT(Fcb->UncleanCount != 0);
+        Fcb->UncleanCount--;
+        if (!FlagOn(FileObject->Flags, FO_CACHE_SUPPORTED))
+        {
+            ASSERT(Fcb->NonCachedUncleanCount != 0);
+            Fcb->NonCachedUncleanCount--;
+        }
+
+        if (FlagOn(FileObject->Flags, FO_CACHE_SUPPORTED) &&
+            (Fcb->NonCachedUncleanCount != 0) &&
+            (Fcb->NonCachedUncleanCount == Fcb->UncleanCount) &&
+            (Fcb->SectionObjectPointers.DataSectionObject != NULL))
+        {
+            CcFlushCache(&Fcb->SectionObjectPointers, NULL, 0, NULL);
+
+            /* Acquire and release PagingIo to get in sync with lazy writer */
+            ExAcquireResourceExclusiveLite(Fcb->Header.PagingIoResource, TRUE);
+            ExReleaseResourceLite(Fcb->Header.PagingIoResource);
+
+            CcPurgeCacheSection(&Fcb->SectionObjectPointers,
+                                NULL,
+                                0,
+                                FALSE);
+        }
+
+        if (Fcb->Condition == FcbBad)
+        {
+            //TruncateSize = &FatLargeZero;
+            UNIMPLEMENTED;
+        }
+
+        /*  Cleanup the cache map */
+        CcUninitializeCacheMap(FileObject, TruncateSize, NULL);
+        break;
+
+    default:
+        KeBugCheckEx(FAT_FILE_SYSTEM, __LINE__, (ULONG_PTR)TypeOfOpen, 0, 0);
+    }
+
+    /* Cleanup the share access */
+
+    if (ShareAccess)
+    {
+        DPRINT("Cleaning up the share access\n");
+        IoRemoveShareAccess(FileObject, ShareAccess);
+    }
+
+    if (TypeOfOpen == UserFileOpen)
+    {
+        /* Update oplocks */
+        FsRtlCheckOplock(&Fcb->Fcb.Oplock,
+                         Irp,
+                         IrpContext,
+                         NULL,
+                         NULL);
+
+        Fcb->Header.IsFastIoPossible = FatIsFastIoPossible(Fcb);
+    }
+
+    /* Set the FO_CLEANUP_COMPLETE flag */
+    SetFlag(FileObject->Flags, FO_CLEANUP_COMPLETE);
+
+    Status = STATUS_SUCCESS;
+
+    // TODO: Unpin repinned BCBs
+    //FatUnpinRepinnedBcbs(IrpContext);
+
+    /* Flush the volume if necessary */
+    if (FlagOn(Vcb->State, VCB_STATE_FLAG_DEFERRED_FLUSH) &&
+        !FlagOn(Vcb->State, VCB_STATE_FLAG_WRITE_PROTECTED))
+    {
+        UNIMPLEMENTED;
+    }
+
+    /* Cleanup */
+    if (AcquiredFcb) FatReleaseFcb(IrpContext, Fcb);
+    if (AcquiredVcb) FatReleaseVcb(IrpContext, Vcb);
+
+    /* Send volume notification */
+    if (SendUnlockNotification)
+        FsRtlNotifyVolumeEvent(FileObject, FSRTL_VOLUME_UNLOCK);
+
+    return Status;
+}
+
 NTSTATUS
 NTAPI
 FatCleanup(PDEVICE_OBJECT DeviceObject, PIRP Irp)
 {
-    DPRINT1("FatCleanup(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
-
-    return STATUS_NOT_IMPLEMENTED;
+    PFAT_IRP_CONTEXT IrpContext;
+    NTSTATUS Status;
+
+    DPRINT("FatCleanup(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
+
+    /* FatCleanup works only with a volume device object */
+    if (DeviceObject == FatGlobalData.DiskDeviceObject)
+    {
+        /* Complete the request and return success */
+        Irp->IoStatus.Status = STATUS_SUCCESS;
+        Irp->IoStatus.Information = FILE_OPENED;
+
+        IoCompleteRequest(Irp, IO_DISK_INCREMENT);
+
+        return STATUS_SUCCESS;
+    }
+
+    /* Enter FsRtl critical region */
+    FsRtlEnterFileSystem();
+
+    /* Build an irp context */
+    IrpContext = FatBuildIrpContext(Irp, TRUE);
+
+    /* Call internal function */
+    Status = FatiCleanup(IrpContext, Irp);
+
+    /* Leave FsRtl critical region */
+    FsRtlExitFileSystem();
+
+    return Status;
 }
 
 /* EOF */

Modified: trunk/reactos/drivers/filesystems/fastfat_new/close.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/fastfat_new/close.c?rev=48487&r1=48486&r2=48487&view=diff
==============================================================================
--- trunk/reactos/drivers/filesystems/fastfat_new/close.c [iso-8859-1] 
(original)
+++ trunk/reactos/drivers/filesystems/fastfat_new/close.c [iso-8859-1] Sun Aug  
8 10:43:28 2010
@@ -15,11 +15,340 @@
 
 NTSTATUS
 NTAPI
+FatiCommonClose(IN PVCB Vcb,
+                IN PFCB Fcb,
+                IN PCCB Ccb,
+                IN TYPE_OF_OPEN TypeOfOpen,
+                IN BOOLEAN Wait,
+                OUT PBOOLEAN VcbDeleted)
+{
+    NTSTATUS Status;
+    PFCB ParentDcb;
+    BOOLEAN RecursiveClose, VcbDeletedLv = FALSE;
+    FAT_IRP_CONTEXT IrpContext;
+
+    if (VcbDeleted) *VcbDeleted = FALSE;
+
+    if (TypeOfOpen == UnopenedFileObject)
+    {
+        DPRINT1("Closing unopened file object\n");
+        Status = STATUS_SUCCESS;
+        return Status;
+    }
+
+    RtlZeroMemory(&IrpContext, sizeof(FAT_IRP_CONTEXT));
+
+    IrpContext.NodeTypeCode = FAT_NTC_IRP_CONTEXT;
+    IrpContext.NodeByteSize = sizeof(IrpContext);
+    IrpContext.MajorFunction = IRP_MJ_CLOSE;
+
+    if (Wait) SetFlag(IrpContext.Flags, IRPCONTEXT_CANWAIT);
+
+    if (!ExAcquireResourceExclusiveLite(&Vcb->Resource, Wait)) return 
STATUS_PENDING;
+
+    if (Vcb->State & VCB_STATE_FLAG_CLOSE_IN_PROGRESS)
+    {
+        RecursiveClose = TRUE;
+    }
+    else
+    {
+        SetFlag(Vcb->State, VCB_STATE_FLAG_CLOSE_IN_PROGRESS);
+        RecursiveClose = FALSE;
+
+        Vcb->OpenFileCount++;
+    }
+
+    /* Update on-disk structures */
+    switch (TypeOfOpen)
+    {
+    case VirtualVolumeFile:
+        DPRINT1("Close VirtualVolumeFile\n");
+
+        InterlockedDecrement((PLONG)&(Vcb->InternalOpenCount));
+        InterlockedDecrement((PLONG)&(Vcb->ResidualOpenCount));
+
+        Status = STATUS_SUCCESS;
+        goto close_done;
+        break;
+
+    case UserVolumeOpen:
+        DPRINT1("Close UserVolumeOpen\n");
+
+        Vcb->DirectAccessOpenCount--;
+        Vcb->OpenFileCount--;
+        if (FlagOn(Ccb->Flags, CCB_READ_ONLY)) Vcb->ReadOnlyCount--;
+
+        FatDeleteCcb(&IrpContext, Ccb);
+
+        Status = STATUS_SUCCESS;
+        goto close_done;
+        break;
+
+    case EaFile:
+        UNIMPLEMENTED;
+        break;
+
+    case DirectoryFile:
+        DPRINT1("Close DirectoryFile\n");
+
+        InterlockedDecrement((PLONG)&(Fcb->Dcb.DirectoryFileOpenCount));
+        InterlockedDecrement((PLONG)&(Vcb->InternalOpenCount));
+
+        if (FatNodeType(Fcb) == FAT_NTC_ROOT_DCB)
+        {
+            InterlockedDecrement((PLONG)&(Vcb->ResidualOpenCount));
+        }
+
+        if (RecursiveClose)
+        {
+            Status = STATUS_SUCCESS;
+            goto close_done;
+        }
+        else
+        {
+            break;
+        }
+
+    case UserDirectoryOpen:
+    case UserFileOpen:
+        DPRINT("Close UserFileOpen/UserDirectoryOpen\n");
+
+        if ((FatNodeType(Fcb) == FAT_NTC_DCB) &&
+            IsListEmpty(&Fcb->Dcb.ParentDcbList) &&
+            (Fcb->OpenCount == 1) &&
+            (Fcb->Dcb.DirectoryFile != NULL))
+        {
+                PFILE_OBJECT DirectoryFileObject = Fcb->Dcb.DirectoryFile;
+
+                DPRINT1("Uninitialize the stream file object\n");
+
+                CcUninitializeCacheMap(DirectoryFileObject, NULL, NULL);
+
+                Fcb->Dcb.DirectoryFile = NULL;
+                ObDereferenceObject(DirectoryFileObject);
+        }
+
+        Fcb->OpenCount--;
+        Vcb->OpenFileCount--;
+        if (FlagOn(Ccb->Flags, CCB_READ_ONLY)) Vcb->ReadOnlyCount --;
+
+        FatDeleteCcb(&IrpContext, Ccb);
+        break;
+
+    default:
+        KeBugCheckEx(FAT_FILE_SYSTEM, __LINE__, (ULONG_PTR)TypeOfOpen, 0, 0);
+    }
+
+    /* Update in-memory structures */
+    if (((FatNodeType(Fcb) == FAT_NTC_FCB) &&
+        (Fcb->OpenCount == 0))
+        ||
+        ((FatNodeType(Fcb) == FAT_NTC_DCB) &&
+        (IsListEmpty(&Fcb->Dcb.ParentDcbList)) &&
+        (Fcb->OpenCount == 0) &&
+        (Fcb->Dcb.DirectoryFileOpenCount == 0)))
+    {
+        ParentDcb = Fcb->ParentFcb;
+
+        SetFlag(Vcb->State, VCB_STATE_FLAG_DELETED_FCB);
+
+        FatDeleteFcb(&IrpContext, Fcb);
+
+        while ((FatNodeType(ParentDcb) == FAT_NTC_DCB) &&
+            IsListEmpty(&ParentDcb->Dcb.ParentDcbList) &&
+            (ParentDcb->OpenCount == 0) &&
+            (ParentDcb->Dcb.DirectoryFile != NULL))
+        {
+                PFILE_OBJECT DirectoryFileObject;
+
+                DirectoryFileObject = ParentDcb->Dcb.DirectoryFile;
+
+                DPRINT1("Uninitialize parent Stream Cache Map\n");
+
+                CcUninitializeCacheMap(DirectoryFileObject, NULL, NULL);
+
+                ParentDcb->Dcb.DirectoryFile = NULL;
+
+                ObDereferenceObject(DirectoryFileObject);
+
+                if (ParentDcb->Dcb.DirectoryFileOpenCount == 0)
+                {
+                    PFCB CurrentDcb;
+
+                    CurrentDcb = ParentDcb;
+                    ParentDcb = CurrentDcb->ParentFcb;
+
+                    SetFlag(Vcb->State, VCB_STATE_FLAG_DELETED_FCB);
+
+                    FatDeleteFcb(&IrpContext, CurrentDcb);
+                }
+                else
+                {
+                    break;
+                }
+        }
+    }
+
+    Status = STATUS_SUCCESS;
+
+close_done:
+    /* Closing is done, check if VCB could be closed too */
+    if (!RecursiveClose)
+    {
+        /* One open left - yes, VCB can go away */
+        if (Vcb->OpenFileCount == 1 &&
+            !FlagOn(Vcb->State, VCB_STATE_FLAG_DISMOUNT_IN_PROGRESS)
+            && VcbDeleted)
+        {
+            FatReleaseVcb(&IrpContext, Vcb );
+
+            SetFlag(IrpContext.Flags, IRPCONTEXT_CANWAIT);
+
+            FatAcquireExclusiveGlobal(&IrpContext);
+
+            FatAcquireExclusiveVcb(&IrpContext, Vcb);
+
+            Vcb->OpenFileCount--;
+
+            VcbDeletedLv = FatCheckForDismount(&IrpContext, Vcb, FALSE);
+
+            FatReleaseGlobal(&IrpContext);
+
+            if (VcbDeleted) *VcbDeleted = VcbDeletedLv;
+        }
+        else
+        {
+            /* Remove extra referenec */
+            Vcb->OpenFileCount --;
+        }
+
+        /* Clear recursion flag if necessary */
+        if (!VcbDeletedLv)
+        {
+            ClearFlag(Vcb->State, VCB_STATE_FLAG_CLOSE_IN_PROGRESS);
+        }
+    }
+
+    /* Release VCB if it wasn't deleted */
+    if (!VcbDeletedLv)
+        FatReleaseVcb(&IrpContext, Vcb);
+
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+FatiClose(IN PFAT_IRP_CONTEXT IrpContext,
+          IN PIRP Irp)
+{
+    PIO_STACK_LOCATION IrpSp;
+    TYPE_OF_OPEN TypeOfOpen;
+    PVCB Vcb;
+    PFCB Fcb;
+    PCCB Ccb;
+    BOOLEAN TopLevel, Wait, VcbDeleted = FALSE;
+    NTSTATUS Status;
+    PCLOSE_CONTEXT CloseContext = NULL;
+
+    TopLevel = FatIsTopLevelIrp(Irp);
+
+    /* Get current IRP stack location */
+    IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+    /* Decode incoming file object */
+    TypeOfOpen = FatDecodeFileObject(IrpSp->FileObject, &Vcb, &Fcb, &Ccb);
+
+    /* Set CCB read only flag */
+    if (Ccb && IsFileObjectReadOnly(IrpSp->FileObject))
+        SetFlag(Ccb->Flags, CCB_READ_ONLY);
+
+    /* It's possible to wait only if we are top level or not a system process 
*/
+    Wait = TopLevel && (PsGetCurrentProcess() != FatGlobalData.SystemProcess);
+
+    /* Call the common handler */
+    Status = FatiCommonClose(Vcb, Fcb, Ccb, TypeOfOpen, Wait, &VcbDeleted);
+
+    if (((TypeOfOpen == UserFileOpen ||
+        TypeOfOpen == UserDirectoryOpen) &&
+        (Fcb->State & FCB_STATE_DELAY_CLOSE) &&
+        !FatGlobalData.ShutdownStarted) ||
+        Status == STATUS_PENDING)
+    {
+        DPRINT1("TODO: Queue a pending close request\n");
+    }
+    else
+    {
+        /* Close finished right away */
+        if (TypeOfOpen == VirtualVolumeFile ||
+            TypeOfOpen == DirectoryFile ||
+            TypeOfOpen == EaFile)
+        {
+                if (TypeOfOpen == VirtualVolumeFile)
+                {
+                    /* Free close context for the not deleted VCB */
+                    if (!VcbDeleted)
+                    {
+                        CloseContext = Vcb->CloseContext;
+                        Vcb->CloseContext = NULL;
+
+                        ASSERT(CloseContext != NULL);
+                    }
+                }
+                else
+                {
+                    //CloseContext = FatAllocateCloseContext(Vcb);
+                    DPRINT1("TODO: Allocate close context!\n");
+                    ASSERT(CloseContext != NULL);
+                }
+
+                /* Free close context */
+                if (CloseContext) ExFreePool(CloseContext);
+        }
+    }
+
+    /* Complete the request */
+    FatCompleteRequest(NULL, Irp, Status);
+
+    /* Reset the top level IRP if necessary */
+    if (TopLevel) IoSetTopLevelIrp(NULL);
+
+    return Status;
+}
+
+NTSTATUS
+NTAPI
 FatClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
 {
-    DPRINT1("FatClose(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
-
-    return STATUS_NOT_IMPLEMENTED;
+    PFAT_IRP_CONTEXT IrpContext;
+    NTSTATUS Status;
+
+    DPRINT("FatClose(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
+
+    /* FatClose works only with a volume device object */
+    if (DeviceObject == FatGlobalData.DiskDeviceObject)
+    {
+        /* Complete the request and return success */
+        Irp->IoStatus.Status = STATUS_SUCCESS;
+        Irp->IoStatus.Information = FILE_OPENED;
+
+        IoCompleteRequest(Irp, IO_DISK_INCREMENT);
+
+        return STATUS_SUCCESS;
+    }
+
+    /* Enter FsRtl critical region */
+    FsRtlEnterFileSystem();
+
+    /* Build an irp context */
+    IrpContext = FatBuildIrpContext(Irp, TRUE);
+
+    /* Call internal function */
+    Status = FatiClose(IrpContext, Irp);
+
+    /* Leave FsRtl critical region */
+    FsRtlExitFileSystem();
+
+    return Status;
 }
 
 /* EOF */

Modified: trunk/reactos/drivers/filesystems/fastfat_new/create.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/fastfat_new/create.c?rev=48487&r1=48486&r2=48487&view=diff
==============================================================================
--- trunk/reactos/drivers/filesystems/fastfat_new/create.c [iso-8859-1] 
(original)
+++ trunk/reactos/drivers/filesystems/fastfat_new/create.c [iso-8859-1] Sun Aug 
 8 10:43:28 2010
@@ -72,7 +72,9 @@
 
         /* Increment counters */
         Dcb->OpenCount++;
+        Dcb->UncleanCount++;
         Vcb->OpenFileCount++;
+        if (IsFileObjectReadOnly(FileObject)) Vcb->ReadOnlyCount++;
 
         /* Set success statuses */
         Iosb.Status = STATUS_SUCCESS;
@@ -186,7 +188,7 @@
         CcSetFileSizes(FileObject, 
(PCC_FILE_SIZES)&Fcb->Header.AllocationSize);
 
         // TODO: Actually truncate the file
-        DPRINT1("TODO: Actually truncate the file with a fullfat handle %x\n", 
Fcb->FatHandle);
+        DPRINT1("TODO: Actually truncate file '%wZ' with a fullfat handle 
%x\n", &Fcb->FullFileName, Fcb->FatHandle);
 
         /* Release the paging resource */
         ExReleaseResourceLite(Fcb->Header.PagingIoResource);
@@ -287,6 +289,12 @@
                      UserDirectoryOpen,
                      Fcb,
                      FatCreateCcb());
+
+    /* Increase counters */
+    Fcb->UncleanCount++;
+    Fcb->OpenCount++;
+    Vcb->OpenFileCount++;
+    if (IsFileObjectReadOnly(FileObject)) Vcb->ReadOnlyCount++;
 
     Iosb.Status = STATUS_SUCCESS;
     Iosb.Information = FILE_OPENED;
@@ -319,6 +327,7 @@
     PFCB Fcb;
     NTSTATUS Status;
     FF_FILE *FileHandle;
+    FF_ERROR FfError;
 
     /* Check for create file option and fail */
     if (CreateDisposition == FILE_CREATE)
@@ -341,20 +350,22 @@
     }
 
     /* Open the file with FullFAT */
-    FileHandle = FF_Open(Vcb->Ioman, AnsiName.Buffer, FF_MODE_READ, NULL);
+    FileHandle = FF_Open(Vcb->Ioman, AnsiName.Buffer, FF_MODE_READ, &FfError);
 
     if (!FileHandle)
     {
+        DPRINT1("Failed to open file '%s', error %ld\n", AnsiName.Buffer, 
FfError);
         Iosb.Status = STATUS_OBJECT_NAME_NOT_FOUND; // FIXME: A shortcut for 
now
         return Iosb;
     }
+    DPRINT1("Succeeded opening file '%s'\n", AnsiName.Buffer);
 
     /* Create a new FCB for this file */
     Fcb = FatCreateFcb(IrpContext, Vcb, ParentDcb, FileHandle);
 
     // TODO: Check if overwrite is needed
 
-    // This is usual file open branch, without overwriting!
+    // TODO: This is usual file open branch, without overwriting!
     /* Set context and section object pointers */
     FatSetFileObject(FileObject,
                      UserFileOpen,
@@ -364,6 +375,13 @@
 
     Iosb.Status = STATUS_SUCCESS;
     Iosb.Information = FILE_OPENED;
+
+
+    /* Increase counters */
+    Fcb->UncleanCount++;
+    Fcb->OpenCount++;
+    if (FlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING)) 
Fcb->NonCachedUncleanCount++;
+    if (IsFileObjectReadOnly(FileObject)) Vcb->ReadOnlyCount++;
 
     return Iosb;
 }
@@ -397,7 +415,7 @@
         // and opened handles count is not 0
         //if (!FlagOn(ShareAccess, FILE_SHARE_READ)
 
-        DPRINT1("Exclusive voume open\n");
+        DPRINT1("Exclusive volume open\n");
 
         // TODO: Flush the volume
         VolumeFlushed = TRUE;
@@ -450,6 +468,7 @@
     /* Increase direct open count */
     Vcb->DirectOpenCount++;
     Vcb->OpenFileCount++;
+    if (IsFileObjectReadOnly(FileObject)) Vcb->ReadOnlyCount++;
 
     /* Set no buffering flag */
     FileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING;
@@ -720,7 +739,7 @@
         /* Set parent DCB */
         ParentDcb = RelatedDcb;
 
-        DPRINT1("Opening file '%wZ' relatively to '%wZ'\n", &FileName, 
&ParentDcb->FullFileName);
+        DPRINT("Opening file '%wZ' relatively to '%wZ'\n", &FileName, 
&ParentDcb->FullFileName);
     }
     else
     {
@@ -1137,6 +1156,12 @@
                                 DeleteOnClose,
                                 OpenedAsDos);
 
+    /* In case of success set cache supported flag */
+    if (NT_SUCCESS(Iosb.Status) && !NoIntermediateBuffering)
+    {
+        SetFlag(FileObject->Flags, FO_CACHE_SUPPORTED);
+    }
+
     Irp->IoStatus.Information = Iosb.Information;
 
     /* Unlock VCB */

Modified: trunk/reactos/drivers/filesystems/fastfat_new/dir.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/fastfat_new/dir.c?rev=48487&r1=48486&r2=48487&view=diff
==============================================================================
--- trunk/reactos/drivers/filesystems/fastfat_new/dir.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/fastfat_new/dir.c [iso-8859-1] Sun Aug  8 
10:43:28 2010
@@ -81,9 +81,6 @@
     /* Initialize advanced FCB header fields */
     ExInitializeFastMutex(&Dcb->HeaderMutex);
     FsRtlSetupAdvancedHeader(&Dcb->Header, &Dcb->HeaderMutex);
-
-    /* Initialize MCB */
-    FsRtlInitializeLargeMcb(&Dcb->Mcb, NonPagedPool);
 
     /* Set up first cluster field depending on FAT type */
     if (TRUE/*FatIsFat32(Vcb)*/)

Modified: trunk/reactos/drivers/filesystems/fastfat_new/fastfat.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/fastfat_new/fastfat.c?rev=48487&r1=48486&r2=48487&view=diff
==============================================================================
--- trunk/reactos/drivers/filesystems/fastfat_new/fastfat.c [iso-8859-1] 
(original)
+++ trunk/reactos/drivers/filesystems/fastfat_new/fastfat.c [iso-8859-1] Sun 
Aug  8 10:43:28 2010
@@ -42,6 +42,7 @@
     RtlZeroMemory(&FatGlobalData, sizeof(FAT_GLOBAL_DATA));
     FatGlobalData.DriverObject = DriverObject;
     FatGlobalData.DiskDeviceObject = DeviceObject;
+    FatGlobalData.SystemProcess = PsGetCurrentProcess();
 
     /* Fill major function handlers */
     DriverObject->MajorFunction[IRP_MJ_CLOSE] = FatClose;
@@ -317,7 +318,7 @@
 
             TypeOfOpen = (*Ccb == NULL ? DirectoryFile : UserDirectoryOpen);
 
-            DPRINT1("Referencing a directory: %wZ\n", 
&(*FcbOrDcb)->FullFileName);
+            DPRINT("Referencing a directory: %wZ\n", 
&(*FcbOrDcb)->FullFileName);
             break;
 
         /* File */
@@ -510,4 +511,17 @@
         return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, 
NormalPagePriority);
 }
 
+BOOLEAN
+NTAPI
+FatIsTopLevelIrp(IN PIRP Irp)
+{
+    if (!IoGetTopLevelIrp())
+    {
+        IoSetTopLevelIrp(Irp);
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
 /* EOF */

Modified: trunk/reactos/drivers/filesystems/fastfat_new/fastfat.h
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/fastfat_new/fastfat.h?rev=48487&r1=48486&r2=48487&view=diff
==============================================================================
--- trunk/reactos/drivers/filesystems/fastfat_new/fastfat.h [iso-8859-1] 
(original)
+++ trunk/reactos/drivers/filesystems/fastfat_new/fastfat.h [iso-8859-1] Sun 
Aug  8 10:43:28 2010
@@ -36,6 +36,22 @@
     ExReleaseResourceLite(&(FatGlobalData.Resource)); \
 }
 
+#define FatIsFastIoPossible(FCB) ((BOOLEAN)                                    
            \
+    (((FCB)->Condition != FcbGood || 
!FsRtlOplockIsFastIoPossible(&(FCB)->Fcb.Oplock)) ?   \
+        FastIoIsNotPossible                                                    
            \
+    :                                                                          
            \
+        (!FsRtlAreThereCurrentFileLocks(&(FCB)->Fcb.Lock) &&                   
            \
+         ((FCB)->OutstandingAsyncWrites == 0) &&                               
            \
+         !FlagOn((FCB)->Vcb->State, VCB_STATE_FLAG_WRITE_PROTECTED) ?          
            \
+            FastIoIsPossible                                                   
            \
+        :                                                                      
            \
+            FastIoIsQuestionable                                               
            \
+        )                                                                      
            \
+    )                                                                          
            \
+)
+
+#define IsFileObjectReadOnly(FO) (!((FO)->WriteAccess | (FO)->DeleteAccess))
+
 NTSYSAPI
 NTSTATUS
 NTAPI
@@ -66,6 +82,12 @@
                   ULONG ByteSize,
                   PBCB *Bcb,
                   PVOID *Buffer);
+
+BOOLEAN
+NTAPI
+FatCheckForDismount(IN PFAT_IRP_CONTEXT IrpContext,
+                    PVCB Vcb,
+                    IN BOOLEAN Force);
 
 /*  -----------------------------------------------------------  dir.c  */
 
@@ -205,6 +227,9 @@
 PVOID FASTCALL
 FatMapUserBuffer(PIRP Irp);
 
+BOOLEAN NTAPI
+FatIsTopLevelIrp(IN PIRP Irp);
+
 /* --------------------------------------------------------- fullfat.c */
 
 FF_T_SINT32
@@ -283,6 +308,10 @@
     IN PVCB Vcb,
     IN PFCB ParentDcb,
     IN FF_FILE *FileHandle);
+
+VOID NTAPI
+FatDeleteFcb(IN PFAT_IRP_CONTEXT IrpContext,
+             IN PFCB Fcb);
 
 IO_STATUS_BLOCK NTAPI
 FatiOpenExistingFcb(IN PFAT_IRP_CONTEXT IrpContext,
@@ -320,6 +349,10 @@
 FatCreateCcb();
 
 VOID NTAPI
+FatDeleteCcb(IN PFAT_IRP_CONTEXT IrpContext,
+             IN PCCB Ccb);
+
+VOID NTAPI
 FatSetFullNameInFcb(PFCB Fcb,
                     PUNICODE_STRING Name);
 

Modified: trunk/reactos/drivers/filesystems/fastfat_new/fat.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/fastfat_new/fat.c?rev=48487&r1=48486&r2=48487&view=diff
==============================================================================
--- trunk/reactos/drivers/filesystems/fastfat_new/fat.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/fastfat_new/fat.c [iso-8859-1] Sun Aug  8 
10:43:28 2010
@@ -201,6 +201,10 @@
         goto FatInitializeVcbCleanup;
     }
 
+    /* Increase internal / residual open counter */
+    InterlockedIncrement((PLONG)&(Vcb->InternalOpenCount));
+    InterlockedIncrement((PLONG)&(Vcb->ResidualOpenCount));
+
     /* Set up notifications */
     FsRtlNotifyInitializeSync(&Vcb->NotifySync);
     InitializeListHead(&Vcb->NotifyList);

Modified: trunk/reactos/drivers/filesystems/fastfat_new/fatstruc.h
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/fastfat_new/fatstruc.h?rev=48487&r1=48486&r2=48487&view=diff
==============================================================================
--- trunk/reactos/drivers/filesystems/fastfat_new/fatstruc.h [iso-8859-1] 
(original)
+++ trunk/reactos/drivers/filesystems/fastfat_new/fatstruc.h [iso-8859-1] Sun 
Aug  8 10:43:28 2010
@@ -14,15 +14,17 @@
 #define FatNodeType(Ptr) (*((PFAT_NODE_TYPE)(Ptr)))
 
 /* Node type codes */
-#define FAT_NTC_VCB      (CSHORT) '00VF'
-#define FAT_NTC_FCB      (CSHORT)   'CF'
-#define FAT_NTC_DCB      (CSHORT)   'DF'
-#define FAT_NTC_ROOT_DCB (CSHORT)  'RFD'
-#define FAT_NTC_CCB      (CSHORT)  'BCC'
+#define FAT_NTC_VCB         (CSHORT) '00VF'
+#define FAT_NTC_FCB         (CSHORT)   'CF'
+#define FAT_NTC_DCB         (CSHORT)   'DF'
+#define FAT_NTC_ROOT_DCB    (CSHORT)  'RFD'
+#define FAT_NTC_CCB         (CSHORT)  'BCC'
+#define FAT_NTC_IRP_CONTEXT (CSHORT)  'PRI'
 
 typedef struct _FAT_GLOBAL_DATA
 {
     ERESOURCE Resource;
+    PEPROCESS SystemProcess;
     PDRIVER_OBJECT DriverObject;
     PDEVICE_OBJECT DiskDeviceObject;
     LIST_ENTRY VcbListHead;
@@ -33,6 +35,7 @@
     CACHE_MANAGER_CALLBACKS CacheMgrCallbacks;
     CACHE_MANAGER_CALLBACKS CacheMgrNoopCallbacks;
     BOOLEAN Win31FileSystem;
+    BOOLEAN ShutdownStarted;
     /* Jan 1, 1980 System Time */
     LARGE_INTEGER DefaultFileTime;
 
@@ -82,6 +85,10 @@
 
 typedef struct _FAT_IRP_CONTEXT
 {
+    /*  Type and size of this record (must be FAT_NTC_IRP_CONTEXT) */
+    FAT_NODE_TYPE NodeTypeCode;
+    CSHORT NodeByteSize;
+
     PIRP Irp;
     PDEVICE_OBJECT DeviceObject;
     UCHAR MajorFunction;
@@ -132,10 +139,15 @@
     PFAT_SETFAT_VALUE_RUN_ROUTINE SetValueRun;
 } FAT_METHODS, *PFAT_METHODS;
 
-#define VCB_STATE_FLAG_LOCKED        0x01
-#define VCB_STATE_FLAG_DIRTY         0x02
-#define VCB_STATE_MOUNTED_DIRTY      0x04
-#define VCB_STATE_CREATE_IN_PROGRESS 0x08
+#define VCB_STATE_FLAG_LOCKED               0x001
+#define VCB_STATE_FLAG_DIRTY                0x002
+#define VCB_STATE_MOUNTED_DIRTY             0x004
+#define VCB_STATE_CREATE_IN_PROGRESS        0x008
+#define VCB_STATE_FLAG_CLOSE_IN_PROGRESS    0x010
+#define VCB_STATE_FLAG_DELETED_FCB          0x020
+#define VCB_STATE_FLAG_DISMOUNT_IN_PROGRESS 0x040
+#define VCB_STATE_FLAG_DEFERRED_FLUSH       0x080
+#define VCB_STATE_FLAG_WRITE_PROTECTED      0x100
 
 typedef enum _VCB_CONDITION
 {
@@ -158,10 +170,11 @@
     ULONG State;
     VCB_CONDITION Condition;
     ERESOURCE Resource;
+    struct _CLOSE_CONTEXT *CloseContext;
 
     /* Direct volume access */
-    ULONG DirectOpenCount;
     SHARE_ACCESS ShareAccess;
+    PFILE_OBJECT FileObjectWithVcbLocked;
 
     /* Notifications support */
     PNOTIFY_SYNC NotifySync;
@@ -186,8 +199,13 @@
     struct _FCB *RootDcb;
 
     /* Counters */
+    ULONG DirectOpenCount;
+    ULONG OpenFileCount;
+    ULONG ReadOnlyCount;
+    ULONG InternalOpenCount;
+    ULONG ResidualOpenCount;
+    ULONG DirectAccessOpenCount;
     ULONG MediaChangeCount;
-    ULONG OpenFileCount;
 
     /* FullFAT integration */
     FF_IOMAN *Ioman;
@@ -252,6 +270,7 @@
 #define FCB_STATE_PAGEFILE          0x04
 #define FCB_STATE_DELAY_CLOSE       0x08
 #define FCB_STATE_TRUNCATE_ON_CLOSE 0x10
+#define FCB_STATE_DELETE_ON_CLOSE   0x20
 
 typedef struct _FCB
 {
@@ -281,8 +300,6 @@
     FCB_CONDITION Condition;
     /* Share access */
     SHARE_ACCESS ShareAccess;
-    /* Mcb mapping Vbo->Lbo */
-    LARGE_MCB Mcb;
     ULONG FirstCluster;
     /* Links into FCB Tree */
     FCB_NAME_LINK ShortName;
@@ -307,6 +324,8 @@
     PKEVENT OutstandingAsyncEvent;
     /* Counters */
     ULONG OpenCount;
+    ULONG UncleanCount;
+    ULONG NonCachedUncleanCount;
     union
     {
         struct
@@ -318,10 +337,11 @@
 
         struct
         {
-            /* A list of all FCBs/DCBs opened under this DCB */
-            LIST_ENTRY ParentDcbList;
+            LIST_ENTRY ParentDcbList; /* A list of all FCBs/DCBs opened under 
this DCB */
+            ULONG DirectoryFileOpenCount; /* Sector-based access to the dir */
+            PFILE_OBJECT DirectoryFile;
             /* Directory data stream (just handy to have it). */
-            PFILE_OBJECT StreamFileObject;
+            //PFILE_OBJECT StreamFileObject;
             /* Bitmap to search for free dirents. */
             RTL_BITMAP FreeBitmap;
             /* Names */
@@ -390,6 +410,17 @@
     EaFile
 } TYPE_OF_OPEN;
 
+typedef struct _CLOSE_CONTEXT
+{
+    LIST_ENTRY GlobalLinks;
+    LIST_ENTRY VcbLinks;
+
+    PVCB Vcb;
+    PFCB Fcb;
+    TYPE_OF_OPEN TypeOfOpen;
+    BOOLEAN Free;
+} CLOSE_CONTEXT, *PCLOSE_CONTEXT;
+
 typedef enum _FILE_TIME_INDEX
 {
     FileCreationTime = 0,
@@ -402,4 +433,8 @@
 #define CCB_SEARCH_PATTERN_LEGAL_8DOT3      0x02
 #define CCB_SEARCH_PATTERN_HAS_WILD_CARD    0x04
 #define CCB_DASD_IO                         0x10
+#define CCB_READ_ONLY                       0x20
+#define CCB_DELETE_ON_CLOSE                 0x40
+#define CCB_COMPLETE_DISMOUNT               0x80
+
 extern FAT_GLOBAL_DATA FatGlobalData;

Modified: trunk/reactos/drivers/filesystems/fastfat_new/fcb.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/fastfat_new/fcb.c?rev=48487&r1=48486&r2=48487&view=diff
==============================================================================
--- trunk/reactos/drivers/filesystems/fastfat_new/fcb.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/fastfat_new/fcb.c [iso-8859-1] Sun Aug  8 
10:43:28 2010
@@ -149,10 +149,72 @@
     Fcb->Header.ValidDataLength.LowPart = FileHandle->Filesize;
     Fcb->FatHandle = FileHandle;
 
+    /* Initialize locks */
+    FsRtlInitializeFileLock(&Fcb->Fcb.Lock, NULL, NULL);
+    FsRtlInitializeOplock(&Fcb->Fcb.Oplock);
+
     /* Set names */
     FatSetFcbNames(IrpContext, Fcb);
 
     return Fcb;
+}
+
+VOID
+NTAPI
+FatDeleteFcb(IN PFAT_IRP_CONTEXT IrpContext,
+             IN PFCB Fcb)
+{
+    DPRINT("FatDeleteFcb %p\n", Fcb);
+
+    if (Fcb->OpenCount != 0)
+    {
+        DPRINT1("Trying to delete FCB with OpenCount %d\n", Fcb->OpenCount);
+        ASSERT(FALSE);
+    }
+
+    if ((Fcb->Header.NodeTypeCode == FAT_NTC_DCB) ||
+        (Fcb->Header.NodeTypeCode == FAT_NTC_ROOT_DCB))
+    {
+        /* Make sure it's a valid deletion */
+        ASSERT(Fcb->Dcb.DirectoryFileOpenCount == 0);
+        ASSERT(IsListEmpty(&Fcb->Dcb.ParentDcbList));
+        ASSERT(Fcb->Dcb.DirectoryFile == NULL);
+    }
+    else
+    {
+        /* Free locks */
+        FsRtlUninitializeFileLock(&Fcb->Fcb.Lock);
+        FsRtlUninitializeOplock(&Fcb->Fcb.Oplock);
+    }
+
+    /* Release any possible filter contexts */
+    FsRtlTeardownPerStreamContexts(&Fcb->Header);
+
+    /* Remove from parents queue */
+    if (Fcb->Header.NodeTypeCode != FAT_NTC_ROOT_DCB)
+    {
+        RemoveEntryList(&(Fcb->ParentDcbLinks));
+    }
+
+    /* Free FullFAT handle */
+    if (Fcb->FatHandle) FF_Close(Fcb->FatHandle);
+
+    /* Remove from the splay table */
+    if (FlagOn(Fcb->State, FCB_STATE_HAS_NAMES))
+        FatRemoveNames(IrpContext, Fcb);
+
+    /* Free file name buffers */
+    if (Fcb->Header.NodeTypeCode != FAT_NTC_ROOT_DCB)
+    {
+        if (Fcb->FullFileName.Buffer)
+            ExFreePool(Fcb->FullFileName.Buffer);
+    }
+
+    if (Fcb->ExactCaseLongName.Buffer)
+        ExFreePool(Fcb->ExactCaseLongName.Buffer);
+
+    /* Free this FCB, finally */
+    ExFreePool(Fcb);
 }
 
 PCCB
@@ -170,6 +232,17 @@
     Ccb->NodeByteSize = sizeof(CCB);
 
     return Ccb;
+}
+
+VOID
+NTAPI
+FatDeleteCcb(IN PFAT_IRP_CONTEXT IrpContext,
+             IN PCCB Ccb)
+{
+    // TODO: Deallocate CCB strings, if any
+
+    /* Free the CCB */
+    ExFreePool(Ccb);
 }
 
 IO_STATUS_BLOCK
@@ -443,8 +516,11 @@
         ClearFlag(Fcb->State, FCB_STATE_DELAY_CLOSE);
 
         /* Increase counters */
+        Fcb->UncleanCount++;
         Fcb->OpenCount++;
         Vcb->OpenFileCount++;
+        if (IsFileObjectReadOnly(FileObject)) Vcb->ReadOnlyCount++;
+        if (FlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING)) 
Fcb->NonCachedUncleanCount++;
 
         // TODO: Handle DeleteOnClose and OpenedAsDos by storing those flags 
in CCB
     }

Modified: trunk/reactos/drivers/filesystems/fastfat_new/volume.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/fastfat_new/volume.c?rev=48487&r1=48486&r2=48487&view=diff
==============================================================================
--- trunk/reactos/drivers/filesystems/fastfat_new/volume.c [iso-8859-1] 
(original)
+++ trunk/reactos/drivers/filesystems/fastfat_new/volume.c [iso-8859-1] Sun Aug 
 8 10:43:28 2010
@@ -8,7 +8,7 @@
 
 /* INCLUDES *****************************************************************/
 
-//#define NDEBUG
+#define NDEBUG
 #include "fastfat.h"
 
 /* FUNCTIONS ****************************************************************/
@@ -77,8 +77,8 @@
     Buffer->SectorsPerAllocationUnit = Vcb->Bpb.SectorsPerCluster;
     Buffer->BytesPerSector = Vcb->Bpb.BytesPerSector;
 
-    DPRINT1("Total %d, free %d, SPC %d, BPS %d\n", Partition->FreeClusterCount,
-        Partition->NumClusters, Vcb->Bpb.SectorsPerCluster, 
Vcb->Bpb.BytesPerSector);
+    DPRINT1("Total %d, free %d, SPC %d, BPS %d\n", Partition->NumClusters,
+        Partition->FreeClusterCount, Vcb->Bpb.SectorsPerCluster, 
Vcb->Bpb.BytesPerSector);
 
     return Status;
 }
@@ -228,4 +228,14 @@
     }
 }
 
+BOOLEAN
+NTAPI
+FatCheckForDismount(IN PFAT_IRP_CONTEXT IrpContext,
+                    PVCB Vcb,
+                    IN BOOLEAN Force)
+{
+    /* We never allow deletion of a volume for now */
+    return FALSE;
+}
+
 /* EOF */


Reply via email to